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

来源:互联网 发布:ubuntu虚拟机无法上网 编辑:程序博客网 时间:2024/06/06 01:02
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.


阅读全文
1 0
原创粉丝点击