Решил написать небольшую прогу на Харе для вывода синусоиды 440Гц. Чтобы все было как можно проще, я использовал фиксированный период времени в 10 секунд. Вот код:

use fs;
use fmt;
use io;
use os;
use math;
//use unix;
use unix::signal;
//use sndctl;
use rt;

// #include </usr/include/linux/soundcard.h>
// tested on Debian Stable
// manual for dsp:
// https://docs.oracle.com/cd/E88353_01/html/E37851/dsp-4i.html
def SNDCTL_DSP_GETBLKSIZE       = 3221508100u64;
def SNDCTL_DSP_SETFRAGMENT      = 3221508106u64;
def SNDCTL_DSP_GETOSPACE        = 2148552716u64;
def SNDCTL_DSP_SPEED            = 3221508098u64;
def SNDCTL_DSP_GETFMTS          = 2147766283u64;
def SNDCTL_DSP_SETFMT           = 3221508101u64;

def AFMT_MU_LAW = 1;
def AFMT_A_LAW  = 2;
def AFMT_U8     = 8;
def AFMT_S16_LE = 16;
def AFMT_S16_BE = 32;
def AFMT_S16_NE = 16;
def AFMT_U16_LE = 128;

export fn main() void = {
        const fw : f64 = 440.0; // frequency of sine wave
        const pi : f64 = 3.14159;
        
        defer fmt::printf("Bye\n")!;
        fmt::printf("Type Ctrl-d to quit\n")!;

        let fd  = os::open("/dev/dsp", fs::flags::WRONLY, 0);
        if (fd is fs::error) {
                fmt::printf("Couldn't open OSS device\n")!;
                os::exit(1);
        };
        let fd = fd:io::file;
        defer io::close(fd)!;

        let frag_size : int = 1;
        rt::ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &frag_size)!;
        fmt::printf("frag size = {}\n", frag_size)!;

        const arg = 10; // double-buffering
        rt::ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &arg)!;

        // set sampling frequency
        let fs : int = 22000; // sampling frequency
        fmt::printf("Requested speed: {}, ", fs)!;
        rt::ioctl(fd, SNDCTL_DSP_SPEED, &fs)!;
        fmt::printf("actual speed: {}\n", fs)!;

        // ensure we can set the right format
        let fmt : int = 0;
        rt::ioctl(fd, SNDCTL_DSP_GETFMTS, &fmt)!; // get a mask of the format types available
        fmt::printf("Formats supported: {}\n", fmt)!;
        let fmt_type : int = AFMT_U16_LE; // this is the type we want to use
        assert((fmt & fmt_type) != 0); // make sure it is available
        //fmt = fmt_type; // we want to use this format
        rt::ioctl(fd, SNDCTL_DSP_SETFMT, &fmt_type)!; // set it

        const dt : f64 = 2.0 * pi * fw / fs:f64; 
        let t : f64 = 0.0; // time

        const els : size  = 512;
        let buf : [1024]u8 = [0...]; // low and high bytes

        const secs : size = 10;
        const rounds =  secs * fs:size /els; // number of rounds to last given number of seconds
        for (let i = 0z; i < rounds ; i+=1) {
                for (let j = 0z; j < els; j+=1) {
                        const v : f64 = (math::sinf64(t) +1.0) * 4000.0; // fit it inside a u16
                        const v : u16 = v:u16;
                        buf[j*2] = v:u8;
                        buf[j*2+1] = (v/256):u8;
                        t += dt;
                        if (t > 2.0*pi) { t -= 2.0 * pi; };
                };
                io::write(fd, buf:[]u8)!;

        };
};