Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ FFmpeg-噪声较大的重采样音频_C++_Qt_Ffmpeg_Pcm_Libswresample - Fatal编程技术网

C++ FFmpeg-噪声较大的重采样音频

C++ FFmpeg-噪声较大的重采样音频,c++,qt,ffmpeg,pcm,libswresample,C++,Qt,Ffmpeg,Pcm,Libswresample,我不熟悉auido重采样。我试着从两个视频中重新采样auido流。第一个输出接近原始输出,但有噪声,另一个几乎充满噪声 第一个的信息 128 kb/s,48.0kHz,2个通道,AACLC 第二个的信息 384 kb/s,48.0 kHz,6通道,AACLC 我发现,当我将样本量设置为16时,第一个样本效果很好,但仍然有噪音。另一个工作得很糟糕,但仍然有声音。什么以及如何确定输出样本量?虽然我使用channels*av\u get\u bytes\u per\u sample((AVSample

我不熟悉auido重采样。我试着从两个视频中重新采样auido流。第一个输出接近原始输出,但有噪声,另一个几乎充满噪声

第一个的信息

128 kb/s,48.0kHz,2个通道,AACLC

第二个的信息

384 kb/s,48.0 kHz,6通道,AACLC

我发现,当我将样本量设置为16时,第一个样本效果很好,但仍然有噪音。另一个工作得很糟糕,但仍然有声音。什么以及如何确定输出样本量?虽然我使用
channels*av\u get\u bytes\u per\u sample((AVSampleFormat)output\u fmt)
作为输出样本大小,因为我希望它与原始样本相同,但它根本没有声音

MyResampling.cpp

bool MyResample::open(AVCodecParameters* par) {
    if (!par) {
        std::cout << "par is null" << std::endl;
        return false;
    }   
    audio_context = swr_alloc_set_opts(
        audio_context, av_get_default_channel_layout(2), (AVSampleFormat)output_fmt,
        par->sample_rate, av_get_default_channel_layout(par->channels), (AVSampleFormat)par->format, par->sample_rate,
        0, 0);

    avcodec_parameters_free(&par);
    int ret = swr_init(audio_context);
    if (ret != 0) {
        std::cout << "failed to open audio codec" << std::endl;
    }
    return true;
}

int MyResample::resample(AVFrame* frame, unsigned char* output)
{
    if (!frame)
        return 0;
    if (!output)
        av_frame_free(&frame);

    uint8_t* data[2] = { 0 };
    data[0] = output;
    int ret = swr_convert(audio_context, data, frame->nb_samples, (const uint8_t**)frame->data, frame->nb_samples);
    //int size =  ret * frame->channels * av_get_bytes_per_sample((AVSampleFormat)output_fmt);
    int size = av_samples_get_buffer_size(nullptr, frame->channels, frame->nb_samples, (AVSampleFormat)output_fmt, 1);
    if (ret < 0)
        return ret;
    return size;
}
bool open()
{
    close();
    QAudioFormat fmt;
    fmt.setSampleRate(sample_rate); // from audioStream->codecpar->sample_rate
    fmt.setSampleSize(16); //
    fmt.setChannelCount(channels); // from audioStream->codecpar->channels
    fmt.setCodec("audio/pcm");
    fmt.setByteOrder(QAudioFormat::LittleEndian);
    fmt.setSampleType(QAudioFormat::UnSignedInt);
    output = new QAudioOutput(fmt);
    io = output->start();
    if (io)
        return true;
    return false;
}

bool write(const unsigned char* data, int data_size)
{
    if (!data || data_size <= 0)
        return false;
    if (!output || !io)
    {
        return false;
    }
    int size = io->write((char*)data, data_size);
    if (data_size != size)
        return false;
    return true;
}
MyAudioPlayer::open();
unsigned char* pcm = new unsigned char[1024 * 1024];
if (demux.get_media_type() == 1) { // audio 
    audio_decode.sendPacket(pkt);
    AVFrame* frame = audio_decode.receiveFrame();
    int len = resample.resample(frame, pcm);
    while (len > 0) {
        if (MyAudioPlayer::check_space() >= len) {
            MyAudioPlayer::write(pcm, len);
            break;
        }
        msleep(1);
    }               
}

如果您对最终质量和噪声有问题,可能是您误解了执行重采样的正确方法,或者配置中存在错误

看看这个例子:

我不熟悉FFmpeg API,因为我倾向于使用它来进行重采样

关于旧示例,以下是使用FFMPEG执行基本重采样的步骤:

  • 从配置重采样上下文开始:
  • 根据输入数据类型和预期的输出格式,需要指定正确的格式。这在以下方面是等价的:

  • 以正确的格式从任何地方获取数据,并估计采样计数 之后,您可以通过几个步骤执行重采样:

  • 估计输出样本的数量
  • 为输出文件分配内存
  • 将输入数据转换为预期的输出格式
  • 别忘了释放你的记忆
  • 如果存在噪波,可能是输入格式和输出格式不正确,或者重采样质量低


    例如,如果得到的样本少于预期,不要惊慌。这是常见的行为,因为过滤的工作方式。要获得剩余的尾迹,您可以使用NULL作为输入执行步骤5,这将刷新内部数据。

    如果您对最终质量和噪声有问题,可能是您误解了执行重采样的正确方法,或者配置中存在错误

    看看这个例子:

    我不熟悉FFmpeg API,因为我倾向于使用它来进行重采样

    关于旧示例,以下是使用FFMPEG执行基本重采样的步骤:

  • 从配置重采样上下文开始:
  • 根据输入数据类型和预期的输出格式,需要指定正确的格式。这在以下方面是等价的:

  • 以正确的格式从任何地方获取数据,并估计采样计数 之后,您可以通过几个步骤执行重采样:

  • 估计输出样本的数量
  • 为输出文件分配内存
  • 将输入数据转换为预期的输出格式
  • 别忘了释放你的记忆
  • 如果存在噪波,可能是输入格式和输出格式不正确,或者重采样质量低

    例如,如果得到的样本少于预期,不要惊慌。这是常见的行为,因为过滤的工作方式。要获得剩余的尾随,您可以使用NULL作为输入执行步骤5,这将刷新内部数据

    //Set up resampling context
    SwrContext *swr = swr_alloc();
    av_opt_set_channel_layout(swr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
    av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
    av_opt_set_int(swr, "in_sample_rate", 44100, 0);
    av_opt_set_int(swr, "out_sample_rate", 22050, 0);
    av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
    av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0);
    swr_init(swr);
    
    ----------------------------------------
    | *AV_SAMPLE_FMT_S16* | `std::int16_t` |
    | *AV_SAMPLE_FMT_S32* | `std::int32_t` |
    | *AV_SAMPLE_FMT_FLT* | `float`        |
    | *AV_SAMPLE_FMT_DBL  | `double`       |
    | *AV_SAMPLE_FMT_U8P* | `std::uint8_t` |
    | ...                 |                |
    
    uint8_t* out_samples;
    int out_num_samples = av_rescale_rnd(swr_get_delay(swr, in_samplerate) + in_num_samples, out_samplerate, in_samplerate, AV_ROUND_UP);
    
    av_samples_alloc(&out_samples, NULL, out_num_channels, out_num_samples, AV_SAMPLE_FMT_FLT, 0);
    
    out_num_samples = swr_convert(swr, &out_samples, out_num_samples, &in_samples, in_num_samples);
    
    av_freep(&out_samples);
    swr_free(&swr);