前面讲解了如何使用libavdevice采集摄像头图像
同样 libavdevice 也可以采集麦克风的声音。
下面就讲解麦克风声音的采集:
采集声音和采集摄像头本质上没有多大的却别,基本上就是换个名字:
其中"audio=麦克风 (Realtek High Definition Audio)"跟之前获取摄像头名字一样的方法,直接使用ffmpeg命令行获取即可,不懂得直接查看之前的教程。传送门
成功打开麦克风之后,就是查找流然后打开解码器:
每一帧所发费的时间由pFrame->nb_samples * 1.0 / pCodecCtx->sample_rate;来获得。
上面总共采集了30秒,同时将采集得到的pcm音频数据写入了文件。
打开pcm数据可以使用cool edit这个软件。有需要的可以百度下载。
pcm是最原始的音频数据,是不带有任何采集率以及声道的信息的。
因此我们需要手动告诉cool edit软件需要打开的pcm数据的采样率和声道信息,否则打开之后会是全部杂音。
我们这里采集到的是44100 双声道的。
接着就可以看到漂亮的波形图了,
cool edit的使用这里就不说了,自行琢磨吧。
#include <stdio.h>
#include <iostream>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
}
using namespace std;
//'1' Use Dshow
//'0' Use VFW
#define USE_DSHOW 0
//Show Dshow Device
void show_dshow_device(){
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options,"list_devices","true",0);
AVInputFormat *iformat = av_find_input_format("dshow");
printf("========Device Info=============\n");
avformat_open_input(&pFormatCtx,"video=dummy",iformat,&options);
printf("================================\n");
}
//Show Dshow Device Option
void show_dshow_device_option(){
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options,"list_options","true",0);
AVInputFormat *iformat = av_find_input_format("dshow");
printf("========Device Option Info======\n");
avformat_open_input(&pFormatCtx,"video=Integrated Camera",iformat,&options);
printf("================================\n");
}
//Show VFW Device
void show_vfw_device(){
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVInputFormat *iformat = av_find_input_format("vfwcap");
printf("========VFW Device Info======\n");
avformat_open_input(&pFormatCtx,"list",iformat,NULL);
printf("=============================\n");
}
//Show AVFoundation Device
void show_avfoundation_device(){
AVFormatContext *pFormatCtx = avformat_alloc_context();
AVDictionary* options = NULL;
av_dict_set(&options,"list_devices","true",0);
AVInputFormat *iformat = av_find_input_format("avfoundation");
printf("==AVFoundation Device Info===\n");
avformat_open_input(&pFormatCtx,"",iformat,&options);
printf("=============================\n");
}
#define USE_DSHOW 1
int main(int argc, char* argv[])
{
AVFormatContext *pFormatCtx;
int i, audioindex;
AVCodecContext *pCodecCtx;
AVCodec *pCodec;
av_register_all();
avformat_network_init();
avdevice_register_all();//Register Device
show_dshow_device();
pFormatCtx = avformat_alloc_context();
#if 1
AVInputFormat *ifmt=av_find_input_format("dshow");
//Set own video device's name
if(avformat_open_input(&pFormatCtx,"audio=麦克风 (Realtek High Definition Au0",ifmt,NULL)!=0){
printf("Couldn't open input stream.\n");
return -1;
}
#else
AVInputFormat *ifmt=av_find_input_format("vfwcap");
if(avformat_open_input(&pFormatCtx,"0",ifmt,NULL)!=0){
printf("Couldn't open input stream.\n");
return -1;
}
#endif
if(avformat_find_stream_info(pFormatCtx,NULL)<0)
{
printf("Couldn't find stream information.\n");
return -1;
}
audioindex=-1;
for(i=0; i<pFormatCtx->nb_streams; i++)
{
if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
{
audioindex=i;
}
}
if(audioindex==-1)
{
printf("Couldn't find a audio stream.\n");
return -1;
}
pCodecCtx=pFormatCtx->streams[audioindex]->codec;
pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
if(pCodec==NULL)
{
printf("Codec not found.\n");
return -1;
}
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
{
printf("Could not open codec.\n");
return -1;
}
///这里打印出音频的信息
printf("audio info:");
cout<<"audio info:"<<pCodecCtx->sample_fmt<<pCodecCtx->bit_rate<<pCodecCtx->sample_rate<<pCodecCtx->channels;
FILE *fp_pcm=fopen("output.pcm","wb");
AVPacket *packet= (AVPacket*)av_malloc(sizeof(AVPacket));
AVFrame *pFrame = (AVFrame *)av_malloc(sizeof(AVFrame ));
int got_picture = -1;
float Time = 0;
for(int i=0;;i++)
{
if (Time > 10) break; //就采集30秒
if(av_read_frame(pFormatCtx, packet) < 0)
{
break;
}
if(packet->stream_index==audioindex)
{
int ret = avcodec_decode_audio4(pCodecCtx, pFrame, &got_picture, packet);
if(ret < 0){
printf("Decode Error.\n");
return -1;
}
if(got_picture)
{
int pcmSize = av_samples_get_buffer_size(NULL,pCodecCtx->channels, pFrame->nb_samples,pCodecCtx->sample_fmt, 1);
uint8_t * pcmBuffer = pFrame->data[0];
float useTime = pFrame->nb_samples * 1.0 / pCodecCtx->sample_rate;
Time += useTime;
cout<<i<<Time<<useTime;
fwrite(pcmBuffer,1,pcmSize,fp_pcm); //写入文件
}
}
av_free_packet(packet);
}
fclose(fp_pcm);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}