ref: 1631ca601fc896c41dde746e34d18654a6a70d73
dir: /kern/devaudio-alsa.c/
/* * ALSA */ #include <alsa/asoundlib.h> #include "u.h" #include "lib.h" #include "dat.h" #include "fns.h" #include "error.h" #include "devaudio.h" enum { Channels = 2, Rate = 44100, Bits = 16, }; static snd_pcm_t *playback; static snd_pcm_t *capture; static int speed = Rate; /* maybe this should return -1 instead of sysfatal */ void audiodevopen(void) { if(snd_pcm_open(&playback, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) error("snd_pcm_open playback"); if(snd_pcm_set_params(playback, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, speed, 1, 500000) < 0) error("snd_pcm_set_params playback"); if(snd_pcm_prepare(playback) < 0) error("snd_pcm_prepare playback"); if(snd_pcm_open(&capture, "default", SND_PCM_STREAM_CAPTURE, 0) < 0) error("snd_pcm_open capture"); if(snd_pcm_set_params(capture, SND_PCM_FORMAT_S16_LE, SND_PCM_ACCESS_RW_INTERLEAVED, 2, speed, 1, 500000) < 0) error("snd_pcm_set_params capture"); if(snd_pcm_prepare(capture) < 0) error("snd_pcm_prepare capture"); } void audiodevclose(void) { snd_pcm_drain(playback); snd_pcm_close(playback); snd_pcm_close(capture); } void audiodevsetvol(int what, int left, int right) { if(what == Vspeed){ speed = left; return; } } void audiodevgetvol(int what, int *left, int *right) { if(what == Vspeed){ *left = *right = speed; return; } *left = *right = 100; } int audiodevwrite(void *v, int n) { snd_pcm_sframes_t frames; int tot, m, fr; for(tot = 0; tot < n; tot += m){ fr = (n-tot)/4; do { frames = snd_pcm_writei(playback, v+tot, fr); if (frames < 0 && snd_pcm_recover(playback, frames, 0) == 0) frames = fr; if (frames < 0) break; } while(frames != fr); if (frames < 0) error("snd_pcm_writei"); m = frames*4; } return tot; } int audiodevread(void *v, int n) { snd_pcm_sframes_t frames; do { frames = snd_pcm_readi(capture, v, n/4); } while(frames == -EAGAIN); if (frames < 0 && snd_pcm_recover(capture, frames, 0) == 0) frames = n/4; if (frames < 0) error("snd_pcm_readi"); return frames*4; }