]> git.sesse.net Git - pitch/blob - linux_audio.cpp
Make an SDL/OpenGL-frontend; might be more intuitive to read, although I'm not sure...
[pitch] / linux_audio.cpp
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <math.h>
5 #include <unistd.h>
6 #include <fcntl.h>
7 #include <sys/ioctl.h>
8 #include <linux/soundcard.h>
9
10 #include "linux_audio.h"
11
12 int get_dsp_fd(int sample_rate, int fft_length, int overlap)
13 {
14         int fd = open("/dev/dsp", O_RDWR);
15         if (fd == -1) {
16                 perror("/dev/dsp");
17                 exit(1);
18         }
19         
20         ioctl(3, SNDCTL_DSP_RESET, 0);
21         
22         int fmt = AFMT_S16_LE;   // FIXME
23         ioctl(fd, SNDCTL_DSP_SETFMT, &fmt);
24
25         int chan = 1;
26         ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &chan);
27         
28         int rate = sample_rate;
29         ioctl(fd, SOUND_PCM_WRITE_RATE, &rate);
30
31         int max_fragments = 2;
32         int frag_shift = ffs(fft_length / overlap) - 1;
33         int fragments = (max_fragments << 16) | frag_shift;
34         ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &fragments);
35         
36         ioctl(3, SNDCTL_DSP_SYNC, 0);
37         
38         return fd;
39 }
40
41 #if 1
42 void read_chunk(int fd, short *in, unsigned num_samples)
43 {
44         int ret;
45
46         ret = read(fd, in, num_samples * sizeof(short));
47         if (ret == 0) {
48                 printf("EOF\n");
49                 exit(0);
50         }
51
52         if (ret != int(num_samples * sizeof(short))) {
53                 // blah
54                 perror("read");
55                 exit(1);
56         }
57 }
58 #else
59 // make a pure 440hz sine for testing
60 void read_chunk(int fd, short *in, unsigned num_samples)
61 {
62         static double theta = 0.0;
63         for (unsigned i = 0; i < num_samples; ++i) {
64                 in[i] = 32768.0 * cos(theta);
65                 theta += 2.0 * M_PI * 440.0 / double(SAMPLE_RATE);
66         }
67 }
68 #endif
69
70 void write_sine(int dsp_fd, double freq, unsigned num_samples, unsigned sample_rate) 
71 {
72         static double theta = 0.0;
73         short buf[num_samples];
74         
75         for (unsigned i = 0; i < num_samples; ++i) {
76                 buf[i] = short(cos(theta) * 16384.0);
77                 theta += 2.0 * M_PI * freq / double(sample_rate);
78         }
79
80         write(dsp_fd, buf, num_samples * sizeof(short));
81 }
82