サンプリングレート変換の段

今作っているゲームでは音声の再生にWASAPIを使ってみているのですが、
PCの設定次第で出力される音声フォーマットが違うのでそれぞれ対応する必要があることに気付きました。

用意している音声データは16bit/44100Hzで、同じ出力フォーマットの環境だと問題ないものの
HDMI側の音声出力を使ってサウンドコントロールパネルから16bit/48000Hzの形式に変えると音が間延びして再生されます。
これを正しく再生させるための対応として、44100Hzの音声データを別のサンプリングレートに変換する必要が出てきました。
Unity等だとこの辺りは自動でやってくれそうですね。

というわけでサンプリングレート変換の方法は大まかに下の二つの模様。

  • 音声データをn倍したり1/nに間引く
  • フーリエ変換して周波数成分を取り出し、逆変換して戻す

……このあたりの知識はあまり無いのですが、後者の方法は見るからに大変そうな上にちゃんと戻せるのか不安なところがあります。
というわけで前者の方法を取ることにしました。


変換するサンプリングレートが24000から48000のように整数倍であれば、
1 7 10 8 というデータを 1 1 7 7 10 10 8 8 という感じに値を同じ数だけ増やしていけばよさそうです。
逆に半分にする場合は1つ飛ばしで値を取っていけばよし。

ただ44100から48000にするとなるとデータを1.0884倍にすることになるので、そのままだとデータの間に新たに追加していくことができません。
そこで一旦二つの最小公倍数である7056000Hzに変換し、そこからデータを間引いていく方法を使うとのこと。
倍率でいえば 44100 →(160倍)→ 7056000 →(1/147)→ 48000 。
ただしこの方法でも元の波形と変わっていることに変わりはないので、特に高周波の成分が折り返しノイズとして乗ってしまうようです。
ノイズを取るためには高周波数をカットするフィルタ、LPFをかけることになります。カットする周波数は44100Hzと48000Hzのうち低い方の半分である22050Hzよりも上。

ではこのLPFはどうやって計算すればいいのか、というのが新たな問題となりました。
そのあたりの知識も無いので、活用するは古くから(それほどでもない)伝わるCookbook formulae for audio equalizer biquad filter coefficients。以前はテキストファイルだったかと思いますが、今は成型されたHTMLとなって残っていますね。

これを使ってフィルタをかけることで、まだ若干のノイズが乗る場合があるものの無事48000Hzのデータに変換することができました。ノイズも大して気にならないレベルの筈。
一度データを160倍にして計算したりする必要がある関係上、どうしても変換に時間がかかってしまう点がネックですね。2分の曲の場合で10秒、長くて30秒くらいはかかりそうな予感。
初回のみ変換を待ってもらって以降は再利用していけばいいとはいえ気になる時間です。


参考用に変換前後のデータ(Waveファイル)を置いてみます。曲はbroox-lにあるやつ。

元データ(44100Hz)
変換後フィルタなし(48000Hz、耳によくない可能性があるので音量注意
変換後フィルタあり(48000Hz)

フィルタの前後で高周波成分が少なくなっている気がしなくもない……?殆ど分からないのはサンプルが悪いやつです。
ベル系の音だと比較的わかりやすい感じでした。
元の音をどれだけ歪ませないかはフィルタの性能次第という感じがあります。難しいですねー。

音声データの変換はサンプリングレートのほかにビットレート変換もあります。
こちらも対応する必要がありますが、サンプリングレートに比べると分かりやすいので気は楽です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です