xref: /aosp_15_r20/system/extras/sound/playwav.c (revision 288bf5226967eb3dac5cce6c939ccc2a7f2b4fe5)
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