tinyplay.c revision edff708e3129d7d8e05bbdfb624af97a3264a332
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*/
28
29#include <tinyalsa/asoundlib.h>
30#include <stdio.h>
31#include <stdlib.h>
32#include <stdint.h>
33
34#define ID_RIFF 0x46464952
35#define ID_WAVE 0x45564157
36#define ID_FMT  0x20746d66
37#define ID_DATA 0x61746164
38
39#define FORMAT_PCM 1
40
41struct wav_header {
42    uint32_t riff_id;
43    uint32_t riff_sz;
44    uint32_t riff_fmt;
45    uint32_t fmt_id;
46    uint32_t fmt_sz;
47    uint16_t audio_format;
48    uint16_t num_channels;
49    uint32_t sample_rate;
50    uint32_t byte_rate;
51    uint16_t block_align;
52    uint16_t bits_per_sample;
53    uint32_t data_id;
54    uint32_t data_sz;
55};
56
57void play_sample(FILE *file, unsigned int channels, unsigned int rate,
58                 unsigned int bits);
59
60int main(int argc, char **argv)
61{
62    FILE *file;
63    struct wav_header header;
64
65    if (argc != 2) {
66        fprintf(stderr, "Usage: %s <file.wav>\n", argv[0]);
67        return 1;
68    }
69
70    file = fopen(argv[1], "rb");
71    if (!file) {
72        fprintf(stderr, "Unable to open file '%s'\n", argv[1]);
73        return 1;
74    }
75
76    fread(&header, sizeof(struct wav_header), 1, file);
77
78    if ((header.riff_id != ID_RIFF) ||
79        (header.riff_fmt != ID_WAVE) ||
80        (header.fmt_id != ID_FMT) ||
81        (header.audio_format != FORMAT_PCM) ||
82        (header.fmt_sz != 16)) {
83        fprintf(stderr, "Error: '%s' is not a PCM riff/wave file\n", argv[1]);
84        fclose(file);
85        return 1;
86    }
87
88    play_sample(file, header.num_channels, header.sample_rate,
89                header.bits_per_sample);
90
91    fclose(file);
92
93    return 0;
94}
95
96void play_sample(FILE *file, unsigned int channels, unsigned int rate,
97                 unsigned int bits)
98{
99    struct pcm_config config;
100    struct pcm *pcm;
101    char *buffer;
102    int size;
103    int num_read;
104
105    config.channels = channels;
106    config.rate = rate;
107    config.period_size = 1024;
108    config.period_count = 4;
109    if (bits == 32)
110        config.format = PCM_FORMAT_S32_LE;
111    else if (bits == 16)
112        config.format = PCM_FORMAT_S16_LE;
113
114    pcm = pcm_open(0, 0, PCM_OUT, &config);
115    if (!pcm || !pcm_is_ready(pcm)) {
116        fprintf(stderr, "Unable to open PCM device (%s)\n",
117                pcm_get_error(pcm));
118        return;
119    }
120
121    size = pcm_get_buffer_size(pcm);
122    buffer = malloc(size);
123    if (!buffer) {
124        fprintf(stderr, "Unable to allocate %d bytes\n", size);
125        free(buffer);
126        pcm_close(pcm);
127        return;
128    }
129
130    printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits);
131
132    do {
133        num_read = fread(buffer, 1, size, file);
134        if (num_read > 0) {
135            if (pcm_write(pcm, buffer, num_read)) {
136                fprintf(stderr, "Error playing sample\n");
137                break;
138            }
139        }
140    } while (num_read > 0);
141
142    free(buffer);
143    pcm_close(pcm);
144}
145
146