2016-09-20 338 views
0

我正尝试使用ffmpeg/libswresample在我的C++应用程序中重新采样流音频。改变样本宽度效果很好,结果听起来像人们期望的那样;但是,当改变采样率时,结果有点不明确。我不确定是否由于libswresample库的使用不正确,或者我误解了重采样理论。libswresample:swr_convert()没有产生足够的样本

这里是我的重采样过程,简化了示范的缘故:

//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的采样率到采样率为22050的256个采样进行降采样应产生128个采样,但swr_convert()正在产生112个采样。当用音频持续时间表达时,这也令人费解。在44100 = 5.8ms的256个采样,但是在22050 = 5.07ms的112个采样。下采样过程不应该改变重采样音频的持续时间吗?

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

+0

尝试使用更大尺寸的out_samples数组,我怀疑计算出了问题。 –

回答

2

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

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

+0

这样做的窍门,谢谢你的及时回复!因此,当在实时环境中使用时,下一次调用swr_convert()时,其输入样本应以前一个调用中省略的最后几个样本开始。它是否正确? – Tsherr

+0

不,swr_convert()为您缓存输入样本。只是不要指望所有样本在输入时同时出现,也就是说期望swr_convert()引入一个小的延迟。 –

+0

我明白了,现在有道理。再次感谢! – Tsherr