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