Wizard Notes

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

1次IIRオールパスフィルタでローパス/ハイパスフィルタを作る(Python実装)

信号処理に欠かせないオールパスフィルタ―の概要・使い方・利用例」では、オールパスフィルタによって低演算量で様々な周波数特性のフィルタを作成できることを紹介しました。

www.wizard-notes.com

この記事では、その具体例として1次IIRオールパスフィルタの並列回路でローパス/ハイパスフィルタを作成します。

1次IIRオールパスフィルタ

1次IIRオールパスフィルタの詳細はこちらの記事を参考にしてください。

今回は位相が90度遅れる周波数 fc を4つ用意し、それぞれのフィルタ係数用パラメタ λを算出しました。

sr   = 44100
worN = 4096

# 0.3, 2.8, 11.0, 17.6 kHz
fc_list = (sr/128, sr/16, sr/4, sr/2.5) 

fr_list = []
for fc in fc_list:
    lam = -(np.tan(np.pi*fc/sr)-1)/(np.tan(np.pi*fc/sr)+1)
    b = np.array([-lam, 1.0])
    a = np.array([1.0, -lam])
    label=f"lam={lam:0.3f}, fc={fc:.0f} Hz"

    w, h = freqz(b, a=a, worN=worN)
    freqs = w / np.pi * (sr//2)

    angle = np.angle(h)/np.pi*180
    angle[angle>0] = -180 - (180 - angle[angle>0])
    angle = -angle

各オールパスフィルタの位相特性は以下のようになります。

なお、今回はプロット用に手動で位相アンラッピングをしていますが、numpy.unwrapが便利です*1

ローパスフィルタ

以下は1次IIRオールパスフィルタを使ったローパスフィルタのブロック図と伝達関数です。

入力信号とオールパスフィルタ出力を足し合わせることで、最終的な出力信号となります。

h = 0.5*(h+1)

オールパスフィルタによって高周波では位相が逆相波に近づくため、この回路全体の振幅特性は以下のようなローパスフィルタの特性となります。

以下は回路全体の振幅特性のプロットです。なお、下図は横軸(周波数)を対数軸にしたバージョンです。

ハイパスフィルタ

以下は1次IIRオールパスフィルタを使ったハイパスフィルタのブロック図と伝達関数です。

結局のところ、オールパスフィルタ出力は符号を変えることで低周波になるほど逆位相に近づき、高周波になるほど入力信号と同位相に近づきます。

h = 0.5*(h-1)

従って、回路全体の出力では高周波が残るためハイパスフィルタの特性となります。

まとめ

Python1次IIRオールパスフィルタを使った並列回路でローパス/ハイパスフィルタを作りました。

なお、今回のフィルタは1次FIRフィルタの遅延素子を1次IIRオールパスフィルタに置き換えることで周波数特性の伸縮(周波数ワープ)をしているとも考えられます。

周波数ワープの詳細については以下の記事をご覧ください。

www.wizard-notes.com

*1:使用可能な numpyのバージョンは 1.21.0 以上