1*288bf522SAndroid Build Coastguard Worker /* Copyright (C) 2008 The Android Open Source Project
2*288bf522SAndroid Build Coastguard Worker */
3*288bf522SAndroid Build Coastguard Worker
4*288bf522SAndroid Build Coastguard Worker #include <stdio.h>
5*288bf522SAndroid Build Coastguard Worker #include <stdlib.h>
6*288bf522SAndroid Build Coastguard Worker #include <fcntl.h>
7*288bf522SAndroid Build Coastguard Worker #include <stdint.h>
8*288bf522SAndroid Build Coastguard Worker #include <string.h>
9*288bf522SAndroid Build Coastguard Worker #include <sys/mman.h>
10*288bf522SAndroid Build Coastguard Worker #include <sys/ioctl.h>
11*288bf522SAndroid Build Coastguard Worker #include <unistd.h>
12*288bf522SAndroid Build Coastguard Worker
13*288bf522SAndroid Build Coastguard Worker #include <linux/ioctl.h>
14*288bf522SAndroid Build Coastguard Worker
15*288bf522SAndroid Build Coastguard Worker #define AUDIO_IOCTL_MAGIC 'a'
16*288bf522SAndroid Build Coastguard Worker
17*288bf522SAndroid Build Coastguard Worker #define AUDIO_START _IOW(AUDIO_IOCTL_MAGIC, 0, unsigned)
18*288bf522SAndroid Build Coastguard Worker #define AUDIO_STOP _IOW(AUDIO_IOCTL_MAGIC, 1, unsigned)
19*288bf522SAndroid Build Coastguard Worker #define AUDIO_FLUSH _IOW(AUDIO_IOCTL_MAGIC, 2, unsigned)
20*288bf522SAndroid Build Coastguard Worker #define AUDIO_GET_CONFIG _IOR(AUDIO_IOCTL_MAGIC, 3, unsigned)
21*288bf522SAndroid Build Coastguard Worker #define AUDIO_SET_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 4, unsigned)
22*288bf522SAndroid Build Coastguard Worker #define AUDIO_GET_STATS _IOR(AUDIO_IOCTL_MAGIC, 5, unsigned)
23*288bf522SAndroid Build Coastguard Worker
24*288bf522SAndroid Build Coastguard Worker struct msm_audio_config {
25*288bf522SAndroid Build Coastguard Worker uint32_t buffer_size;
26*288bf522SAndroid Build Coastguard Worker uint32_t buffer_count;
27*288bf522SAndroid Build Coastguard Worker uint32_t channel_count;
28*288bf522SAndroid Build Coastguard Worker uint32_t sample_rate;
29*288bf522SAndroid Build Coastguard Worker uint32_t codec_type;
30*288bf522SAndroid Build Coastguard Worker uint32_t unused[3];
31*288bf522SAndroid Build Coastguard Worker };
32*288bf522SAndroid Build Coastguard Worker
33*288bf522SAndroid Build Coastguard Worker struct msm_audio_stats {
34*288bf522SAndroid Build Coastguard Worker uint32_t out_bytes;
35*288bf522SAndroid Build Coastguard Worker uint32_t unused[3];
36*288bf522SAndroid Build Coastguard Worker };
37*288bf522SAndroid Build Coastguard Worker
pcm_play(unsigned rate,unsigned channels,int (* fill)(void * buf,unsigned sz,void * cookie),void * cookie)38*288bf522SAndroid Build Coastguard Worker int pcm_play(unsigned rate, unsigned channels,
39*288bf522SAndroid Build Coastguard Worker int (*fill)(void *buf, unsigned sz, void *cookie),
40*288bf522SAndroid Build Coastguard Worker void *cookie)
41*288bf522SAndroid Build Coastguard Worker {
42*288bf522SAndroid Build Coastguard Worker struct msm_audio_config config;
43*288bf522SAndroid Build Coastguard Worker #if 0
44*288bf522SAndroid Build Coastguard Worker struct msm_audio_stats stats;
45*288bf522SAndroid Build Coastguard Worker #endif
46*288bf522SAndroid Build Coastguard Worker unsigned sz, n;
47*288bf522SAndroid Build Coastguard Worker char buf[8192];
48*288bf522SAndroid Build Coastguard Worker int afd;
49*288bf522SAndroid Build Coastguard Worker
50*288bf522SAndroid Build Coastguard Worker afd = open("/dev/msm_pcm_out", O_RDWR);
51*288bf522SAndroid Build Coastguard Worker if (afd < 0) {
52*288bf522SAndroid Build Coastguard Worker perror("pcm_play: cannot open audio device");
53*288bf522SAndroid Build Coastguard Worker return -1;
54*288bf522SAndroid Build Coastguard Worker }
55*288bf522SAndroid Build Coastguard Worker
56*288bf522SAndroid Build Coastguard Worker if(ioctl(afd, AUDIO_GET_CONFIG, &config)) {
57*288bf522SAndroid Build Coastguard Worker perror("could not get config");
58*288bf522SAndroid Build Coastguard Worker return -1;
59*288bf522SAndroid Build Coastguard Worker }
60*288bf522SAndroid Build Coastguard Worker
61*288bf522SAndroid Build Coastguard Worker config.channel_count = channels;
62*288bf522SAndroid Build Coastguard Worker config.sample_rate = rate;
63*288bf522SAndroid Build Coastguard Worker if (ioctl(afd, AUDIO_SET_CONFIG, &config)) {
64*288bf522SAndroid Build Coastguard Worker perror("could not set config");
65*288bf522SAndroid Build Coastguard Worker return -1;
66*288bf522SAndroid Build Coastguard Worker }
67*288bf522SAndroid Build Coastguard Worker sz = config.buffer_size;
68*288bf522SAndroid Build Coastguard Worker if (sz > sizeof(buf)) {
69*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"too big\n");
70*288bf522SAndroid Build Coastguard Worker return -1;
71*288bf522SAndroid Build Coastguard Worker }
72*288bf522SAndroid Build Coastguard Worker
73*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"prefill\n");
74*288bf522SAndroid Build Coastguard Worker for (n = 0; n < config.buffer_count; n++) {
75*288bf522SAndroid Build Coastguard Worker if (fill(buf, sz, cookie))
76*288bf522SAndroid Build Coastguard Worker break;
77*288bf522SAndroid Build Coastguard Worker if (write(afd, buf, sz) != (ssize_t) sz)
78*288bf522SAndroid Build Coastguard Worker break;
79*288bf522SAndroid Build Coastguard Worker }
80*288bf522SAndroid Build Coastguard Worker
81*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"start\n");
82*288bf522SAndroid Build Coastguard Worker ioctl(afd, AUDIO_START, 0);
83*288bf522SAndroid Build Coastguard Worker
84*288bf522SAndroid Build Coastguard Worker for (;;) {
85*288bf522SAndroid Build Coastguard Worker #if 0
86*288bf522SAndroid Build Coastguard Worker if (ioctl(afd, AUDIO_GET_STATS, &stats) == 0)
87*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"%10d\n", stats.out_bytes);
88*288bf522SAndroid Build Coastguard Worker #endif
89*288bf522SAndroid Build Coastguard Worker if (fill(buf, sz, cookie))
90*288bf522SAndroid Build Coastguard Worker break;
91*288bf522SAndroid Build Coastguard Worker if (write(afd, buf, sz) != (ssize_t) sz)
92*288bf522SAndroid Build Coastguard Worker break;
93*288bf522SAndroid Build Coastguard Worker }
94*288bf522SAndroid Build Coastguard Worker
95*288bf522SAndroid Build Coastguard Worker close(afd);
96*288bf522SAndroid Build Coastguard Worker return 0;
97*288bf522SAndroid Build Coastguard Worker }
98*288bf522SAndroid Build Coastguard Worker
99*288bf522SAndroid Build Coastguard Worker /* http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
100*288bf522SAndroid Build Coastguard Worker
101*288bf522SAndroid Build Coastguard Worker #define ID_RIFF 0x46464952
102*288bf522SAndroid Build Coastguard Worker #define ID_WAVE 0x45564157
103*288bf522SAndroid Build Coastguard Worker #define ID_FMT 0x20746d66
104*288bf522SAndroid Build Coastguard Worker #define ID_DATA 0x61746164
105*288bf522SAndroid Build Coastguard Worker
106*288bf522SAndroid Build Coastguard Worker #define FORMAT_PCM 1
107*288bf522SAndroid Build Coastguard Worker
108*288bf522SAndroid Build Coastguard Worker struct wav_header {
109*288bf522SAndroid Build Coastguard Worker uint32_t riff_id;
110*288bf522SAndroid Build Coastguard Worker uint32_t riff_sz;
111*288bf522SAndroid Build Coastguard Worker uint32_t riff_fmt;
112*288bf522SAndroid Build Coastguard Worker uint32_t fmt_id;
113*288bf522SAndroid Build Coastguard Worker uint32_t fmt_sz;
114*288bf522SAndroid Build Coastguard Worker uint16_t audio_format;
115*288bf522SAndroid Build Coastguard Worker uint16_t num_channels;
116*288bf522SAndroid Build Coastguard Worker uint32_t sample_rate;
117*288bf522SAndroid Build Coastguard Worker uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */
118*288bf522SAndroid Build Coastguard Worker uint16_t block_align; /* num_channels * bps / 8 */
119*288bf522SAndroid Build Coastguard Worker uint16_t bits_per_sample;
120*288bf522SAndroid Build Coastguard Worker uint32_t data_id;
121*288bf522SAndroid Build Coastguard Worker uint32_t data_sz;
122*288bf522SAndroid Build Coastguard Worker };
123*288bf522SAndroid Build Coastguard Worker
124*288bf522SAndroid Build Coastguard Worker
125*288bf522SAndroid Build Coastguard Worker static char *next;
126*288bf522SAndroid Build Coastguard Worker static unsigned avail;
127*288bf522SAndroid Build Coastguard Worker
fill_buffer(void * buf,unsigned sz,void * cookie)128*288bf522SAndroid Build Coastguard Worker int fill_buffer(void *buf, unsigned sz, void *cookie)
129*288bf522SAndroid Build Coastguard Worker {
130*288bf522SAndroid Build Coastguard Worker if (sz > avail)
131*288bf522SAndroid Build Coastguard Worker return -1;
132*288bf522SAndroid Build Coastguard Worker memcpy(buf, next, sz);
133*288bf522SAndroid Build Coastguard Worker next += sz;
134*288bf522SAndroid Build Coastguard Worker avail -= sz;
135*288bf522SAndroid Build Coastguard Worker return 0;
136*288bf522SAndroid Build Coastguard Worker }
137*288bf522SAndroid Build Coastguard Worker
play_file(unsigned rate,unsigned channels,int fd,unsigned count)138*288bf522SAndroid Build Coastguard Worker void play_file(unsigned rate, unsigned channels,
139*288bf522SAndroid Build Coastguard Worker int fd, unsigned count)
140*288bf522SAndroid Build Coastguard Worker {
141*288bf522SAndroid Build Coastguard Worker next = malloc(count);
142*288bf522SAndroid Build Coastguard Worker if (!next) {
143*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"could not allocate %d bytes\n", count);
144*288bf522SAndroid Build Coastguard Worker return;
145*288bf522SAndroid Build Coastguard Worker }
146*288bf522SAndroid Build Coastguard Worker if (read(fd, next, count) != (ssize_t) count) {
147*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"could not read %d bytes\n", count);
148*288bf522SAndroid Build Coastguard Worker return;
149*288bf522SAndroid Build Coastguard Worker }
150*288bf522SAndroid Build Coastguard Worker avail = count;
151*288bf522SAndroid Build Coastguard Worker pcm_play(rate, channels, fill_buffer, 0);
152*288bf522SAndroid Build Coastguard Worker }
153*288bf522SAndroid Build Coastguard Worker
wav_play(const char * fn)154*288bf522SAndroid Build Coastguard Worker int wav_play(const char *fn)
155*288bf522SAndroid Build Coastguard Worker {
156*288bf522SAndroid Build Coastguard Worker struct wav_header hdr;
157*288bf522SAndroid Build Coastguard Worker int fd;
158*288bf522SAndroid Build Coastguard Worker fd = open(fn, O_RDONLY);
159*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
160*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "playwav: cannot open '%s'\n", fn);
161*288bf522SAndroid Build Coastguard Worker return -1;
162*288bf522SAndroid Build Coastguard Worker }
163*288bf522SAndroid Build Coastguard Worker if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
164*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "playwav: cannot read header\n");
165*288bf522SAndroid Build Coastguard Worker return -1;
166*288bf522SAndroid Build Coastguard Worker }
167*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"playwav: %d ch, %d hz, %d bit, %s\n",
168*288bf522SAndroid Build Coastguard Worker hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
169*288bf522SAndroid Build Coastguard Worker hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
170*288bf522SAndroid Build Coastguard Worker
171*288bf522SAndroid Build Coastguard Worker if ((hdr.riff_id != ID_RIFF) ||
172*288bf522SAndroid Build Coastguard Worker (hdr.riff_fmt != ID_WAVE) ||
173*288bf522SAndroid Build Coastguard Worker (hdr.fmt_id != ID_FMT)) {
174*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "playwav: '%s' is not a riff/wave file\n", fn);
175*288bf522SAndroid Build Coastguard Worker return -1;
176*288bf522SAndroid Build Coastguard Worker }
177*288bf522SAndroid Build Coastguard Worker if ((hdr.audio_format != FORMAT_PCM) ||
178*288bf522SAndroid Build Coastguard Worker (hdr.fmt_sz != 16)) {
179*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "playwav: '%s' is not pcm format\n", fn);
180*288bf522SAndroid Build Coastguard Worker return -1;
181*288bf522SAndroid Build Coastguard Worker }
182*288bf522SAndroid Build Coastguard Worker if (hdr.bits_per_sample != 16) {
183*288bf522SAndroid Build Coastguard Worker fprintf(stderr, "playwav: '%s' is not 16bit per sample\n", fn);
184*288bf522SAndroid Build Coastguard Worker return -1;
185*288bf522SAndroid Build Coastguard Worker }
186*288bf522SAndroid Build Coastguard Worker
187*288bf522SAndroid Build Coastguard Worker play_file(hdr.sample_rate, hdr.num_channels,
188*288bf522SAndroid Build Coastguard Worker fd, hdr.data_sz);
189*288bf522SAndroid Build Coastguard Worker
190*288bf522SAndroid Build Coastguard Worker return 0;
191*288bf522SAndroid Build Coastguard Worker }
192*288bf522SAndroid Build Coastguard Worker
wav_rec(const char * fn,unsigned channels,unsigned rate)193*288bf522SAndroid Build Coastguard Worker int wav_rec(const char *fn, unsigned channels, unsigned rate)
194*288bf522SAndroid Build Coastguard Worker {
195*288bf522SAndroid Build Coastguard Worker struct wav_header hdr;
196*288bf522SAndroid Build Coastguard Worker unsigned char buf[8192];
197*288bf522SAndroid Build Coastguard Worker struct msm_audio_config cfg;
198*288bf522SAndroid Build Coastguard Worker unsigned sz;
199*288bf522SAndroid Build Coastguard Worker int fd, afd;
200*288bf522SAndroid Build Coastguard Worker unsigned total = 0;
201*288bf522SAndroid Build Coastguard Worker unsigned char tmp;
202*288bf522SAndroid Build Coastguard Worker
203*288bf522SAndroid Build Coastguard Worker hdr.riff_id = ID_RIFF;
204*288bf522SAndroid Build Coastguard Worker hdr.riff_sz = 0;
205*288bf522SAndroid Build Coastguard Worker hdr.riff_fmt = ID_WAVE;
206*288bf522SAndroid Build Coastguard Worker hdr.fmt_id = ID_FMT;
207*288bf522SAndroid Build Coastguard Worker hdr.fmt_sz = 16;
208*288bf522SAndroid Build Coastguard Worker hdr.audio_format = FORMAT_PCM;
209*288bf522SAndroid Build Coastguard Worker hdr.num_channels = channels;
210*288bf522SAndroid Build Coastguard Worker hdr.sample_rate = rate;
211*288bf522SAndroid Build Coastguard Worker hdr.byte_rate = hdr.sample_rate * hdr.num_channels * 2;
212*288bf522SAndroid Build Coastguard Worker hdr.block_align = hdr.num_channels * 2;
213*288bf522SAndroid Build Coastguard Worker hdr.bits_per_sample = 16;
214*288bf522SAndroid Build Coastguard Worker hdr.data_id = ID_DATA;
215*288bf522SAndroid Build Coastguard Worker hdr.data_sz = 0;
216*288bf522SAndroid Build Coastguard Worker
217*288bf522SAndroid Build Coastguard Worker fd = open(fn, O_CREAT | O_RDWR, 0666);
218*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
219*288bf522SAndroid Build Coastguard Worker perror("cannot open output file");
220*288bf522SAndroid Build Coastguard Worker return -1;
221*288bf522SAndroid Build Coastguard Worker }
222*288bf522SAndroid Build Coastguard Worker write(fd, &hdr, sizeof(hdr));
223*288bf522SAndroid Build Coastguard Worker
224*288bf522SAndroid Build Coastguard Worker afd = open("/dev/msm_pcm_in", O_RDWR);
225*288bf522SAndroid Build Coastguard Worker if (afd < 0) {
226*288bf522SAndroid Build Coastguard Worker perror("cannot open msm_pcm_in");
227*288bf522SAndroid Build Coastguard Worker close(fd);
228*288bf522SAndroid Build Coastguard Worker return -1;
229*288bf522SAndroid Build Coastguard Worker }
230*288bf522SAndroid Build Coastguard Worker
231*288bf522SAndroid Build Coastguard Worker /* config change should be a read-modify-write operation */
232*288bf522SAndroid Build Coastguard Worker if (ioctl(afd, AUDIO_GET_CONFIG, &cfg)) {
233*288bf522SAndroid Build Coastguard Worker perror("cannot read audio config");
234*288bf522SAndroid Build Coastguard Worker goto fail;
235*288bf522SAndroid Build Coastguard Worker }
236*288bf522SAndroid Build Coastguard Worker
237*288bf522SAndroid Build Coastguard Worker cfg.channel_count = hdr.num_channels;
238*288bf522SAndroid Build Coastguard Worker cfg.sample_rate = hdr.sample_rate;
239*288bf522SAndroid Build Coastguard Worker if (ioctl(afd, AUDIO_SET_CONFIG, &cfg)) {
240*288bf522SAndroid Build Coastguard Worker perror("cannot write audio config");
241*288bf522SAndroid Build Coastguard Worker goto fail;
242*288bf522SAndroid Build Coastguard Worker }
243*288bf522SAndroid Build Coastguard Worker
244*288bf522SAndroid Build Coastguard Worker if (ioctl(afd, AUDIO_GET_CONFIG, &cfg)) {
245*288bf522SAndroid Build Coastguard Worker perror("cannot read audio config");
246*288bf522SAndroid Build Coastguard Worker goto fail;
247*288bf522SAndroid Build Coastguard Worker }
248*288bf522SAndroid Build Coastguard Worker
249*288bf522SAndroid Build Coastguard Worker sz = cfg.buffer_size;
250*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"buffer size %d x %d\n", sz, cfg.buffer_count);
251*288bf522SAndroid Build Coastguard Worker if (sz > sizeof(buf)) {
252*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"buffer size %d too large\n", sz);
253*288bf522SAndroid Build Coastguard Worker goto fail;
254*288bf522SAndroid Build Coastguard Worker }
255*288bf522SAndroid Build Coastguard Worker
256*288bf522SAndroid Build Coastguard Worker if (ioctl(afd, AUDIO_START, 0)) {
257*288bf522SAndroid Build Coastguard Worker perror("cannot start audio");
258*288bf522SAndroid Build Coastguard Worker goto fail;
259*288bf522SAndroid Build Coastguard Worker }
260*288bf522SAndroid Build Coastguard Worker
261*288bf522SAndroid Build Coastguard Worker fcntl(0, F_SETFL, O_NONBLOCK);
262*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"\n*** RECORDING * HIT ENTER TO STOP ***\n");
263*288bf522SAndroid Build Coastguard Worker
264*288bf522SAndroid Build Coastguard Worker for (;;) {
265*288bf522SAndroid Build Coastguard Worker while (read(0, &tmp, 1) == 1) {
266*288bf522SAndroid Build Coastguard Worker if ((tmp == 13) || (tmp == 10)) goto done;
267*288bf522SAndroid Build Coastguard Worker }
268*288bf522SAndroid Build Coastguard Worker if (read(afd, buf, sz) != (ssize_t) sz) {
269*288bf522SAndroid Build Coastguard Worker perror("cannot read buffer");
270*288bf522SAndroid Build Coastguard Worker goto fail;
271*288bf522SAndroid Build Coastguard Worker }
272*288bf522SAndroid Build Coastguard Worker if (write(fd, buf, sz) != (ssize_t) sz) {
273*288bf522SAndroid Build Coastguard Worker perror("cannot write buffer");
274*288bf522SAndroid Build Coastguard Worker goto fail;
275*288bf522SAndroid Build Coastguard Worker }
276*288bf522SAndroid Build Coastguard Worker total += sz;
277*288bf522SAndroid Build Coastguard Worker
278*288bf522SAndroid Build Coastguard Worker }
279*288bf522SAndroid Build Coastguard Worker done:
280*288bf522SAndroid Build Coastguard Worker close(afd);
281*288bf522SAndroid Build Coastguard Worker
282*288bf522SAndroid Build Coastguard Worker /* update lengths in header */
283*288bf522SAndroid Build Coastguard Worker hdr.data_sz = total;
284*288bf522SAndroid Build Coastguard Worker hdr.riff_sz = total + 8 + 16 + 8;
285*288bf522SAndroid Build Coastguard Worker lseek(fd, 0, SEEK_SET);
286*288bf522SAndroid Build Coastguard Worker write(fd, &hdr, sizeof(hdr));
287*288bf522SAndroid Build Coastguard Worker close(fd);
288*288bf522SAndroid Build Coastguard Worker return 0;
289*288bf522SAndroid Build Coastguard Worker
290*288bf522SAndroid Build Coastguard Worker fail:
291*288bf522SAndroid Build Coastguard Worker close(afd);
292*288bf522SAndroid Build Coastguard Worker close(fd);
293*288bf522SAndroid Build Coastguard Worker unlink(fn);
294*288bf522SAndroid Build Coastguard Worker return -1;
295*288bf522SAndroid Build Coastguard Worker }
296*288bf522SAndroid Build Coastguard Worker
mp3_play(const char * fn)297*288bf522SAndroid Build Coastguard Worker int mp3_play(const char *fn)
298*288bf522SAndroid Build Coastguard Worker {
299*288bf522SAndroid Build Coastguard Worker char buf[64*1024];
300*288bf522SAndroid Build Coastguard Worker int r;
301*288bf522SAndroid Build Coastguard Worker int fd, afd;
302*288bf522SAndroid Build Coastguard Worker
303*288bf522SAndroid Build Coastguard Worker fd = open(fn, O_RDONLY);
304*288bf522SAndroid Build Coastguard Worker if (fd < 0) {
305*288bf522SAndroid Build Coastguard Worker perror("cannot open mp3 file");
306*288bf522SAndroid Build Coastguard Worker return -1;
307*288bf522SAndroid Build Coastguard Worker }
308*288bf522SAndroid Build Coastguard Worker
309*288bf522SAndroid Build Coastguard Worker afd = open("/dev/msm_mp3", O_RDWR);
310*288bf522SAndroid Build Coastguard Worker if (afd < 0) {
311*288bf522SAndroid Build Coastguard Worker close(fd);
312*288bf522SAndroid Build Coastguard Worker perror("cannot open mp3 output device");
313*288bf522SAndroid Build Coastguard Worker return -1;
314*288bf522SAndroid Build Coastguard Worker }
315*288bf522SAndroid Build Coastguard Worker
316*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"MP3 PLAY\n");
317*288bf522SAndroid Build Coastguard Worker ioctl(afd, AUDIO_START, 0);
318*288bf522SAndroid Build Coastguard Worker
319*288bf522SAndroid Build Coastguard Worker for (;;) {
320*288bf522SAndroid Build Coastguard Worker r = read(fd, buf, 64*1024);
321*288bf522SAndroid Build Coastguard Worker if (r <= 0) break;
322*288bf522SAndroid Build Coastguard Worker r = write(afd, buf, r);
323*288bf522SAndroid Build Coastguard Worker if (r < 0) break;
324*288bf522SAndroid Build Coastguard Worker }
325*288bf522SAndroid Build Coastguard Worker
326*288bf522SAndroid Build Coastguard Worker close(fd);
327*288bf522SAndroid Build Coastguard Worker close(afd);
328*288bf522SAndroid Build Coastguard Worker return 0;
329*288bf522SAndroid Build Coastguard Worker }
330*288bf522SAndroid Build Coastguard Worker
main(int argc,char ** argv)331*288bf522SAndroid Build Coastguard Worker int main(int argc, char **argv)
332*288bf522SAndroid Build Coastguard Worker {
333*288bf522SAndroid Build Coastguard Worker const char *fn = 0;
334*288bf522SAndroid Build Coastguard Worker int play = 1;
335*288bf522SAndroid Build Coastguard Worker unsigned channels = 1;
336*288bf522SAndroid Build Coastguard Worker unsigned rate = 44100;
337*288bf522SAndroid Build Coastguard Worker
338*288bf522SAndroid Build Coastguard Worker argc--;
339*288bf522SAndroid Build Coastguard Worker argv++;
340*288bf522SAndroid Build Coastguard Worker while (argc > 0) {
341*288bf522SAndroid Build Coastguard Worker if (!strcmp(argv[0],"-rec")) {
342*288bf522SAndroid Build Coastguard Worker play = 0;
343*288bf522SAndroid Build Coastguard Worker } else if (!strcmp(argv[0],"-play")) {
344*288bf522SAndroid Build Coastguard Worker play = 1;
345*288bf522SAndroid Build Coastguard Worker } else if (!strcmp(argv[0],"-stereo")) {
346*288bf522SAndroid Build Coastguard Worker channels = 2;
347*288bf522SAndroid Build Coastguard Worker } else if (!strcmp(argv[0],"-mono")) {
348*288bf522SAndroid Build Coastguard Worker channels = 1;
349*288bf522SAndroid Build Coastguard Worker } else if (!strcmp(argv[0],"-rate")) {
350*288bf522SAndroid Build Coastguard Worker argc--;
351*288bf522SAndroid Build Coastguard Worker argv++;
352*288bf522SAndroid Build Coastguard Worker if (argc == 0) {
353*288bf522SAndroid Build Coastguard Worker fprintf(stderr,"playwav: -rate requires a parameter\n");
354*288bf522SAndroid Build Coastguard Worker return -1;
355*288bf522SAndroid Build Coastguard Worker }
356*288bf522SAndroid Build Coastguard Worker rate = atoi(argv[0]);
357*288bf522SAndroid Build Coastguard Worker } else {
358*288bf522SAndroid Build Coastguard Worker fn = argv[0];
359*288bf522SAndroid Build Coastguard Worker }
360*288bf522SAndroid Build Coastguard Worker argc--;
361*288bf522SAndroid Build Coastguard Worker argv++;
362*288bf522SAndroid Build Coastguard Worker }
363*288bf522SAndroid Build Coastguard Worker
364*288bf522SAndroid Build Coastguard Worker if (fn == 0) {
365*288bf522SAndroid Build Coastguard Worker fn = play ? "/data/out.wav" : "/data/rec.wav";
366*288bf522SAndroid Build Coastguard Worker }
367*288bf522SAndroid Build Coastguard Worker
368*288bf522SAndroid Build Coastguard Worker if (play) {
369*288bf522SAndroid Build Coastguard Worker const char *dot = strrchr(fn, '.');
370*288bf522SAndroid Build Coastguard Worker if (dot && !strcmp(dot,".mp3")) {
371*288bf522SAndroid Build Coastguard Worker return mp3_play(fn);
372*288bf522SAndroid Build Coastguard Worker } else {
373*288bf522SAndroid Build Coastguard Worker return wav_play(fn);
374*288bf522SAndroid Build Coastguard Worker }
375*288bf522SAndroid Build Coastguard Worker } else {
376*288bf522SAndroid Build Coastguard Worker return wav_rec(fn, channels, rate);
377*288bf522SAndroid Build Coastguard Worker }
378*288bf522SAndroid Build Coastguard Worker return 0;
379*288bf522SAndroid Build Coastguard Worker }
380