1 /* 2 ** Copyright 2010, The Android Open-Source Project 3 ** 4 ** Licensed under the Apache License, Version 2.0 (the "License"); 5 ** you may not use this file except in compliance with the License. 6 ** You may obtain a copy of the License at 7 ** 8 ** http://www.apache.org/licenses/LICENSE-2.0 9 ** 10 ** Unless required by applicable law or agreed to in writing, software 11 ** distributed under the License is distributed on an "AS IS" BASIS, 12 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 ** See the License for the specific language governing permissions and 14 ** limitations under the License. 15 */ 16 17 #include <stdio.h> 18 #include <stdlib.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <stdint.h> 22 #include <string.h> 23 24 #include "alsa_audio.h" 25 26 #define ID_RIFF 0x46464952 27 #define ID_WAVE 0x45564157 28 #define ID_FMT 0x20746d66 29 #define ID_DATA 0x61746164 30 31 #define FORMAT_PCM 1 32 33 struct wav_header { 34 uint32_t riff_id; 35 uint32_t riff_sz; 36 uint32_t riff_fmt; 37 uint32_t fmt_id; 38 uint32_t fmt_sz; 39 uint16_t audio_format; 40 uint16_t num_channels; 41 uint32_t sample_rate; 42 uint32_t byte_rate; /* sample_rate * num_channels * bps / 8 */ 43 uint16_t block_align; /* num_channels * bps / 8 */ 44 uint16_t bits_per_sample; 45 uint32_t data_id; 46 uint32_t data_sz; 47 }; 48 49 int play_file(unsigned rate, unsigned channels, int fd, unsigned count) 50 { 51 struct pcm *pcm; 52 struct mixer *mixer; 53 struct pcm_ctl *ctl = NULL; 54 unsigned bufsize; 55 char *data; 56 unsigned flags = PCM_OUT; 57 58 if (channels == 1) 59 flags |= PCM_MONO; 60 else 61 flags |= PCM_STEREO; 62 63 pcm = pcm_open(flags); 64 if (!pcm_ready(pcm)) { 65 pcm_close(pcm); 66 return -1; 67 } 68 69 mixer = mixer_open(); 70 if (mixer) 71 ctl = mixer_get_control(mixer,"Playback Path", 0); 72 73 bufsize = pcm_buffer_size(pcm); 74 data = malloc(bufsize); 75 if (!data) { 76 fprintf(stderr,"could not allocate %d bytes\n", count); 77 return -1; 78 } 79 80 while (read(fd, data, bufsize) == bufsize) { 81 if (pcm_write(pcm, data, bufsize)) 82 break; 83 84 /* HACK: remove */ 85 if (ctl) { 86 //mixer_ctl_select(ctl, "SPK"); 87 ctl = 0; 88 } 89 } 90 pcm_close(pcm); 91 return 0; 92 } 93 94 int play_wav(const char *fn) 95 { 96 struct wav_header hdr; 97 unsigned rate, channels; 98 int fd; 99 fd = open(fn, O_RDONLY); 100 if (fd < 0) { 101 fprintf(stderr, "aplay: cannot open '%s'\n", fn); 102 return -1; 103 } 104 if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { 105 fprintf(stderr, "aplay: cannot read header\n"); 106 return -1; 107 } 108 fprintf(stderr,"aplay: %d ch, %d hz, %d bit, %s\n", 109 hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample, 110 hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown"); 111 112 if ((hdr.riff_id != ID_RIFF) || 113 (hdr.riff_fmt != ID_WAVE) || 114 (hdr.fmt_id != ID_FMT)) { 115 fprintf(stderr, "aplay: '%s' is not a riff/wave file\n", fn); 116 return -1; 117 } 118 if ((hdr.audio_format != FORMAT_PCM) || 119 (hdr.fmt_sz != 16)) { 120 fprintf(stderr, "aplay: '%s' is not pcm format\n", fn); 121 return -1; 122 } 123 if (hdr.bits_per_sample != 16) { 124 fprintf(stderr, "aplay: '%s' is not 16bit per sample\n", fn); 125 return -1; 126 } 127 128 return play_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz); 129 } 130 131 int main(int argc, char **argv) 132 { 133 if (argc != 2) { 134 fprintf(stderr,"usage: aplay <file>\n"); 135 return -1; 136 } 137 138 return play_wav(argv[1]); 139 } 140 141