diff options
Diffstat (limited to 'dogwhistle.c')
| -rw-r--r-- | dogwhistle.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/dogwhistle.c b/dogwhistle.c new file mode 100644 index 0000000..2d48b82 --- /dev/null +++ b/dogwhistle.c @@ -0,0 +1,76 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" +#include <alsa/asoundlib.h> +#include <math.h> + +/* 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; +} |
