/* * This extra small demo sends silence to your speakers if all your ALSA plugins support rewinds properly. */ #include #include #include const char* device = "hw:2"; const int channels = 2; const snd_pcm_sframes_t period_size = 1024; const int periods = 4; const int rate = 48000; const int freq = 440; int main(int argc, char* argv[]) { int err; unsigned int c, i, s, t; short *wave; short *silence; unsigned int half_period = rate / 2 / freq; snd_pcm_t *handle; snd_output_t *out = NULL; snd_pcm_hw_params_t *params; snd_pcm_sw_params_t *swparams; snd_pcm_hw_params_alloca(¶ms); snd_pcm_sw_params_alloca(&swparams); t = 0; snd_output_stdio_attach(&out, stderr, 0); wave = calloc(period_size, sizeof(short) * channels); silence = calloc(period_size * periods, sizeof(short) * channels); if ((err = snd_pcm_open(&handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) { fprintf(stderr, "Playback open error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_hw_params_any(handle, params) < 0 || snd_pcm_hw_params_set_rate_resample(handle, params, 1) < 0 || snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0 || snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16) < 0 || snd_pcm_hw_params_set_channels(handle, params, channels) < 0 || snd_pcm_hw_params_set_rate(handle, params, rate, 0) < 0 || snd_pcm_hw_params_set_period_size(handle, params, period_size, 0) < 0 || snd_pcm_hw_params_set_periods(handle, params, periods, 0) < 0 || snd_pcm_hw_params(handle, params) < 0; if (err) { fprintf(stderr, "Playback hwparams error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } err = snd_pcm_sw_params_current(handle, swparams) < 0 || snd_pcm_sw_params_set_start_threshold(handle, swparams, period_size) < 0 || snd_pcm_sw_params_set_avail_min(handle, swparams, period_size) < 0 || snd_pcm_sw_params(handle, swparams) < 0; if (err) { fprintf(stderr, "Playback swparams error: %s\n", snd_strerror(err)); exit(EXIT_FAILURE); } snd_pcm_dump(handle, out); fprintf(stderr, "Playing silence\n"); fflush(stderr); memset(silence, 0, period_size * sizeof(short) * channels); for (i = 0; i < periods; i++) { err = snd_pcm_writei(handle, silence, period_size); if (err != period_size) { fprintf(stderr, "Playback incomplete write or error: %d\n", err); exit(EXIT_FAILURE); } } fprintf(stderr, "Playing tricks\n"); for (i = 0; i < 100; i++) { snd_pcm_sframes_t towrite; err = snd_pcm_rewindable(handle); if (err < period_size) { fprintf(stderr, "Cannot rewind, got %d\n", err); exit(EXIT_FAILURE); } towrite = snd_pcm_rewind(handle, period_size); if (towrite < period_size) { fprintf(stderr, "Rewind attempt failed or didn't yield as much as we want, got %d\n", err); exit(EXIT_FAILURE); } fprintf(stderr, "Rewind attempt forgot %d samples out of %d requested\n", (int)towrite, (int)period_size); err = snd_pcm_writei(handle, silence, towrite); if (err != towrite) { fprintf(stderr, "Writing silence: incomplete write or error: %d\n", err); exit(EXIT_FAILURE); } for (s = 0; s < period_size; s++) { short val = (t % (2 * half_period) >= half_period) ? 30000 : -30000; for (c = 0; c < channels; c++) wave[c + s * channels] = val; t++; } err = snd_pcm_writei(handle, wave, period_size); if (err != period_size) { fprintf(stderr, "Writing wave: incomplete write or error: %d\n", err); exit(EXIT_FAILURE); } } snd_pcm_drop(handle); snd_pcm_close(handle); free(wave); free(silence); return 0; }