Home | History | Annotate | Download | only in libaudio
      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