libswresample: swr_convert() 没有产生足够的样本

libswresample: swr_convert() not producing enough samples

我正在尝试使用 ffmpeg/libswresample 在我的 C++ 应用程序中重新采样流式音频。更改样本宽度效果很好,结果听起来符合预期;但是,当更改采样率时,结果有些不稳定。我不确定这是否是由于 libswresample 库的使用不正确,或者我是否误解了重采样理论。

这是我的重采样过程,为演示起见进行了简化:

//Externally supplied data
const uint8_t* in_samples //contains the audio data to be resampled
int in_num_samples = 256

//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);

//Perform the resampe
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);

我怀疑重新采样的音频听起来不正确的原因是因为 swr_convert() returns 112,我希望它是 return 128(采样数重采样音频): 将 256 个样本从 44100 的采样率下采样到 22050 的采样率应该产生 128 个样本,但 swr_convert() 正在产生 112 个样本。当用音频持续时间表示时,这也令人费解。 44100 处的 256 个样本 = 5.8 毫秒,但 22050 处的 112 个样本 = 5.07 毫秒。下采样过程不应该改变重采样音频的持续时间吗?

我还逐步完成了 ffmpeg 提供的示例,其中 swr_convert() 也 return 比我预期的要小。所以,我怀疑问题不是因为libswresample中的错误,而是因为我自己缺乏理解。

样本数量减少的原因是因为重采样过滤了许多时间上相邻的样本。想象一下,我们正在使用 32 抽头滤波器进行重采样,样本 127 需要输入 127-16 到 127+16(或针对采样率调整校正的可比位置)。由于您只有 128 个输入样本,因此在此示例中您最多只能输出 112 个样本。其余的存储在内部队列中,直到下一个输入可用。

要获得最终(尾随)样本(当输入完成时),输入 NULL 作为输入,这将刷新内部队列。