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

时间:2016-09-20 07:11:52

标签: c++ audio ffmpeg resampling downsampling

我正在尝试使用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()返回112,我希望它返回128(重采样音频的样本数): 将256个样本从44100的采样率下采样到22050的采样率应该产生128个样本,而swr_convert()产生112个样本。当以音频持续时间表示时,这也令人费解。 256个样本在44100 = 5.8毫秒,但112个样本在22050 = 5.07毫秒。下采样过程不应该改变重采样音频的持续时间吗?

我还介绍了一个ffmpeg提供的示例,其中swr_convert()也返回一个比我预期的更小的数字。因此,我怀疑问题不是由于libswresample中的错误而是由于我自己缺乏理解。

1 个答案:

答案 0 :(得分:2)

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

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