チェビシェフフィルタの設計原理とPython実装

チェビシェフフィルタ(I型・II型)の数学的基礎から、等リップル特性の導出、次数決定、SciPyを使ったローパス/ハイパス/バンドパスフィルタのPython実装までを解説します。

はじめに

チェビシェフフィルタは、通過域(I型)または阻止域(II型)に等リップルを許容することで、同次数のバターワースフィルタよりも急峻な遷移帯域を実現するIIRフィルタです。

バターワースフィルタが通過域で最大限に平坦な特性を持つのに対し、チェビシェフフィルタはその平坦性を犠牲にして遷移の鋭さを優先します。本記事ではI型とII型それぞれの数学的基礎から、SciPyを使った実践的な設計・実装までを解説します。

チェビシェフ多項式

チェビシェフフィルタの周波数特性は、チェビシェフ多項式 \(T_N(x)\) に基づいています。

\[T_N(x) = \begin{cases} \cos(N \arccos x) & |x| \leq 1 \\ \cosh(N \operatorname{arccosh} x) & |x| > 1 \end{cases} \tag{1}\]

低次のチェビシェフ多項式は次のとおりです。

次数 \(N\)\(T_N(x)\)
0\(1\)
1\(x\)
2\(2x^2 - 1\)
3\(4x^3 - 3x\)
4\(8x^4 - 8x^2 + 1\)

\(|x| \leq 1\) の範囲でチェビシェフ多項式は \(-1\) から \(+1\) の間を等振幅で振動する性質があり、これがフィルタに等リップル特性をもたらします。

チェビシェフI型フィルタ

振幅特性

\(N\) 次チェビシェフI型ローパスフィルタの振幅二乗関数は次の式で定義されます。

\[|H(j\Omega)|^2 = \frac{1}{1 + \varepsilon^2 T_N^2\!\left(\dfrac{\Omega}{\Omega_p}\right)} \tag{2}\]

ここで、

  • \(\varepsilon\): リップル係数(\(\varepsilon > 0\))
  • \(\Omega_p\): 通過域端の角周波数
  • \(T_N\): \(N\) 次チェビシェフ多項式

\(\Omega \leq \Omega_p\) の通過域では \(T_N(\Omega/\Omega_p) \in [-1, 1]\) となり、振幅は \(1/\sqrt{1+\varepsilon^2}\) から \(1\) の間を等振幅でリップルします。通過域リップル \(R_p\) [dB] とリップル係数の関係は次のとおりです。

\[\varepsilon = \sqrt{10^{R_p/10} - 1} \tag{3}\]

極の配置

チェビシェフI型フィルタの極は、楕円上に配置されます。\(k = 1, 2, \ldots, N\) について

\[\sigma_k = -\sinh\!\left(\frac{\operatorname{arcsinh}(1/\varepsilon)}{N}\right)\sin\theta_k \tag{4}\]

\[\omega_k = \cosh\!\left(\frac{\operatorname{arcsinh}(1/\varepsilon)}{N}\right)\cos\theta_k \tag{5}\]

ただし \(\theta_k = \dfrac{\pi(2k-1)}{2N}\) です。安定な左半平面の極 \(s_k = \sigma_k + j\omega_k\) のみを採用します。

チェビシェフII型フィルタ

チェビシェフII型(逆チェビシェフ)フィルタは、阻止域に等リップルを持ち、通過域は単調です。振幅二乗関数は次のとおりです。

\[|H(j\Omega)|^2 = \frac{1}{1 + \left[\varepsilon^2 T_N^2\!\left(\dfrac{\Omega_s}{\Omega}\right)\right]^{-1}} \tag{6}\]

ここで \(\Omega_s\) は阻止域端の角周波数です。通過域が単調なので、位相特性がI型より滑らかになります。

I型とII型の特性比較

特性チェビシェフI型チェビシェフII型
通過域等リップル単調(平坦)
阻止域単調等リップル
遷移帯域バターワースより急峻バターワースより急峻
位相特性非線形(I型より非線形)比較的滑らか
用途ノイズ除去の急峻遮断通過域平坦性重視

フィルタ次数の決定

所望の仕様(通過域リップル \(R_p\)、阻止域減衰 \(R_s\)、通過域端 \(\Omega_p\)、阻止域端 \(\Omega_s\))から必要な次数を求めます。

\[N \geq \frac{\operatorname{arccosh}\!\left(\sqrt{\dfrac{10^{R_s/10}-1}{10^{R_p/10}-1}}\right)}{\operatorname{arccosh}(\Omega_s/\Omega_p)} \tag{7}\]

同じ仕様に対して、チェビシェフフィルタはバターワースフィルタよりも低い次数で仕様を満足できます。

Python実装

SciPyによるチェビシェフI型フィルタ設計

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

# --- フィルタ仕様 ---
fs = 1000         # サンプリング周波数 [Hz]
fp = 100          # 通過域端 [Hz]
rp = 1.0          # 通過域リップル [dB]
orders = [2, 4, 6]

fig, axes = plt.subplots(2, 1, figsize=(10, 8))

for N in orders:
    # チェビシェフI型ローパスフィルタ
    sos = signal.cheby1(N, rp, fp, btype='low', fs=fs, output='sos')
    w, h = signal.sosfreqz(sos, worN=4096, fs=fs)

    axes[0].plot(w, 20 * np.log10(np.abs(h) + 1e-12), label=f'N={N}')
    axes[1].plot(w, np.degrees(np.unwrap(np.angle(h))), label=f'N={N}')

axes[0].set_xlabel('Frequency [Hz]')
axes[0].set_ylabel('Magnitude [dB]')
axes[0].set_title('Chebyshev Type I - Magnitude Response (rp=1dB)')
axes[0].set_xlim(0, 500)
axes[0].set_ylim(-80, 5)
axes[0].axvline(fp, color='gray', linestyle='--', alpha=0.5, label=f'fp={fp}Hz')
axes[0].axhline(-rp, color='r', linestyle=':', alpha=0.5, label=f'-{rp}dB ripple')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

axes[1].set_xlabel('Frequency [Hz]')
axes[1].set_ylabel('Phase [degrees]')
axes[1].set_title('Chebyshev Type I - Phase Response')
axes[1].set_xlim(0, 500)
axes[1].legend()
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

チェビシェフII型フィルタ設計

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

fs = 1000
fs_stop = 150     # 阻止域端 [Hz]
rs = 40.0         # 阻止域減衰量 [dB]
orders = [2, 4, 6]

fig, axes = plt.subplots(2, 1, figsize=(10, 8))

for N in orders:
    # チェビシェフII型ローパスフィルタ
    sos = signal.cheby2(N, rs, fs_stop, btype='low', fs=fs, output='sos')
    w, h = signal.sosfreqz(sos, worN=4096, fs=fs)

    axes[0].plot(w, 20 * np.log10(np.abs(h) + 1e-12), label=f'N={N}')
    axes[1].plot(w, np.degrees(np.unwrap(np.angle(h))), label=f'N={N}')

axes[0].set_xlabel('Frequency [Hz]')
axes[0].set_ylabel('Magnitude [dB]')
axes[0].set_title('Chebyshev Type II - Magnitude Response (rs=40dB)')
axes[0].set_xlim(0, 500)
axes[0].set_ylim(-80, 5)
axes[0].axvline(fs_stop, color='gray', linestyle='--', alpha=0.5, label=f'fs={fs_stop}Hz')
axes[0].axhline(-rs, color='r', linestyle=':', alpha=0.5, label=f'-{rs}dB')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

axes[1].set_xlabel('Frequency [Hz]')
axes[1].set_ylabel('Phase [degrees]')
axes[1].set_title('Chebyshev Type II - Phase Response')
axes[1].set_xlim(0, 500)
axes[1].legend()
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

バターワースとの次数比較

from scipy.signal import buttord, cheb1ord
import numpy as np

# フィルタ仕様
fp = 100   # 通過域端 [Hz]
fs_stop = 150  # 阻止域端 [Hz]
rp = 1.0   # 通過域リップル [dB]
rs = 40.0  # 阻止域減衰量 [dB]
fs = 1000  # サンプリング周波数

# バターワースの必要次数
N_butter, Wn_butter = buttord(fp, fs_stop, rp, rs, fs=fs)

# チェビシェフI型の必要次数
N_cheby1, Wn_cheby1 = cheb1ord(fp, fs_stop, rp, rs, fs=fs)

print(f"バターワース    : {N_butter}次")
print(f"チェビシェフI型 : {N_cheby1}次")

実行例では、同じ仕様に対してチェビシェフI型の方がバターワースよりも低い次数で設計できることが確認できます。

ノイズ除去への応用

import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

fs = 1000
t = np.arange(0, 1, 1/fs)
clean = np.sin(2 * np.pi * 10 * t) + 0.5 * np.sin(2 * np.pi * 30 * t)
noisy = clean + 0.8 * np.random.randn(len(t))

# バターワース(4次)
sos_butter = signal.butter(4, 100, fs=fs, output='sos')
y_butter = signal.sosfiltfilt(sos_butter, noisy)

# チェビシェフI型(4次、1dBリップル)
sos_cheby1 = signal.cheby1(4, 1, 100, fs=fs, output='sos')
y_cheby1 = signal.sosfiltfilt(sos_cheby1, noisy)

# チェビシェフII型(4次、40dB減衰)
sos_cheby2 = signal.cheby2(4, 40, 150, fs=fs, output='sos')
y_cheby2 = signal.sosfiltfilt(sos_cheby2, noisy)

fig, axes = plt.subplots(4, 1, figsize=(10, 12), sharex=True)
axes[0].plot(t, noisy, alpha=0.5, label='Noisy'); axes[0].plot(t, clean, 'k', label='Original')
axes[0].set_title('Input Signal'); axes[0].legend(); axes[0].grid(True, alpha=0.3)

axes[1].plot(t, y_butter, label='Butterworth N=4'); axes[1].plot(t, clean, 'k', lw=1.5)
axes[1].set_title('Butterworth (N=4)'); axes[1].legend(); axes[1].grid(True, alpha=0.3)

axes[2].plot(t, y_cheby1, label='Chebyshev I N=4, rp=1dB'); axes[2].plot(t, clean, 'k', lw=1.5)
axes[2].set_title('Chebyshev Type I (N=4, rp=1dB)'); axes[2].legend(); axes[2].grid(True, alpha=0.3)

axes[3].plot(t, y_cheby2, label='Chebyshev II N=4, rs=40dB'); axes[3].plot(t, clean, 'k', lw=1.5)
axes[3].set_title('Chebyshev Type II (N=4, rs=40dB)')
axes[3].set_xlabel('Time [s]'); axes[3].legend(); axes[3].grid(True, alpha=0.3)

plt.tight_layout()
plt.show()

他のIIRフィルタとの比較

フィルタ通過域阻止域遷移帯域位相特性
バターワース最大平坦単調減少広い比較的滑らか
チェビシェフI型等リップル単調減少バターワースより狭い非線形
チェビシェフII型単調減少等リップルバターワースより狭い比較的滑らか
楕円(Cauer)等リップル等リップル最も狭い最も非線形

急峻な遮断が必要で通過域のリップルが許容できる場合はI型、通過域の平坦性を保ちつつ阻止域を改善したい場合はII型が適しています。

まとめ

  • チェビシェフフィルタはチェビシェフ多項式の等振幅特性を利用した等リップルIIRフィルタ
  • I型は通過域に等リップル、II型は阻止域に等リップルを持つ
  • 同次数でバターワースより急峻な遷移帯域を実現できる
  • SciPyでは signal.cheby1() / signal.cheby2() で設計、signal.cheb1ord() で必要次数を自動計算できる

関連記事

参考文献


関連ツール