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 record_file(unsigned rate, unsigned channels, int fd, unsigned count)
     50 {
     51     struct pcm *pcm;
     52     unsigned avail, xfer, bufsize;
     53     char *data, *next;
     54     int r;
     55 
     56     pcm = pcm_open(PCM_IN|PCM_MONO);
     57     if (!pcm_ready(pcm)) {
     58         pcm_close(pcm);
     59         goto fail;
     60     }
     61 
     62     bufsize = pcm_buffer_size(pcm);
     63 
     64     data = malloc(bufsize);
     65     if (!data) {
     66         fprintf(stderr,"could not allocate %d bytes\n", count);
     67         return -1;
     68     }
     69 
     70     while (!pcm_read(pcm, data, bufsize)) {
     71         if (write(fd, data, bufsize) != bufsize) {
     72             fprintf(stderr,"could not write %d bytes\n", bufsize);
     73             return -1;
     74         }
     75     }
     76 
     77     close(fd);
     78     pcm_close(pcm);
     79     return 0;
     80 
     81 fail:
     82     fprintf(stderr,"pcm error: %s\n", pcm_error(pcm));
     83     return -1;
     84 }
     85 
     86 int rec_wav(const char *fn)
     87 {
     88     struct wav_header hdr;
     89     unsigned rate, channels;
     90     int fd;
     91     fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0664);
     92     if (fd < 0) {
     93         fprintf(stderr, "arec: cannot open '%s'\n", fn);
     94         return -1;
     95     }
     96 
     97     hdr.riff_id = ID_RIFF;
     98     hdr.riff_fmt = ID_WAVE;
     99     hdr.fmt_id = ID_FMT;
    100     hdr.audio_format = FORMAT_PCM;
    101     hdr.fmt_sz = 16;
    102     hdr.bits_per_sample = 16;
    103     hdr.num_channels = 1;
    104     hdr.data_sz = 0;
    105     hdr.sample_rate = 44100;
    106 
    107     if (write(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
    108         fprintf(stderr, "arec: cannot write header\n");
    109         return -1;
    110     }
    111     fprintf(stderr,"arec: %d ch, %d hz, %d bit, %s\n",
    112             hdr.num_channels, hdr.sample_rate, hdr.bits_per_sample,
    113             hdr.audio_format == FORMAT_PCM ? "PCM" : "unknown");
    114 
    115 
    116     return record_file(hdr.sample_rate, hdr.num_channels, fd, hdr.data_sz);
    117 }
    118 
    119 int main(int argc, char **argv)
    120 {
    121     if (argc != 2) {
    122         fprintf(stderr,"usage: arec <file>\n");
    123         return -1;
    124     }
    125 
    126     return rec_wav(argv[1]);
    127 }
    128 
    129