gpt4 book ai didi

audio - FFmpeg - 从 AV_SAMPLE_FMT_FLTP 重采样到 AV_SAMPLE_FMT_S16 音质非常差(缓慢、走调、噪音)

转载 作者:行者123 更新时间:2023-12-01 17:43:19 27 4
gpt4 key购买 nike

我对新 ffmpeg 中的重采样结果感到困惑。我将 AAC 音频解码为 PCM,ffmpeg 显示音频信息为:

Stream #0:0: Audio: aac, 44100 Hz, stereo, fltp, 122 kb/s

在新的ffmpeg中,输出样本是fltp格式,所以我必须将其从AV_SAMPLE_FMT_FLTP转换为AV_SAMPLE_FMT_S16

PS:老的ffmpeg如libavcodec 54.12.100中,直接是S16,所以不需要重采样,没有任何音质问题

然后我尝试了三种重新采样的方法,

  1. 使用 swr_convert

  2. 使用 avresample_convert

  3. 手动转换

但结果都是一样的,音质很差,很慢而且走调,还有些噪音。

我的重采样代码如下:

void resampling(AVFrame* frame_, AVCodecContext* pCodecCtx, int64_t want_sample_rate, uint8_t* outbuf){
SwrContext *swrCtx_ = 0;
AVAudioResampleContext *avr = 0;

// Initializing the sample rate convert. We only really use it to convert float output into int.
int64_t wanted_channel_layout = AV_CH_LAYOUT_STEREO;

#ifdef AV_SAMPLEING
avr = avresample_alloc_context();
av_opt_set_int(avr, "in_channel_layout", frame_->channel_layout, 0);
av_opt_set_int(avr, "out_channel_layout", wanted_channel_layout, 0);
av_opt_set_int(avr, "in_sample_rate", frame_->sample_rate, 0);
av_opt_set_int(avr, "out_sample_rate", 44100, 0);
av_opt_set_int(avr, "in_sample_fmt", pCodecCtx->sample_fmt, 0); //AV_SAMPLE_FMT_FLTP
av_opt_set_int(avr, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
av_opt_set_int(avr, "internal_sample_fmt", pCodecCtx->sample_fmt, 0);
avresample_open(avr);
avresample_convert(avr, &outbuf, frame_->linesize[0], frame_->nb_samples, frame_->extended_data, frame_->linesize[0], frame_->nb_samples);
avresample_close(avr);
return;
#endif

#ifdef USER_SAMPLEING
if (pCodecCtx->sample_fmt == AV_SAMPLE_FMT_FLTP)
{
int nb_samples = frame_->nb_samples;
int channels = frame_->channels;
int outputBufferLen = nb_samples & channels * 2;
auto outputBuffer = (int16_t*)outbuf;

for (int i = 0; i < nb_samples; i++)
{
for (int c = 0; c < channels; c++)
{
float* extended_data = (float*)frame_->extended_data[c];
float sample = extended_data[i];
if (sample < -1.0f) sample = -1.0f;
else if (sample > 1.0f) sample = 1.0f;
outputBuffer[i * channels + c] = (int16_t)round(sample * 32767.0f);
}
}
return;
}
#endif
swrCtx_ = swr_alloc_set_opts(
NULL, //swrCtx_,
wanted_channel_layout,
AV_SAMPLE_FMT_S16,
want_sample_rate,
pCodecCtx->channel_layout,
pCodecCtx->sample_fmt,
pCodecCtx->sample_rate,
0,
NULL);

if (!swrCtx_ || swr_init(swrCtx_) < 0) {
printf("swr_init: Failed to initialize the resampling context");
return;
}

// convert audio to AV_SAMPLE_FMT_S16
int swrRet = swr_convert(swrCtx_, &outbuf, frame_->nb_samples, (const uint8_t **)frame_->extended_data, frame_->nb_samples);
if (swrRet < 0) {
printf("swr_convert: Error while converting %d", swrRet);
return;
}
}

应该做什么?

PS1:用ffplay玩就可以了。

PS2:将重采样S16 PCM保存到文件中并播放会出现同样的音质问题。

非常感谢您的帮助和建议!

<小时/>

我还注意到,在旧的ffmpeg中,aac被识别为FLT格式并直接解码为16位PCM,而在新的ffmpeg中,aac被视为FLTP格式并产生仍然32位IEEE浮点输出。

因此,相同的代码对于不同版本的 ffmpeg 将产生完全不同的输出。那么,我想问一下,在新版本中,将AAC音频转换为16位PCM的正确方法是什么?

提前非常感谢!

最佳答案

您需要记住 AV_SAMPLE_FMT_FLTP 是平面模式。如果您的代码需要 AV_SAMPLE_FMT_S16(交错模式)输出,则需要在转换后对样本重新排序。考虑 2 个音频 channel 并使用交错模式,样本排序为“c0, c1, c0, c1, c0, c1, ...”。平面模式为“c0, c0, c0, ..., c1, c1, c1, ...”。

类似问题:What is the difference between AV_SAMPLE_FMT_S16P and AV_SAMPLE_FMT_S16?

详细信息请参见:http://www.ffmpeg.org/doxygen/2.0/samplefmt_8h.html

关于audio - FFmpeg - 从 AV_SAMPLE_FMT_FLTP 重采样到 AV_SAMPLE_FMT_S16 音质非常差(缓慢、走调、噪音),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22822515/

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