]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/platform-external-tinyalsa.git/blob - tinyplay.c
Update to latest tinyalsa
[android-sdk/platform-external-tinyalsa.git] / tinyplay.c
1 /* tinyplay.c
2 **
3 ** Copyright 2011, The Android Open Source Project
4 **
5 ** Redistribution and use in source and binary forms, with or without
6 ** modification, are permitted provided that the following conditions are met:
7 **     * Redistributions of source code must retain the above copyright
8 **       notice, this list of conditions and the following disclaimer.
9 **     * Redistributions in binary form must reproduce the above copyright
10 **       notice, this list of conditions and the following disclaimer in the
11 **       documentation and/or other materials provided with the distribution.
12 **     * Neither the name of The Android Open Source Project nor the names of
13 **       its contributors may be used to endorse or promote products derived
14 **       from this software without specific prior written permission.
15 **
16 ** THIS SOFTWARE IS PROVIDED BY The Android Open Source Project ``AS IS'' AND
17 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 ** ARE DISCLAIMED. IN NO EVENT SHALL The Android Open Source Project BE LIABLE
20 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 ** SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 ** CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26 ** DAMAGE.
27 */
29 #include <tinyalsa/asoundlib.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <stdint.h>
34 #define ID_RIFF 0x46464952
35 #define ID_WAVE 0x45564157
36 #define ID_FMT  0x20746d66
37 #define ID_DATA 0x61746164
39 struct riff_wave_header {
40     uint32_t riff_id;
41     uint32_t riff_sz;
42     uint32_t wave_id;
43 };
45 struct chunk_header {
46     uint32_t id;
47     uint32_t sz;
48 };
50 struct chunk_fmt {
51     uint16_t audio_format;
52     uint16_t num_channels;
53     uint32_t sample_rate;
54     uint32_t byte_rate;
55     uint16_t block_align;
56     uint16_t bits_per_sample;
57 };
59 void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
60                  unsigned int rate, unsigned int bits, unsigned int period_size,
61                  unsigned int period_count);
63 int main(int argc, char **argv)
64 {
65     FILE *file;
66     struct riff_wave_header riff_wave_header;
67     struct chunk_header chunk_header;
68     struct chunk_fmt chunk_fmt;
69     unsigned int device = 0;
70     unsigned int card = 0;
71     unsigned int period_size = 1024;
72     unsigned int period_count = 4;
73     char *filename;
74     int more_chunks = 1;
76     if (argc < 2) {
77         fprintf(stderr, "Usage: %s file.wav [-D card] [-d device] [-p period_size]"
78                 " [-n n_periods] \n", argv[0]);
79         return 1;
80     }
82     filename = argv[1];
83     file = fopen(filename, "rb");
84     if (!file) {
85         fprintf(stderr, "Unable to open file '%s'\n", filename);
86         return 1;
87     }
89     fread(&riff_wave_header, sizeof(riff_wave_header), 1, file);
90     if ((riff_wave_header.riff_id != ID_RIFF) ||
91         (riff_wave_header.wave_id != ID_WAVE)) {
92         fprintf(stderr, "Error: '%s' is not a riff/wave file\n", filename);
93         fclose(file);
94         return 1;
95     }
97     do {
98         fread(&chunk_header, sizeof(chunk_header), 1, file);
100         switch (chunk_header.id) {
101         case ID_FMT:
102             fread(&chunk_fmt, sizeof(chunk_fmt), 1, file);
103             /* If the format header is larger, skip the rest */
104             if (chunk_header.sz > sizeof(chunk_fmt))
105                 fseek(file, chunk_header.sz - sizeof(chunk_fmt), SEEK_CUR);
106             break;
107         case ID_DATA:
108             /* Stop looking for chunks */
109             more_chunks = 0;
110             break;
111         default:
112             /* Unknown chunk, skip bytes */
113             fseek(file, chunk_header.sz, SEEK_CUR);
114         }
115     } while (more_chunks);
117     /* parse command line arguments */
118     argv += 2;
119     while (*argv) {
120         if (strcmp(*argv, "-d") == 0) {
121             argv++;
122             if (*argv)
123                 device = atoi(*argv);
124         }
125         if (strcmp(*argv, "-p") == 0) {
126             argv++;
127             if (*argv)
128                 period_size = atoi(*argv);
129         }
130         if (strcmp(*argv, "-n") == 0) {
131             argv++;
132             if (*argv)
133                 period_count = atoi(*argv);
134         }
135         if (strcmp(*argv, "-D") == 0) {
136             argv++;
137             if (*argv)
138                 card = atoi(*argv);
139         }
140         if (*argv)
141             argv++;
142     }
144     play_sample(file, card, device, chunk_fmt.num_channels, chunk_fmt.sample_rate,
145                 chunk_fmt.bits_per_sample, period_size, period_count);
147     fclose(file);
149     return 0;
152 void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels,
153                  unsigned int rate, unsigned int bits, unsigned int period_size,
154                  unsigned int period_count)
156     struct pcm_config config;
157     struct pcm *pcm;
158     char *buffer;
159     int size;
160     int num_read;
162     config.channels = channels;
163     config.rate = rate;
164     config.period_size = period_size;
165     config.period_count = period_count;
166     if (bits == 32)
167         config.format = PCM_FORMAT_S32_LE;
168     else if (bits == 16)
169         config.format = PCM_FORMAT_S16_LE;
170     config.start_threshold = 0;
171     config.stop_threshold = 0;
172     config.silence_threshold = 0;
174     pcm = pcm_open(card, device, PCM_OUT, &config);
175     if (!pcm || !pcm_is_ready(pcm)) {
176         fprintf(stderr, "Unable to open PCM device %u (%s)\n",
177                 device, pcm_get_error(pcm));
178         return;
179     }
181     size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
182     buffer = malloc(size);
183     if (!buffer) {
184         fprintf(stderr, "Unable to allocate %d bytes\n", size);
185         free(buffer);
186         pcm_close(pcm);
187         return;
188     }
190     printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits);
192     do {
193         num_read = fread(buffer, 1, size, file);
194         if (num_read > 0) {
195             if (pcm_write(pcm, buffer, num_read)) {
196                 fprintf(stderr, "Error playing sample\n");
197                 break;
198             }
199         }
200     } while (num_read > 0);
202     free(buffer);
203     pcm_close(pcm);