Решил написать небольшую прогу на Харе для вывода синусоиды 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)!; }; };