--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/soundcard.h>
+
+#include "linux_audio.h"
+
+int get_dsp_fd(int sample_rate, int fft_length, int overlap)
+{
+ int fd = open("/dev/dsp", O_RDWR);
+ if (fd == -1) {
+ perror("/dev/dsp");
+ exit(1);
+ }
+
+ ioctl(3, SNDCTL_DSP_RESET, 0);
+
+ int fmt = AFMT_S16_LE; // FIXME
+ ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
+
+ int chan = 1;
+ ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &chan);
+
+ int rate = sample_rate;
+ ioctl(fd, SOUND_PCM_WRITE_RATE, &rate);
+
+ int max_fragments = 2;
+ int frag_shift = ffs(fft_length / overlap) - 1;
+ int fragments = (max_fragments << 16) | frag_shift;
+ ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
+
+ ioctl(3, SNDCTL_DSP_SYNC, 0);
+
+ return fd;
+}
+
+#if 1
+void read_chunk(int fd, short *in, unsigned num_samples)
+{
+ int ret;
+
+ ret = read(fd, in, num_samples * sizeof(short));
+ if (ret == 0) {
+ printf("EOF\n");
+ exit(0);
+ }
+
+ if (ret != int(num_samples * sizeof(short))) {
+ // blah
+ perror("read");
+ exit(1);
+ }
+}
+#else
+// make a pure 440hz sine for testing
+void read_chunk(int fd, short *in, unsigned num_samples)
+{
+ static double theta = 0.0;
+ for (unsigned i = 0; i < num_samples; ++i) {
+ in[i] = 32768.0 * cos(theta);
+ theta += 2.0 * M_PI * 440.0 / double(SAMPLE_RATE);
+ }
+}
+#endif
+
+void write_sine(int dsp_fd, double freq, unsigned num_samples, unsigned sample_rate)
+{
+ static double theta = 0.0;
+ short buf[num_samples];
+
+ for (unsigned i = 0; i < num_samples; ++i) {
+ buf[i] = short(cos(theta) * 16384.0);
+ theta += 2.0 * M_PI * freq / double(sample_rate);
+ }
+
+ write(dsp_fd, buf, num_samples * sizeof(short));
+}
+