#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/soundcard.h>
-
+#include <alsa/asoundlib.h>
#include "linux_audio.h"
-int get_dsp_fd(int sample_rate, int fft_length, int overlap)
+snd_pcm_t *get_dsp_handle(int sample_rate)
{
- int fd = open("/dev/dsp", O_RDWR);
- if (fd == -1) {
- perror("/dev/dsp");
+ int err;
+ snd_pcm_t *handle;
+ snd_pcm_hw_params_t *hw_params;
+
+ if ((err = snd_pcm_open(&handle, "plughw:0,0", SND_PCM_STREAM_CAPTURE, 0)) < 0) {
+ fprintf(stderr, "cannot open audio device plughw:0,0: %s\n",
+ snd_strerror(err));
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);
+ if ((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {
+ fprintf(stderr, "cannot allocate hardware parameter structure: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
- 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 ((err = snd_pcm_hw_params_any(handle, hw_params)) < 0) {
+ fprintf(stderr, "cannot initialize hardware parameter structure: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_access(handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
+ fprintf(stderr, "cannot set access type: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_format(handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) { // FIXME
+ fprintf(stderr, "cannot set sample format: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_rate(handle, hw_params, sample_rate, 0)) < 0) {
+ fprintf(stderr, "cannot set sample rate: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params_set_channels(handle, hw_params, 1)) < 0) {
+ fprintf(stderr, "cannot set channel count: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ if ((err = snd_pcm_hw_params(handle, hw_params)) < 0) {
+ fprintf(stderr, "cannot set parameters: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ snd_pcm_hw_params_free(hw_params);
+
+ if ((err = snd_pcm_prepare(handle)) < 0) {
+ fprintf(stderr, "cannot prepare audio interface for use: %s\n",
+ snd_strerror(err));
+ exit(1);
+ }
+
+ return handle;
}
#if 1
-void read_chunk(int fd, short *in, unsigned num_samples)
+void read_chunk(snd_pcm_t *handle, short *in, unsigned num_samples)
{
int ret;
+ int samples_left = num_samples;
- 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);
+ while (samples_left > 0) {
+ ret = snd_pcm_readi(handle, in, samples_left);
+ if (ret == 0) {
+ printf("EOF\n");
+ exit(0);
+ }
+ if (ret == -1) {
+ perror("read");
+ exit(1);
+ }
+ in += ret;
+ samples_left -= ret;
}
}
#else
// make a pure 440hz sine for testing
-void read_chunk(int fd, short *in, unsigned num_samples)
+void read_chunk(snd_pcm_t *handle, short *in, unsigned num_samples)
{
static double theta = 0.0;
for (unsigned i = 0; i < num_samples; ++i) {