C++ FFMPEG音频解码和绘制波形
我正在尝试解码音频并使用ffmpeg绘制波形,输入的音频数据是C++ FFMPEG音频解码和绘制波形,c++,audio,ffmpeg,C++,Audio,Ffmpeg,我正在尝试解码音频并使用ffmpeg绘制波形,输入的音频数据是AV_SAMPLE\u FMT\u S16P,基本上我在遵循教程,音频播放效果良好。现在我需要使用解码数据绘制波形,目前我正在编写左通道和右通道以分离csv文件并在excel上绘制。但是波形与Audacity中使用相同音频剪辑显示的波形有所不同。当我分析写在csv上的值时,大多数值接近最大值uint16\u t(65535),但也有其他一些较低的值,但大多数是高峰值 这是源代码 const char* input_filena
AV_SAMPLE\u FMT\u S16P
,基本上我在遵循教程,音频播放效果良好。现在我需要使用解码数据绘制波形,目前我正在编写左通道和右通道以分离csv文件并在excel上绘制。但是波形与Audacity中使用相同音频剪辑显示的波形有所不同。当我分析写在csv上的值时,大多数值接近最大值uint16\u t
(65535),但也有其他一些较低的值,但大多数是高峰值
这是源代码
const char* input_filename="/home/user/Music/Clip.mp3";
av_register_all();
AVFormatContext* container=avformat_alloc_context();
if(avformat_open_input(&container,input_filename,NULL,NULL)<0){
endApp("Could not open file");
}
if(avformat_find_stream_info(container, NULL)<0){
endApp("Could not find file info");
}
av_dump_format(container,0,input_filename,false);
int stream_id=-1;
int i;
for(i=0;i<container->nb_streams;i++){
if(container->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO){
stream_id=i;
break;
}
}
if(stream_id==-1){
endApp("Could not find Audio Stream");
}
AVDictionary *metadata=container->metadata;
AVCodecContext *ctx=container->streams[stream_id]->codec;
AVCodec *codec=avcodec_find_decoder(ctx->codec_id);
if(codec==NULL){
endApp("cannot find codec!");
}
if(avcodec_open2(ctx,codec,NULL)<0){
endApp("Codec cannot be found");
}
AVPacket packet;
av_init_packet(&packet);
//AVFrame *frame=avcodec_alloc_frame();
AVFrame *frame=av_frame_alloc();
int buffer_size=AVCODEC_MAX_AUDIO_FRAME_SIZE+ FF_INPUT_BUFFER_PADDING_SIZE;
// MSVC can't do variable size allocations on stack, ohgodwhy
uint8_t *buffer = new uint8_t[buffer_size];
packet.data=buffer;
packet.size =buffer_size;
int frameFinished=0;
int plane_size;
ofstream fileCh1,fileCh2;
fileCh1.open ("ch1.csv");
fileCh2.open ("ch2.csv");
AVSampleFormat sfmt=ctx->sample_fmt;
while(av_read_frame(container,&packet)>=0)
{
if(packet.stream_index==stream_id){
int len=avcodec_decode_audio4(ctx,frame,&frameFinished,&packet);
int data_size = av_samples_get_buffer_size(&plane_size, ctx->channels,
frame->nb_samples,
ctx->sample_fmt, 1);
if(frameFinished){
int write_p=0;
// QTime t;
switch (sfmt){
case AV_SAMPLE_FMT_S16P:
for (int nb=0;nb<plane_size/sizeof(uint16_t);nb++){
for (int ch = 0; ch < ctx->channels; ch++) {
if(ch==0)
fileCh1 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n";
else if(ch==1)
fileCh2 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n";
}
}
break;
}
} else {
DBG("frame failed");
}
}
av_free_packet(&packet);
}
fileCh1.close();
fileCh2.close();
avcodec_close(ctx);
avformat_close_input(&container);
delete buffer;
return 0;
const char*input_filename=“/home/user/Music/Clip.mp3”;
av_寄存器_all();
AVFormatContext*容器=avformat_alloc_context();
if(avformat\u open\u input(&container,input\u filename,NULL,NULL)codec->codec\u type==AVMEDIA\u type\u AUDIO){
流_id=i;
打破
}
}
如果(流_id==-1){
endApp(“找不到音频流”);
}
AVDictionary*元数据=容器->元数据;
AVCodecContext*ctx=container->streams[stream\u id]->codec;
AVCodec*codec=AVCodec\u find\u解码器(ctx->codec\u id);
如果(编解码器==NULL){
endApp(“找不到编解码器!”);
}
如果(avcodec_open2(ctx,codec,NULL)那么问题是当样本格式被签名时,转换到uint16_t
(AV_sample_FMT_S16P,其中S表示已签名)。因此,-1将作为2147483648写入文件,依此类推
要修复此问题,请更改行:
fileCh1 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n";
fileCh1样本值的转换似乎失去了精度。使用printf
格式化样本值时,您会得到什么输出?使用三种方法打印值,如printf(“%u”),(无符号短)out[write\p])当代码签署16位时,你为什么要向UTIN 16t开机?我没有注意到,实际上我在这里遵循代码,没有修改,可能是这个问题,我会检查它并让你知道结果。如果你想处理几乎任何格式的痛苦,请考虑使用函数描述。d在本教程中:
fileCh1 <<((int16_t *) frame->extended_data[ch])[nb]<<"\n";