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