diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | common.h | 1 | ||||
| -rw-r--r-- | config.mk | 2 | ||||
| -rw-r--r-- | dogwhistle.c | 76 |
5 files changed, 83 insertions, 1 deletions
@@ -16,5 +16,6 @@ /clock /counter /dice +/dogwhistle /stopwatch /timer @@ -14,6 +14,7 @@ BIN =\ clock\ counter\ dice\ + dogwhistle\ stopwatch\ timer @@ -84,6 +85,9 @@ counter: counter.o large-digits.o large-minus.o dice: dice.o $(CC) -o $@ $@.o $(LDFLAGS) +dogwhistle: dogwhistle.o + $(CC) -o $@ $@.o $(LDFLAGS) + stopwatch: stopwatch.o $(CC) -o $@ $@.o $(LDFLAGS) @@ -9,6 +9,7 @@ #include <sys/random.h> #include <sys/timerfd.h> #include <sys/timex.h> +#include <stdint.h> #include <termios.h> #include "large.h" @@ -7,4 +7,4 @@ CC = cc CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE CFLAGS = -std=c99 -Wall -Wextra -Os -LDFLAGS = -lsimple -s +LDFLAGS = -lsimple -lm -lasound -s 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; +} |
