[RK3288][Android6.0] Tinycap录音程序源代码浅析

Platform: Rockchip
OS: Android 6.0

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.


你可能感兴趣的:(子类__Audio)