• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
record_file(unsigned rate,unsigned channels,int fd,unsigned count)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 
rec_wav(const char * fn)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 
main(int argc,char ** argv)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