Wizard Notes

Python, JavaScript を使った音楽信号分析の技術録、作曲活動に関する雑記

Pythonとresample_polyでオーバーサンプリング

scipy.signal.resample_polyを使ってオーバーサンプリングを実装してみました。

resample_polyのデフォルトの設定では、パラメタβ=5.0のカイザー窓によるFIRローパスフィルタが使われています。

注意すべき箇所として、フィルタ長はresample_polyの引数では設定できません。仮に、アップ/ダウンサンプリング周波数の比率up/down の大きい値のほうを n_over、FIRフィルタ長をwin_lengthとすると、

win_length = n_over * 2 * 10 + 1

として自動的に決定しています。つまり、4倍オーバーサンプリングであればフィルタ長は81サンプルとなります。

以下に実際のコードを引用します。

scipy/signaltools.py at v1.0.0 · scipy/scipy · GitHub

# Design a linear-phase low-pass FIR filter
max_rate = max(up, down)
f_c = 1. / max_rate  # cutoff of FIR filter (rel. to Nyquist)
half_len = 10 * max_rate  # reasonable cutoff for our sinc-like function
h = firwin(2 * half_len + 1, f_c, window=window)

また、カットオフ周波数は元信号のナイキスト周波数がセットされますが、実用的にはもう少し低い周波数に設定したいことが多々あります(参考)。従って、事前にscipy.signal.firwinで任意のフィルタ長でフィルタ係数を生成し、resample_polyの引数windowに渡す方が良さそうです。

以下に、サンプリング周波数 48 kHzの白色雑音に対して、カイザー窓の形状パラメタとタップ数を変えてオーバーサンプリングを実行した例を示します。実行後、元信号との誤差を周波数領域で可視化しました。

オーバーサンプリング処理はそれなりに演算量がかかるためフィルタ長を短くしたいですが、トレードオフとしてフィルタ長を短くすると誤差が大きくなります。その比較の参考になれば幸いです。

カイザー窓のパラメタ(beta)を変えた場合

f:id:Kurene:20210124162525p:plain f:id:Kurene:20210124162546p:plain

FIRフィルタ長を変えた場合

カイザー窓のパラメタは5.0に固定しています。 f:id:Kurene:20210124162754p:plain f:id:Kurene:20210124162819p:plain

ソースコード

ライセンス:MIT