03 ffmpeg调用声卡录制wav文件

头文件:

#define __STDC_CONSTANT_MACROS
extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libavdevice/avdevice.h>
}

AVInputFormat类型表示一种输入文件/输入设备的数据格式
AVFormatContext类型表示音视频的格式内容
AVDictionary类型表示相关的配置项,如摄像头设备有图像大小的配置 
AVPacket类型用于装载一帧数据

    1. av_register_all();         //注册能用的编解码器及文件格式

    2. avdevice_register_all();   //注册能操作的输入输出设备


    3. 准备参数
       AVInputFormat *ifmt = av_find_input_format("alsa"); ///指定alsa接口的音频设备
           AVFormatContext *fmtContxt = avformat_alloc_context();
           AVDictionary *options = NULL;

       av_dict_set(&options, "sample_rate", "44100", 0);
           av_dict_set(&options, "channels", "1", 0);
        //声卡alsa接口可配置的选项,可参考ffmpeg源码/libavdevice/alsa_dec.c             

    4. 使用指定的参数, 打开指定的设备
        if (avformat_open_input(&fmtContxt, "default", ifmt, &options) < 0)
        {
        perror("avformat open");
        return 1;
        }

    5. 打开设备后, 可检查声音数据格式.
        AVCodecID id = fmtContxt->streams[0]->codec->codec_id; //获取数据的格式ID
        qDebug() << id << "   " << avcodec_get_name(id);  
        // 显示是:pcm_s16le, 也就是pcm数据, 量化精度为小端16位



    6. 准备一帧数据的空间,及读取数据: 
        AVPacket *packet = (AVPacket *)av_malloc(sizeof(AVPacket));

        av_read_frame(fmtContxt, packet); //读取一帧数据
        // packet->data指针指向声音数据缓冲区的首地址
        // packet->size是当前帧数据的真实大小


    7. 封装成一个wav文件. wav文件格式参考http://soundfile.sapp.org/doc/WaveFormat/
       大概来说wav其实就一个文件头+pcm数据组成.
       录制60秒的wav文件

            WavHeader header(44100, 16, 1, 60);
        FILE *fl = fopen("/my.wav", "w");
        fwrite(&header, sizeof(header), 1, fl);   // 写入文件头

        int len = 44100*1*2*60;  //60秒的数据长度
        for (int n = 0; n < len;)
        {
        if (av_read_frame(fmtContxt, packet) < 0)
        {
            perror("read frame failed");
            return 1;
        }
        qDebug() << packet->size;

        n += packet->size;
        fwrite(packet->data, packet->size, 1, fl);  //写入pcm数据
        }
        fclose(fl);
附wav文件头的类型:
class WavHeader {
private:
    unsigned char ChunkID[4];  // "RIFF"
    unsigned int  ChunkSize; // 36 + SubChunk2Size
    unsigned char Format[4]; // "WAVE"

    unsigned char  Subchunk1ID[4]; // "fmt"
    unsigned int   Subchunk1Size; // 16 for pcm
    unsigned short AudioFormat; //  PCM=1
    unsigned short NumChannels;
    unsigned int   SampleRate;
    unsigned int   ByteRate; // SampleRate * NumChannels * BitsPerSample/8
    unsigned short BlockAlign; // NumChannels * BitsPerSample/8
    unsigned short BitsPerSample; //8 bits = 8, 16 bits = 16

    unsigned char   Subchunk2ID[4]; // "data"
    unsigned int    Subchunk2Size; // NumSamples * NumChannels * BitsPerSample/8

public:
    WavHeader (int rate, int bits, int channels, int sec)
    {
        strcpy((char *)ChunkID, "RIFF");
        Subchunk2Size = (sec * rate * channels * bits)>>3;
        ChunkSize = 36 + Subchunk2Size;
        strcpy((char *)Format, "WAVE");

        strcpy((char *)Subchunk1ID, "fmt ");
        Subchunk1Size = 16;
        AudioFormat = 1;
        NumChannels = channels;
        SampleRate = rate;
        ByteRate = (rate * channels * bits)>>3;
        BlockAlign = (channels * bits)>>3;
        BitsPerSample = bits;

        strcpy((char *)Subchunk2ID, "data");
        Subchunk2Size = (sec * rate * channels * bits)>>3;
    }
};

参考:
http://blog.youkuaiyun.com/leixiaohua1020

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值