Я пытаюсь использовать ffmpeg/libswresample для передискретизации потокового аудио в моем приложении С++. Изменение ширины семпла работает хорошо, и результат звучит так, как и следовало ожидать; однако при изменении частоты дискретизации результат несколько трескается. Я не уверен, связано ли это с неправильным использованием библиотеки 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 (количество выборок звука передискретизации): дают 128 образцов, а swr_convert()
производит 112 образцов. Когда это выражается в терминах продолжительности звука, это также вызывает недоумение. 256 выборок на 44 100 = 5,8 мс, но 112 выборок на 22 050 = 5,07 мс. Разве процесс понижения частоты дискретизации не должен изменять продолжительность передискретизированного звука?
Я также рассмотрел пример с ffmpeg, в котором swr_convert() также возвращает меньшее число, чем я ожидал. Итак, я подозреваю, что проблема связана не с ошибкой в libswresample, а скорее с моим собственным непониманием.