ローパスフィルタ 【Python 音声音響信号処理】

本記事では、Python上でローパスフィルタを設計してFIRを適用して実際にフィルタをかけてみます。

FIRフィルタの実装は前回の記事を用いています。

あわせて読みたい
FIRフィルタ 【Python 音声音響信号処理】 本記事では、PythonでFIRフィルタを実装します。 FIRフィルタの構成 FIRフィルタは次式で定義されます。 $$y[n] = \sum_{i=0}^N b_i x[n-i]$$ ここで、\(b_i\)はi番目の...
目次

ローパスフィルタとは

ローパスフィルタとは、以下の図のように低周波成分のみ通過させ、高周波成分を遮断するというフィルタになります。

理想的なローパスフィルタは下図のように、通過帯域はゲインが1, 遮断帯域は0になります。

ローパスフィルタの係数を求める

上記の信号に対して逆フーリエ変換することで、ローパスフィルタの係数が得られます。理想的なローパスフィルタは矩形関数で表すことができ、矩形関数の逆フーリエ変換はsinc関数となります。

したがって、カットオフ周波数で矩形関数を定義し、それを逆フーリエ変換することでフィルタ係数を求めることができる。

しかし、sinc関数は無限の範囲で定義されているため、実際には有限長に打ち切ることが必要です。また、時刻が負の値の値を持っているため、因果性を満たすことはできません。

そこで、まずはシフトさせて0から信号、つまり係数データがはじまるようにします。

実装

from fir import Fir
import numpy as np

def make_low_pass_coeffs(cutoff_frequency, fs, num_taps=51):
    # 周波数特性を作成
    freq_response = np.zeros(num_taps)
    
    # カットオフ周波数までを1にする
    freq_bins = np.fft.fftfreq(num_taps, d=1/fs)
    freq_response[np.abs(freq_bins) <= cutoff_frequency] = 1
    
    # 逆フーリエ変換でインパルス応答を得る
    h = np.fft.ifft(freq_response).real
    
    # シフトして中央に配置
    h = np.fft.fftshift(h)
    
    # 正規化
    h /= np.sum(h)
    
    return h

if __name__ == "__main__":
    import matplotlib.pyplot as plt
    fs = 1000  # サンプリング周波数
    cutoff = 200  # カットオフ周波数
    coeffs = make_low_pass_coeffs(cutoff, fs)


    fir_filter = Fir(coeffs)
    
    # テスト信号の生成
    t = np.linspace(0, 1, fs, endpoint=False)
    t = t[0:fs//5]
    input_signal = np.sin(2 * np.pi * 50 * t) + np.sin(2 * np.pi * 300 * t)  # 50Hzと300Hzの混合信号
    
    # フィルタ処理
    output_signal = fir_filter.process(input_signal)
    
    plt.plot(t, input_signal)
    plt.plot(t, output_signal)
    plt.show()

結果

最初、信号がないのはFIRフィルタの遅延によるものです。青色が入力波形、オレンジ色が出力波形になります。確認すると、高周波成分が除去され、単一の正弦波のみになっていることが確認できます。

まとめ

本記事では、Pythonでローパスフィルタを作成しました。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次