C++ 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

我正在尝试解码音频并使用ffmpeg绘制波形,输入的音频数据是
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";