C++ 使用libswresample重新采样音频,在重新采样后会留下少量噪声

C++ 使用libswresample重新采样音频,在重新采样后会留下少量噪声,c++,audio,ffmpeg,resampling,libswresample,C++,Audio,Ffmpeg,Resampling,Libswresample,我试着将音频从44Khz重采样到48Khz,重采样后我得到的是很小的光噪声。好像有人在轻轻地拨弄麦克风。这是双向的。从48Khz到44Khz,反之亦然 我读到过这样的情况,因为swrContext仍有一些数据剩余,我应该在对下一帧重新采样之前刷新上下文。虽然这有助于减少(不太明显的噪音),但它仍然存在 我尝试过使用FFmpeg重采样过滤器,但输出的只是巨大的非相干噪声。我很确定libswresample不应该在重采样时输出任何噪声,这意味着我不知道如何很好地使用它,我缺少一些选项 这是重采样器的

我试着将音频从44Khz重采样到48Khz,重采样后我得到的是很小的光噪声。好像有人在轻轻地拨弄麦克风。这是双向的。从48Khz到44Khz,反之亦然

我读到过这样的情况,因为swrContext仍有一些数据剩余,我应该在对下一帧重新采样之前刷新上下文。虽然这有助于减少(不太明显的噪音),但它仍然存在

我尝试过使用FFmpeg重采样过滤器,但输出的只是巨大的非相干噪声。我很确定libswresample不应该在重采样时输出任何噪声,这意味着我不知道如何很好地使用它,我缺少一些选项

这是重采样器的代码

int ResampleFrame(VideoState * videoState, AVFrame *decoded_audio_frame,     enum AVSampleFormat out_sample_fmt, uint8_t * out_buf)
{
 int in_sample_rate = videoState->audio->ptrAudioCodecCtx_->sample_rate;
 int out_sample_rate = SAMPLE_RATE;

// get an instance of the AudioResamplingState struct, create if NULL
AudioResamplingState* arState = getAudioResampling(videoState->audio->ptrAudioCodecCtx_->channel_layout);

if (!arState->swr_ctx)
{
    printf("swr_alloc error.\n");
    return -1;
}

// get input audio channels
arState->in_channel_layout = (videoState->audio->ptrAudioCodecCtx_->channels ==
            av_get_channel_layout_nb_channels(videoState->audio->ptrAudioCodecCtx_->channel_layout)) ?
            videoState->audio->ptrAudioCodecCtx_->channel_layout :
            av_get_default_channel_layout(videoState->audio->ptrAudioCodecCtx_->channels);


// check input audio channels correctly retrieved
if (arState->in_channel_layout <= 0)
{
    printf("in_channel_layout error.\n");
    return -1;
}


arState->out_channel_layout = AV_CH_LAYOUT_STEREO;

// retrieve number of audio samples (per channel)
arState->in_nb_samples = decoded_audio_frame->nb_samples;
if (arState->in_nb_samples <= 0)
{
    printf("in_nb_samples error.\n");
    return -1;
}

// Set SwrContext parameters for resampling
av_opt_set_int(arState->swr_ctx, "in_channel_layout", arState->in_channel_layout, 0);
av_opt_set_int(arState->swr_ctx, "in_sample_rate", in_sample_rate, 0);
av_opt_set_sample_fmt(arState->swr_ctx, "in_sample_fmt", videoState->audio->ptrAudioCodecCtx_->sample_fmt, 0);


// Set SwrContext parameters for resampling
av_opt_set_int(arState->swr_ctx, "out_channel_layout", arState->out_channel_layout, 0);
av_opt_set_int(arState->swr_ctx, "out_sample_rate", out_sample_rate, 0);
av_opt_set_sample_fmt(arState->swr_ctx, "out_sample_fmt", out_sample_fmt, 0);


// initialize SWR context after user parameters have been set
int ret = swr_init(arState->swr_ctx);
if (ret < 0)
   {
    printf("Failed to initialize the resampling context.\n");
    return -1;
   }


 // retrieve output samples number taking into account the progressive delay
int64_t delay = swr_get_delay(arState->swr_ctx, videoState->audio->ptrAudioCodecCtx_->sample_rate) + arState->in_nb_samples;
arState->out_nb_samples = av_rescale_rnd(delay, out_sample_rate, in_sample_rate, AV_ROUND_UP );

// check output samples number was correctly rescaled
if (arState->out_nb_samples <= 0)
{
    printf("av_rescale_rnd error\n");
    return -1;
}

// get number of output audio channels
arState->out_nb_channels = av_get_channel_layout_nb_channels(arState->out_channel_layout);

// allocate data pointers array for arState->resampled_data and fill data
// pointers and linesize accordingly
// check memory allocation for the resampled data was successful
ret = av_samples_alloc_array_and_samples(&arState->resampled_data, &arState->out_linesize, arState->out_nb_channels, arState->out_nb_samples, out_sample_fmt, 0);
if (ret < 0)
   {
    printf("av_samples_alloc_array_and_samples() error: Could not allocate destination samples.\n");
    return -1;
   }


if (arState->swr_ctx)
   {
    // do the actual audio data resampling
    // check audio conversion was successful
    int ret_num_samples = swr_convert(arState->swr_ctx,arState->resampled_data,arState->out_nb_samples,(const uint8_t**)decoded_audio_frame->data, decoded_audio_frame->nb_samples);
    //int ret_num_samples = swr_convert_frame(arState->swr_ctx,arState->resampled_data,arState->out_nb_samples,(const uint8_t**)decoded_audio_frame->data, decoded_audio_frame->nb_samples);

    if (ret_num_samples < 0)
       {
        printf("swr_convert_error.\n");
        return -1;
       }


    // get the required buffer size for the given audio parameters
    // check audio buffer size
    arState->resampled_data_size = av_samples_get_buffer_size(&arState->out_linesize,   arState->out_nb_channels,ret_num_samples,out_sample_fmt,1);

    if (arState->resampled_data_size < 0)
       {
        printf("av_samples_get_buffer_size error.\n");
        return -1;
       }
   } else {
           printf("swr_ctx null error.\n");
           return -1;
          }



// copy the resampled data to the output buffer
memcpy(out_buf, arState->resampled_data[0], arState->resampled_data_size);


// flush the swr context
int delayed = swr_convert(arState->swr_ctx,arState->resampled_data,arState->out_nb_samples,NULL,0);



if (arState->resampled_data)
   {
    av_freep(&arState->resampled_data[0]);
   }

av_freep(&arState->resampled_data);
arState->resampled_data = NULL;

int ret_data_size = arState->resampled_data_size;



return ret_data_size;
}
int重采样帧(VideoState*VideoState,AVFrame*decoded\u audio\u frame,enum AVSampleFormat out\u sample\u fmt,uint8\u t*out\u buf)
{
int in_sample_rate=videoState->audio->ptrAudioCodecCtx->sample_rate;
int out_sample_rate=采样率;
//获取AudioResamplingState结构的实例,如果为NULL,则创建
AudioResamplingState*arState=getAudioResampling(视频状态->音频->ptrAudioCodecCtx\>频道布局);
如果(!arState->swr\u ctx)
{
printf(“swr_alloc error.\n”);
返回-1;
}
//获取输入音频通道
arState->in_channel\u layout=(视频状态->音频->ptrAudioCodecCtx->频道==
av获取频道布局频道(视频状态->音频->ptrAudioCodecCtx->频道布局)?
视频状态->音频->ptrAudioCodecCtx->频道布局:
av获取默认频道布局(视频状态->音频->ptrAudioCodecCtx->频道);
//检查输入音频通道是否正确检索
如果(arState->in\u channel\u layout out\u channel\u layout=AV\u CH\u layout\u立体声;
//检索音频采样数(每个通道)
arState->in_nb_samples=解码的音频帧->nb_samples;
如果(arState->in_nb_samples swr_ctx,“in_channel_布局”,arState->in_channel_布局,0);
av_opt_set_int(arState->swr_ctx,“采样率内”,采样率内,0);
av-opt-set-sample-fmt(arState->swr-ctx,“in-sample-fmt”,videoState->audio->PTRAUDIOCOCTX->sample-fmt,0);
//设置用于重采样的SwrContext参数
av_opt_set_int(arState->swr_ctx,“输出通道布局”,arState->输出通道布局,0);
av_opt_set_int(arState->swr_ctx,“输出采样率”,输出采样率,0);
av_opt_set_sample_fmt(arState->swr_ctx,“out_sample_fmt”,out_sample_fmt,0);
//设置用户参数后初始化SWR上下文
int ret=swr_init(arState->swr_ctx);
如果(ret<0)
{
printf(“未能初始化重采样上下文。\n”);
返回-1;
}
//检索输出样本数,考虑渐进延迟
int64_t delay=swr_get_delay(arState->swr_ctx,videoState->audio->ptrAudioCodecCtx->sample_rate)+arState->in_nb_samples;
arState->out\u nb\u samples=av\u rescale\r(延迟、out\u sample\u比率、in\u sample\u比率、av\u取整);
//检查输出样本编号是否已正确重新缩放
如果(arState->out\u nb\u samples out\u nb\u channels=av\u get\u channel\u layout\u nb\u channels(arState->out\u channel\u layout);
//为arState->重采样数据和填充数据分配数据指针数组
//相应的指针和线条大小
//检查重新采样数据的内存分配是否成功
ret=av_样本、alloc_数组和_样本(&arState->重采样的_数据,&arState->out_线条尺寸、arState->out_nb_通道、arState->out_nb_样本、out_样本、fmt,0);
如果(ret<0)
{
printf(“av_samples_alloc_array_and_samples()错误:无法分配目标样本。\n”);
返回-1;
}
如果(arState->swr\U ctx)
{
//进行实际的音频数据重采样
//检查音频转换是否成功
int ret_num_samples=swr_convert(arState->swr_ctx,arState->resampled_data,arState->out_nbu samples,(const uint8_t**)解码的_音频_帧->数据,解码的_音频_帧->nb_样本);
//int ret_num_samples=swr_convert_frame(arState->swr_ctx,arState->重采样数据,arState->out_nbu samples,(const uint8_t**)解码音频帧->数据,解码音频帧->nb_采样);
如果(样本数<0)
{
printf(“swr_转换_错误。\n”);
返回-1;
}
//获取给定音频参数所需的缓冲区大小
//检查音频缓冲区大小
arState->resampled_data_size=av_samples_get_buffer_size(&arState->out_linesize,arState->out_nb_channels,ret_num_samples,out_sample_fmt,1);
如果(arState->重采样数据大小<0)
{
printf(“av样本获取缓冲区大小错误。\n”);
返回-1;
}
}否则{
printf(“swr_ctx空错误。\n”);
返回-1;
}
//将重新采样的数据复制到输出缓冲区
memcpy(out\u buf,arState->resampled\u data[0],arState->resampled\u data\u size);
//刷新swr上下文
int delayed=swr\u convert(arState->swr\u ctx,arState->resampled\u data,arState->out\u nb\u samples,NULL,0);
if(arState->重采样数据)
{
av_freep(&arState->重采样数据[0]);
}
av_freep(&arState->重采样数据);
arState->resampled_data=NULL;
int ret_data_size=arState->resampled_data_size;
返回ret_数据大小;
}
我也尝试使用如图所示的过滤器,但我的输出只是噪声

这是我的过滤代码

int  ResampleFrame(AVFrame *frame, uint8_t *out_buf)
{
   /* Push the decoded frame into the filtergraph */
    qint32 ret;
    ret = av_buffersrc_add_frame_flags(buffersrc_ctx1, frame, AV_BUFFERSRC_FLAG_KEEP_REF);
    if (ret < 0) 
       {
        printf("ResampleFrame: Error adding frame to buffer\n");
        // Delete input frame and return null
        av_frame_unref(frame);
        return 0;
    }


    //printf("resampling\n");
    AVFrame *resampled_frame = av_frame_alloc();


    /* Pull filtered frames from the filtergraph */
    ret = av_buffersink_get_frame(buffersink_ctx1, resampled_frame);

    /* Set the timestamp on the resampled frame */
    resampled_frame->best_effort_timestamp = resampled_frame->pts;

    if (ret < 0) 
       {
        av_frame_unref(frame);
        av_frame_unref(resampled_frame);
        return 0;
       }


    int buffer_size = av_samples_get_buffer_size(NULL,   2,resampled_frame->nb_samples,AV_SAMPLE_FMT_S16,1);

    memcpy(out_buf,resampled_frame->data,buffer_size);

    //av_frame_unref(frame);
    av_frame_unref(resampled_frame);
    return buffer_size;
}





QString filter_description1 = "aresample=48000,aformat=sample_fmts=s16:channel_layouts=stereo,asetnsamples=n=1024:p=0";

int InitAudioFilter(AVStream *inputStream) 
{

    char args[512];
    int ret;
    const AVFilter *buffersrc = avfilter_get_by_name("abuffer");
    const AVFilter *buffersink = avfilter_get_by_name("abuffersink");
    AVFilterInOut *outputs = avfilter_inout_alloc();
    AVFilterInOut *inputs = avfilter_inout_alloc();
    filter_graph = avfilter_graph_alloc();


    const enum AVSampleFormat out_sample_fmts[] = {AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE};
    const int64_t out_channel_layouts[] = {AV_CH_LAYOUT_STEREO, -1};
    const int out_sample_rates[] = {48000, -1};

    snprintf(args, sizeof(args), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%" PRIx64,
                         inputStream->codec->time_base.num, inputStream->codec->time_base.den,
                         inputStream->codec->sample_rate,
                         av_get_sample_fmt_name(inputStream->codec->sample_fmt),
                         inputStream->codec->channel_layout);


    ret = avfilter_graph_create_filter(&buffersrc_ctx1, buffersrc, "in", args, NULL, filter_graph);

    if (ret < 0) 
       {
        printf("InitAudioFilter: Unable to create buffersrc\n");
        return -1;
       }

    ret = avfilter_graph_create_filter(&buffersink_ctx1, buffersink, "out", NULL, NULL, filter_graph);

    if (ret < 0) 
       {
        printf("InitAudioFilter: Unable to create buffersink\n");
        return ret;
       }

    // set opt SAMPLE FORMATS
    ret = av_opt_set_int_list(buffersink_ctx1, "sample_fmts", out_sample_fmts, -1, AV_OPT_SEARCH_CHILDREN);

    if (ret < 0) 
       {
        printf("InitAudioFilter: Cannot set output sample format\n");
        return ret;
       }

    // set opt CHANNEL LAYOUTS
    ret = av_opt_set_int_list(buffersink_ctx1, "channel_layouts", out_channel_layouts, -1, AV_OPT_SEARCH_CHILDREN);

    if (ret < 0) {
        printf("InitAudioFilter: Cannot set output channel layout\n");
        return ret;
    }

    // set opt OUT SAMPLE RATES
    ret = av_opt_set_int_list(buffersink_ctx1, "sample_rates", out_sample_rates, -1, AV_OPT_SEARCH_CHILDREN);

    if (ret < 0) 
       {
        printf("InitAudioFilter: Cannot set output sample rate\n");
        return ret;
       }

    /* Endpoints for the filter graph. */
    outputs -> name = av_strdup("in");
    outputs -> filter_ctx = buffersrc_ctx1;
    outputs -> pad_idx = 0;
    outputs -> next = NULL;

    /* Endpoints for the filter graph. */
    inputs -> name = av_strdup("out");
    inputs -> filter_ctx = buffersink_ctx1;
    inputs -> pad_idx = 0;
    inputs -> next = NULL;


    if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_description1.toStdString().c_str(), &inputs, &outputs, NULL)) < 0) 
       {
        printf("InitAudioFilter: Could not add the filter to graph\n");
       }


    if ((ret = avfilter_graph_config(filter_graph, NULL)) < 0) 
       {
        printf("InitAudioFilter: Could not configure the graph\n");
       }

    /* Print summary of the sink buffer
     * Note: args buffer is reused to store channel layout string */
    AVFilterLink *outlink = buffersink_ctx1->inputs[0];
    av_get_channel_layout_string(args, sizeof(args), -1, outlink->channel_layout);

    QString str = args;
    printf("Output: srate:%dHz fmt:%s chlayout: %s\n", (int) outlink->sample_rate, 
                                                      av_get_sample_fmt_name((AVSampleFormat) outlink->format),
                                                      str.toStdString().c_str());


    filterGraphInitialized_ = true; 
}
int重采样帧(AVFrame*frame,uint8\u t*out\u buf)
{
/*将解码帧推入filtergraph*/
qint32 ret;
ret=av\U buffersrc\U add\U frame\U标志(buffersrc\U ctx1,frame,av\U buffersrc\U标志\U KEEP\U REF);
如果(ret<0)
{
printf(“重采样帧:将帧添加到缓冲区时出错\n”);
//删除输入帧并返回null
av_帧_unref(帧);
返回0;
}
//printf(“重采样”);
AVFrame*重采样的帧=av帧;
/*从filtergraph中拉出已过滤的帧*/
ret=av_缓冲接收器_获取_帧(缓冲接收器_ctx1,重采样_帧);
/*在重新采样的帧上设置时间戳*/
重采样帧->最佳努力时间戳=重采样帧->pts;