Wizard Notes

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

双2次フィルタの自作Pythonライブラリ PyQuadFilter 更新 - フレームベース処理対応

f:id:Kurene:20210104122525p:plain

双2次フィルタの自作Pythonライブラリである PyQuadFilterを更新しました。

PyAudioやPySoundDeviceと組み合わせることで、Pythonでも双2次フィルタを使った簡単なリアルタイム音響信号処理ができます。

GitHub - Kurene/pyquadfilter: Implementation of digital bi-quad filter in Python

更新内容

フレームごとの処理に対応しました。

pyquad = PyQuadFilter(sr)
pyquad.prepare_filter_online(n_ch=n_ch, length=length)
pyquad.set_params(filter_type, fc, q, gain_db)

# 例:コールバックの中身
def callback(x_frame, y_frame):
    # x_frame.shape and y_frame.shape are (n_channels, length) or (length, )
    y_frame[:] = pyquad.filter(x_frame, online=True)

例えば、スレッドを立ててコールバックしつつ、メイン/他スレッドでpyquad.set_params でフィルタパラメタを設定することで、リアルタイムでフィルタの応答を変えることができます。

実現方法

2次IIRフィルタの処理では、過去2サンプルの入出力信号が必要になります。

従って、フレームベース処理で先頭およびその次の出力を計算する際に、前のフレームの入出力信号の内、後ろから2サンプル分の信号が必要になります。それをx_buf, y_bufに格納/保存しています。

@jit(nopython=True, nogil=True)
def compute_biquad_filter(length, x, y, x_buf, y_buf, b, a):
    """
    a[0] == 1.0
    """
    for k in range(length):
        y[k] = b[0] * x[k]\
             + b[1] * x_buf[1]\
             + b[2] * x_buf[0]\
             - a[1] * y_buf[1]\
             - a[2] * y_buf[0]
        x_buf[0] = x_buf[1]
        x_buf[1] = x[k]
        y_buf[0] = y_buf[1]
        y_buf[1] = y[k]

今後の更新について

最低限の機能の実装は完了しましたが、時間があれば以下のようなコードを追加したいと思ってます。

  • PyAudio/PySoundDevice を使ったリアルタイム処理のデモ
  • GUIでフィルタパラメタを触ってリアルタイムに音を加工するデモ

関連ページ

www.wizard-notes.com

www.wizard-notes.com