C++ アプリケーションでストリーミング オーディオをリサンプリングするために 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 のサンプルを生成しています。オーディオの長さで表現すると、これも不可解です。44100 では 256 サンプル = 5.8 ミリ秒ですが、22050 では 112 サンプル = 5.07 ミリ秒です。ダウンサンプリング プロセスは、リサンプリングされたオーディオの長さを変更すべきではありませんか?
また、swr_convert() が予想よりも小さい数値を返す ffmpeg で提供されている例も確認しました。したがって、問題は libswresample のバグではなく、私の理解不足によるものだと思われます。