gpt4 book ai didi

c++ - FFMPEG Audio解码并绘制波形

转载 作者:行者123 更新时间:2023-11-30 03:43:01 33 4
gpt4 key购买 nike

我正在尝试解码音频并使用 ffmpeg 绘制波形,输入音频数据为 AV_SAMPLE_FMT_S16P,基本上我正在按照教程 here 进行操作, 音频在 libao 下播放正常.现在我需要使用解码数据绘制波形,目前我正在编写左右 channel 以分离 csv 文件并在 excel 上绘制。但是波形与使用相同音频剪辑的 Audacity 中显示的波形有所不同。当我分析写在 csv 上的值时,大多数值都接近 uint16_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;

编辑:

我附上了使用opencv绘制的波形图像,这里我将样本值缩放到0-255范围内,并将值127作为0(Y轴)。现在为每个样本绘制从 (x,127) 到 (x,sample value) 的线,其中 x=1,2,3,...

enter image description here

最佳答案

问题是当示例格式已签名时转换为 uint16_t(AV_SAMPLE_FMT_S16P,其中 S 表示已签名)。因此,-1 将作为 2147483648 等写入文件。

要修复它,更改行:

fileCh1 <<((uint16_t *) frame->extended_data[ch])[nb]<<"\n";

到:

fileCh1 <<((int16_t *) frame->extended_data[ch])[nb]<<"\n";

关于c++ - FFMPEG Audio解码并绘制波形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36425401/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com