Libswresample: swr_convert()没有生成足够的样本

libswresample: swr_convert() not producing enough samples

本文关键字:样本 swr convert Libswresample      更新时间:2023-10-16

我试图使用ffmpeg/libswressample在我的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()返回112,我希望它返回128(重新采样音频的样本数):从44100个样本降采样256个样本到22050个样本应该产生128个样本,但swr_convert()产生112个样本。当用音频持续时间来表达时,这也是令人困惑的。44100处256个样本= 5.8 ms,而22050处112个样本= 5.07 ms。降采样过程不应该改变重采样音频的持续时间吗?

我还逐步完成了一个由ffmpeg提供的示例,其中swr_convert()返回的数字也比我预期的要小。所以,我怀疑这个问题不是由于libswresample中的错误,而是我自己缺乏理解。

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

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