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