Kernel: 3.10.92
源代码位于:
external/tinyalsa/tinycap.c
int main(int argc, char **argv)
{
FILE *file;
struct wav_header header;
//默认使用第一个录音设备,双通道,44.1kHz采样率,16bit
//period为1024帧,count一共4个。
unsigned int card = 0;
unsigned int device = 0;
unsigned int channels = 2;
unsigned int rate = 44100;
unsigned int bits = 16;
unsigned int frames;
unsigned int period_size = 1024;
unsigned int period_count = 4;
enum pcm_format format;
//传进来的录音文件参数。
file = fopen(argv[1], "wb");
if (!file) {
fprintf(stderr, "Unable to create file '%s'\n", argv[1]);
return 1;
}
//命令行可以重新设置参数
argv += 2;
while (*argv) {
if (strcmp(*argv, "-d") == 0) {
argv++;
if (*argv)
device = atoi(*argv);
......
}
//wav格式头文件结构填充
header.riff_id = ID_RIFF;
header.riff_sz = 0;
header.riff_fmt = ID_WAVE;
header.fmt_id = ID_FMT;
header.fmt_sz = 16;
header.audio_format = FORMAT_PCM;
header.num_channels = channels;
header.sample_rate = rate;
......
/* leave enough room for header */
fseek(file, sizeof(struct wav_header), SEEK_SET);
......
frames = capture_sample(file, card, device, header.num_channels,
header.sample_rate, format,
period_size, period_count);
......
//最后把wav header写进去。
fwrite(&header, sizeof(struct wav_header), 1, file);
fclose(file);
return 0;
}
capture_sample():
unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device,
unsigned int channels, unsigned int rate,
enum pcm_format format, unsigned int period_size,
unsigned int period_count)
{
struct pcm_config config;
......
//转换成config
config.channels = channels;
config.rate = rate;
config.period_size = period_size;
config.period_count = period_count;
config.format = format;
config.start_threshold = 0;
config.stop_threshold = 0;
config.silence_threshold = 0;
//标准tinyalsa打开接口
pcm = pcm_open(card, device, PCM_IN, &config);
if (!pcm || !pcm_is_ready(pcm)) {
fprintf(stderr, "Unable to open PCM device (%s)\n",
pcm_get_error(pcm));
return 0;
}
//记录的时候是frame,计算的时候要用size.
size = pcm_frames_to_bytes(pcm, pcm_get_buffer_size(pcm));
buffer = malloc(size);
......
//它是整个size一次读取。
while (capturing && !pcm_read(pcm, buffer, size)) {
//写入文件
if (fwrite(buffer, 1, size, file) != size) {
fprintf(stderr,"Error capturing sample\n");
break;
}
//总共读取字节数
bytes_read += size;
}
......
//返回总共读取到的帧数
return pcm_bytes_to_frames(pcm, bytes_read);
}
整个流程相对比较简单,核心部分主要是在pcm_open()以及pcm_read()有兴趣可研究下。
不过要注意的是peroid_size和peroid_count有范围,不是任何数值都可以,而frame rate是固定的,是44.1kHz.