Keyword: サンプリング周波数変換、リサンプリング、サンプリングレート変換、アルゴリズム・方法
サンプリング周波数変換とは、オーディオデータなどのデジタル信号を、異なるサンプリング周波数の信号に変換する処理のことです。例えば、CD規格の44.1 kHzのデータをDVDの48kHzへ変換するときに使用します。
■原理
ここで、サンプリング周波数 fiからfoへの変換を考えます。fiとfoは単純な整数比である必要はありません。
Wikiでは、fiとfoの最小公倍数を求め、ゼロ値の内挿によるアップサンプリングを行い、LPFを通し、間引きする といった方法が示されています。しかし、以下の方法を使えば任意のサンプリング周波数にダイレクトに(ワンパスで)変換できます。
サンプリング周波数 fiからfoへ変換するということは、入力サンプルのfi/foおきに入力サンプルの補間値を求めることといいかえることができます。
ここで、
Xn:入力信号のn番目の値
Ym:出力信号のm番目の値
X'(t):入力信号の時刻tの補間値(tは実数)
とすると、
ここで、m x fi / foを、整数部(n)と小数部(dn)に分ける。
このとき、Ymは次式で求められます
ここで、
■解説
繰り返しになりますが、サンプリング周波数 fiからfoへ変換するということは、入力サンプルのfi/foおきに入力サンプルの補間値を求めることです。
ただ、ここでの補間は、見かけの滑らかさとは違うことに注意が必要です。直線補間やスプライン補間などは折り返し雑音(エイリアシング)が酷くて実際には使えません。サンプリング周波数変換では式(1.1)と式(1.2)のようにsinc関数というもので補間します。
sinc関数の周波数特性は矩形特性で、カットオフ周波数がナイキスト周波数(fs/2)で急峻に減衰する理想のLPF特性です。
sinc関数の周波数特性
ところで、sinc関数ってとても美しい式だと思いませんか。矩形の周波数特性の応答波形を、こんなシンプルな式で表現できます。しかも、いきなり原点が0で割るという、おちゃめな部分もあります。私がこれまでデジタル信号処理に携わってた中で一番お気に入りの関数です。
閑話休題。
式(1.1)と式(1.2)は、FIRデジタルフィルタの畳みこみ演算と似ています。違いはフィルタの係数列が固定ではなく、dnによって出力サンプル点毎に変化(シフト)する点です。これにより、フィルタをかけながら入力サンプル間の途中の値を求めているのです。
アップサンプリングとダウンサンプリングで式が異なるのは、sinc関数のカットオフ周波数(fc)を、アップサンプリングの場合は入力側のナイキスト周波数(fi/2)、ダウンサンプリングの場合は出力側のナイキスト周波数(fo/2)に合わせるためです。ダウンサンプリングの場合は、sinc関数がfiとfoの比によって横に伸長されたイメージです。
ここで、もうお気づきかもしれませんが、sinc関数は無限長のため、このままでは実装できません。なんらかの方法で有限長にする必要があります。
sinc関数はxが大きくなるにつれ振幅が次第に減少していく関数なので、適当な時点で打ち切ればよさそうですが、この部分はもう少しテクニックがあります。次回は応用編として、sinc関数を有限長にする方法について書こうと思います。
■おまけ(実践)
ここにWAVフォーマットのファイル in.wavがあるとします(このサンプリング周波数は任意です)。
これを、各種のコマンドプログラムで、44.1KHzのサンプリング周波数のout.wavに変換してみます。
FFmpegの場合
> ffmpeg -i in.wav -ar 44100 -y out.wav
SoXの場合
> sox in.wav -D out.wav rate 44100
AqResampleの場合
> AqResampleCmd in.wav 44100 out.wav
なお、最近のFFmpegはSoXのリサンプリングエンジンlibsoxrを内包しています。
以下のように"-af aresample=resampler=soxr"を指定することでlibsoxrを使用できます。
> ffmpeg -i in.wav -af aresample=resampler=soxr -ar 44100 out.wav
基本的に、各プログラムの変換結果の違いは、使用している補間の関数(フィルタ係数)の違いとなります。
■リンク
- 次の記事「サンプリング周波数変換(リサンプリング)技術- 応用編」
- 「FFmpeg」 https://www.ffmpeg.org/
- 「SoX」 http://sox.sourceforge.net/
- 「AqResample」(当社リンク)