问题
I'm trying to use ffmpeg/libswresample to resample streaming audio in my c++ application. Changing the sample width works well and the result sounds as one would expect; however, when changing the sample rate the result is somewhat crackly. I am unsure if it is due to incorrect usage of the libswresample library, or if I'm misunderstanding the resampling theory.
Here is my resampling process, simplified for demonstration's sake:
//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);
I suspect that the reason the resampled audio does not sound right is because swr_convert()
returns 112, where I expect it to return 128 (the number of samples of the resampled audio):
Downsampling 256 samples from a samplerate of 44100 to a samplerate of 22050 should yield 128 samples, yet swr_convert()
is producing 112 samples. When expressed in terms of audio duration this is also puzzling. 256 samples at 44100 = 5.8 ms, but 112 samples at 22050 = 5.07 ms. Shouldn't the downsampling process not alter the duration of the resampled audio?
I have also stepped through an example provided with ffmpeg, in which swr_convert() also returns a smaller number than I would expect. So, I suspect that the problem is not due to a bug in libswresample but rather my own lack of understanding.
回答1:
The reason the number of samples is decreased is because the resampling filters over a number of temporally adjacent samples. Imagine that we're resampling using a 32-tap filter, sample 127 needs input 127-16 to 127+16 (or comparable positions corrected for the sample rate adjustment). Since you only have 128 input samples, you can only output up until 112 in this example. The rest is stored in an internal queue until the next input is available.
To get the final (trailing) samples (when the input is finished), input NULL as input, which will flush the internal queue.
来源:https://stackoverflow.com/questions/39587839/libswresample-swr-convert-not-producing-enough-samples