/* 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 */ /* TODO prefer loudspeakers over headphones */ /* TODO use bus to listen for incoming phone calls and pause when arriving */ #define UTYPE uint32_t #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, wavelen; snd_pcm_sframes_t n; snd_pcm_t *sound_handle = NULL; double 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 */ buflen = wavelen = (snd_pcm_uframes_t)((double)SAMPLE_RATE / freq); if ((snd_pcm_uframes_t)freq > 1) buflen *= (snd_pcm_uframes_t)freq; buffer = emallocn((size_t)buflen, sizeof(*buffer), 0); omul = volume * SMAX * 2; #ifdef __GNUC__ # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunsuffixed-float-constants" #endif imul = 2 * M_PI * freq / (double)SAMPLE_RATE; #ifdef __GNUC__ # pragma GCC diagnostic pop #endif for (i = 0; i < wavelen; i++) buffer[i] = (UTYPE)(sin(imul * (double)i) * omul + SMAX); for (i = wavelen; i < buflen; i += wavelen) memcpy(&buffer[i], &buffer[0], wavelen * sizeof(UTYPE)); /* 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; }