繁体   English   中英

FFMPEG音频解码和绘制波形

[英]FFMPEG Audio decode and draw waveform

我正在尝试使用ffmpeg解码音频并绘制波形,并且输入的音频数据是AV_SAMPLE_FMT_S16P ,基本上我在这里按照教程进行操作,并且音频在libao上运行良好 现在,我需要使用解码后的数据来绘制波形,目前我正在编写左右声道以分离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,样本值)的每个样本绘制线,其中x = 1,2,3,...

在此处输入图片说明

问题是对示例格式进行了签名时将其强制转换为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";

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM