はじめに
www.wizard-notes.com
上記の記事で紹介した移動平均フィルタですが、こちらを応用したフィルタとして直列移動平均フィルタとCIC (Cascaded Integrator Comb) フィルタがあります。
こちらはAD-DA変換のような実用的なディジタル信号処理技術として重要なので、簡単に紹介したいと思います。
直列移動平均フィルタ (Cascaded moving average)
前回の記事の通り、移動平均フィルタは線形位相かつローパスフィルタとしての特性を持つ一方で、櫛形フィルタのような周期性があります。そのため、周期的に高周波成分が割と残る帯域が出てきてしまいます。ローパスフィルタとしても十分に遮断できているとはいえません。
そのため、より理想的なローパスフィルタ特性に近づける方法として、移動平均フィルタを直列接続する方法があります。
以下は、ウィンドウサイズ M=8 としたときに、直列接続をした個数による特性の変化をプロットしています。
直列接続することで、高周波の除去性能が向上していることが分かります。
また、ウィンドウサイズの広い移動平均フィルタと比べても、直列移動平均フィルタのほうが高周波の除去性能は高いです。ただし、ウィンドウサイズが大きい方が遮断し始める周波数は低いです。
Pythonコード
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal
def plot(w, h, label, fs=48000, amp_ylim=[-100,0]):
angles = np.unwrap(np.angle(h))
gd = -np.diff(angles) / np.diff(w)
amp_dB = 10 * np.log10(np.abs(h+1e-19)**2)
plt.subplot(3, 1, 1)
plt.plot(w / np.pi * (fs / 2), amp_dB, label=label)
plt.ylabel('Power [dB]', color='b')
plt.xlabel('Frequency [Hz]')
plt.grid()
plt.ylim(amp_ylim)
plt.legend()
plt.subplot(3, 1, 2)
plt.plot(w / np.pi * (fs / 2), angles, label=label)
plt.ylabel('Unwrapped Angle [rad]', color='g')
plt.grid()
plt.axis('tight')
plt.xlabel('Frequency [Hz]')
plt.legend()
plt.subplot(3, 1, 3)
plt.plot(w[:-1] / np.pi * (fs / 2), gd, label=label)
plt.legend()
plt.ylabel('Group Delay [samples]')
plt.xlabel('Frequency [Hz]')
plt.grid()
plt.ylim([0, 20])
return amp_dB, angles, gd
plt.figure(figsize=(8,8))
M = 8
N_list = [1,2,4]
for N in N_list:
b = np.ones(M) / M
a = [1]
w, tmp_h = signal.freqz(b, a, worN=2048)
h = tmp_h.copy()
for n in range(N-1):
h *= tmp_h
amp_dB, angles, gd = plot(w, h, label=f"N={N}", fs=48000)
print(f'Calculated Group Delay at w=0 for M={len(b)}, N={N}: {gd[0]:.2f} samples')
plt.tight_layout()
plt.show()
plt.close()
for M, N in [(8,2), (16,1)]:
b = np.ones(M) / M
a = [1]
w, tmp_h = signal.freqz(b, a, worN=2048)
h = tmp_h.copy()
for n in range(N-1):
h *= tmp_h
amp_dB, angles, gd = plot(w, h, label=f"M={len(b)}, N={N}", fs=48000)
print(f'Calculated Group Delay at w=0 for M={len(b)}, N={N}: {gd[0]:.2f} samples')
plt.tight_layout()
plt.show()
plt.close()
N 次 CIC フィルタ
図のように、移動平均フィルタの数列に手を加えることで、フィードバックIIRとFIRコムフィルタに分解することができます。
これが1 次 CIC フィルタとなります。
さらに、N個直列の場合も同様に構成することができます。以下に3次CICフィルタの図を示します。
CICフィルタはシンプルな実装、線形位相だけでなく、積和を使わない(遅延、加算、減算)という計算コストの面でも優れています*1。
また、フィルタの性能を制御しやすいという特徴もあります。
リサンプリングでの利用
ダウンサンプラやアップサンプラでのアンチエイリアシングフィルタでよく利用されます。
以下はCICフィルタによるダウンサンプラです。計算量削減のために、デシメーション後にFIRコムフィルタを入れることで、保存しておく信号長を削減することができます。アップサンプラの場合は逆の構成になります。
より詳細な情報は参考文献の方をご覧ください。
まとめ
直列移動平均フィルタとCICフィルタ(Cascaded Integrator-Comb Filter)は、いずれもシンプルで効率的な信号処理を可能にするフィルタです。直列移動平均フィルタは、基本的な移動平均フィルタの特性を活かしながら、その高周波除去性能を強化したもので、フィルタの設計が簡単で計算負荷も低いことから、ノイズ除去や信号平滑化に広く利用されています。
一方、CICフィルタはデシメーションやインターポレーションといったサンプリングレートの変換を効率的に行うために設計されており、積和演算を必要としないシンプルな構造で計算コストを大幅に削減できるという特徴を持っています。そのため、デジタル信号処理の分野では特にリサンプリングやデジタルフィルタリングの前処理において重要な役割を果たしています。
実用的なので、特にリアルタイム処理でローパスフィルタが必要な場合はCICフィルタの利用を検討してみるのがよいと思います。
参考文献