#include #include #include #define CHECK(f) do { \ int err = (f); \ if (err < 0) { \ fprintf(stderr, "%s failed: %s\n", #f, snd_strerror(err)); \ return 1; \ } \ } while (0); #define PERIOD 240 int main(void) { snd_pcm_t *pin, *pout; snd_pcm_hw_params_t *hw; snd_pcm_sw_params_t *sw; snd_pcm_uframes_t boundary; static short period_buf[2 * PERIOD]; static short output_buf[10 * 2 * PERIOD]; int i, f; snd_pcm_sframes_t frames; CHECK(snd_pcm_open(&pin, "hw:2", SND_PCM_STREAM_CAPTURE, 0)); CHECK(snd_pcm_open(&pout, "hw:2", SND_PCM_STREAM_PLAYBACK, 0)); snd_pcm_hw_params_alloca(&hw); CHECK(snd_pcm_hw_params_any(pin, hw)); CHECK(snd_pcm_hw_params_set_access(pin, hw, SND_PCM_ACCESS_RW_INTERLEAVED)); CHECK(snd_pcm_hw_params_set_format(pin, hw, SND_PCM_FORMAT_S16_LE)); CHECK(snd_pcm_hw_params_set_channels(pin, hw, 2)); CHECK(snd_pcm_hw_params_set_rate(pin, hw, 48000, 0)); CHECK(snd_pcm_hw_params_set_period_size(pin, hw, PERIOD, 0)); CHECK(snd_pcm_hw_params_set_buffer_size(pin, hw, 16 * PERIOD)); CHECK(snd_pcm_hw_params(pin, hw)); CHECK(snd_pcm_hw_params_any(pout, hw)); CHECK(snd_pcm_hw_params_set_access(pout, hw, SND_PCM_ACCESS_RW_INTERLEAVED)); CHECK(snd_pcm_hw_params_set_format(pout, hw, SND_PCM_FORMAT_S16_LE)); CHECK(snd_pcm_hw_params_set_channels(pout, hw, 2)); CHECK(snd_pcm_hw_params_set_rate(pout, hw, 48000, 0)); CHECK(snd_pcm_hw_params_set_period_size(pout, hw, PERIOD, 0)); CHECK(snd_pcm_hw_params_set_buffer_size(pout, hw, 2 * PERIOD)); CHECK(snd_pcm_hw_params(pout, hw)); snd_pcm_sw_params_alloca(&sw); CHECK(snd_pcm_sw_params_current(pin, sw)); CHECK(snd_pcm_sw_params_get_boundary(sw, &boundary)); CHECK(snd_pcm_sw_params_set_start_threshold(pin, sw, boundary)); CHECK(snd_pcm_sw_params(pin, sw)); CHECK(snd_pcm_sw_params_current(pout, sw)); CHECK(snd_pcm_sw_params_get_boundary(sw, &boundary)); CHECK(snd_pcm_sw_params_set_avail_min(pout, sw, PERIOD)); CHECK(snd_pcm_sw_params_set_start_threshold(pout, sw, boundary)); CHECK(snd_pcm_sw_params(pout, sw)); CHECK(snd_pcm_link(pout, pin)); CHECK(snd_pcm_writei(pout, period_buf, PERIOD)); CHECK(snd_pcm_writei(pout, period_buf, PERIOD)); for (i = 0; i < PERIOD; ++i) period_buf[2 * i] = sin(i * 4 * 3.14 / PERIOD) * 32767.0; CHECK(snd_pcm_start(pout)); CHECK(snd_pcm_writei(pout, period_buf, PERIOD)); for (i = 0; i < 10; ++i) { frames = snd_pcm_readi(pin, period_buf, PERIOD); CHECK(frames); if (frames != PERIOD) { fprintf(stderr, "short read: %lx\n", frames); return 1; } memcpy(output_buf + i * 2 * PERIOD, period_buf, sizeof(period_buf)); for (f = 0; f < PERIOD * 2; ++f) period_buf[f] /= 2; CHECK(snd_pcm_writei(pout, period_buf, PERIOD)); } fwrite(output_buf, 1, sizeof(output_buf), stdout); return 0; }