/* See LICENSE file for copyright and license details. */ #include "common.h" #include #include /* TODO add support for 12, 14, 18 and 20, 22 kHz in addition to 16 kHz as well as custom frequencies */ /* TODO add support for selecting output device and backend */ /* TODO add support for selecting volume */ /* TODO add support for pausing and exiting */ #define UTYPE uint32_t #define SMIN INT32_MIN #define SMAX INT32_MAX #define FORMAT SND_PCM_FORMAT_U32 #define SAMPLE_RATE 52000 /* Hz */ #define LATENCY 100000 /* µs */ USAGE(""); int main(int argc, char *argv[]) { UTYPE *buffer; snd_pcm_uframes_t i, buflen = SAMPLE_RATE; snd_pcm_sframes_t n; snd_pcm_t *sound_handle = NULL; unsigned long int freq = 16000; double volume = (double)0.1f, imul, omul; int r; NOFLAGS(argc); /* Set up audio */ r = snd_pcm_open(&sound_handle, "default", SND_PCM_STREAM_PLAYBACK, 0); if (r < 0) eprintf("snd_pcm_open: %s\n", snd_strerror(r)); if (!sound_handle) eprintf("snd_pcm_open:"); /* Configure audio */ r = snd_pcm_set_params(sound_handle, FORMAT, SND_PCM_ACCESS_RW_INTERLEAVED, 1 /* channels */, SAMPLE_RATE, 1 /* allow resampling? */, LATENCY); if (r < 0) eprintf("snd_pcm_set_params: %s\n", snd_strerror(r)); /* Generate tone */ buffer = emallocn((size_t)buflen, sizeof(*buffer), 0); omul = volume * SMAX * 2; imul = 2 * (double)freq / (double)SAMPLE_RATE; #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunsuffixed-float-constants" #endif imul *= M_PI; #ifdef __GNUC__ # pragma GCC diagnostic pop #endif for (i = 0; i < buflen; i++) buffer[i] = (UTYPE)(sin(imul * (double)i) * omul - SMIN); /* Play tone */ for (;;) { n = snd_pcm_writei(sound_handle, buffer, buflen); if (n < 0) n = snd_pcm_recover(sound_handle, (int)n, 0 /* do not print error reason? */); if (n < 0) eprintf("snd_pcm_writei: %s\n", snd_strerror((int)n)); if (n > 0 && (snd_pcm_uframes_t)n < buflen) eprintf("short write from snd_pcm_writei\n"); } snd_pcm_close(sound_handle); return 0; }