以前にwavファイルのサンプリングレート変換を試してみた内容の続きです。
(2023/10/31 追記)FFT以外の補間法も試してみました。
前回は44100Hzのデータを48000Hzに変換する際に、44100のデータを整数倍に増やして間引く方法を取っていました。
結果的に比較的それなりに変換できることはできたのですが、音に若干のノイズが入る割に変換時間もある程度かかるという問題がありました。
これを何とかできないかということで、もう一つの方法
- フーリエ変換して周波数成分を取り出し、逆変換して戻す
を試してみました。
44100Hzの波形をN=44100でフーリエ変換すると各周波数ごとのデータを取り出せるので、これに空白のデータを追加してN=48000の状態にして逆変換すると48000Hzの波形を復元できるというやつです。
フーリエ変換と言えばFFT。これを自前で組むのは大変な上に早くなさそうなので(理論も大して分かっていない)既存のライブラリを使います。
PFFFT
最初に使ってみたライブラリはPFFFT。ライセンスはほぼ3条項BSDライセンスのようなFFTPACKライセンス。使い方はシンプル、そして速いとのこと。
まず音声データを8192ポイントでフーリエ変換してそのまま逆変換すると本当に元に戻るのかを試してみました。……確かにきれいに元の音が再現されました。
では44100ポイントだとどうか、と思ったところで問題が発生。
FFTは高速に計算を行う関係上、指定できるNの値に制限があることがよくあります。このPFFFTの場合は
N=(2^a)*(3^b)*(5^c), a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128, 144, 160, etc are all acceptable lengths)
という制限。
44100は2*2*3*3*5*5*7*7なので、7の倍数はNとして指定できないわけですね。
別に44100ポイントで変換しなくてもいいのかも知れませんが、さておき違うNでも変換できるライブラリを探してみることにしました。
meow_fft
次に試したのはmeow_fft。ライセンスは0条項BSD。
ファイルはヘッダーファイル1つのみ、速度はPFFFTには劣るもののお手軽とのこと。
このライブラリで使用できるNの値は偶数ならだいたい問題なさそうです。とは云え2の累乗数等でない場合はFFTではなく通常のDFTになるので、比較して遅くはなります。
ともあれこれを使って44100Hz→48000Hzの変換を試したところ、無事きれいに変換することができました。
フーリエ変換は大変そうなイメージがありましたが、むしろ前回の間引き法よりも楽に変換できた感もあります。
変換速度も遅いどころか前回の2/3程度の時間で終わりました。なんとまあ。
変換結果
曲は製作中のゲームの仮曲。
- A.元データ(44100Hz)
- B.データ間引き(48000Hz)
- C.フーリエ変換(48000Hz)
元データの時点で高音がやや刺さっている箇所について、Bではノイズが入っていることが分かります。間引いた後のLPFがうまく効いていないのでしょうか?
Cではノイズが増えていることもなく、問題なさそうです。細かく見れば位相のずれ等があるかと思いますが、まあ大丈夫でしょう。
というわけで、音声のビットレート変換は「フーリエ変換の方が手軽で速く質がいい」という結果に終わりました。
以前にFFTしたものをそのままIFFTしたら波形がきれいには戻らなかった記憶があったのですが、そんなことはありませんでした。どっとはらい。