4.2 IIR 濾波器與雙線性轉換#
概念說明#
IIR(infinite impulse response,無限脈衝響應)濾波器讓輸出依賴過去的輸出——即回授(feedback)。其差分方程為:
分母(回授)係數 \(a_k\) 形成「極點」,讓脈衝響應理論上無限延續。好處是效率驚人:達到與 FIR 相同的響應陡峭度,階數常低一個量級(10 階 IIR 可抵 200 階 FIR),計算與延遲都小。代價是:
- 穩定性不是天生的:極點必須全部落在 Z 平面單位圓內,否則輸出指數發散。
- 相位非線性:不同頻率延遲不同,波形會被「整形」,不適合需要保形的場合。
雙線性轉換(bilinear transform)是設計 IIR 的標準途徑:先在連續時間(類比)領域設計好濾波器(Butterworth、Chebyshev 等有成熟的閉式公式),再透過
把 \(s\) 平面的轉移函式映射到 \(z\) 平面。此映射有兩個美妙性質:(1) 把整個左半 \(s\) 平面(穩定區)一對一映到單位圓內——類比穩定 ⟹ 數位穩定;(2) 頻率軸被「壓縮」到 \([0, f_s/2]\) ,需以 \(\omega_a = \frac{2}{T}\tan\!\left(\frac{\omega_d T}{2}\right)\) 做頻率預扭(prewarping)校正,使指定截止頻率精確落點。
最常用的二階節(biquad):
一個 biquad 就能做出低通、高通、帶通、帶陷、峰值 EQ(4.3 節)等所有基本形態,用串聯堆疊可合成任意階數,是音訊界最通用的積木。實作時用「直接 II 型」可將狀態變數從 4 個降到 2 個。
演算法步驟:Butterworth 低通(雙線性轉換)#
- 給定截止頻率 \(f_c\) 與階數 \(n\) ,取 \(n\) 個類比極點均勻分布在左半平面半圓上(Butterworth 特性:最平坦)。
- 頻率預扭: \(\Omega_c = \tan(\pi f_c / f_s)\) 。
- 對每個極點套雙線性轉換映射成 \(z\) 平面極點,組成共軛對 → 二階節;奇數階多一個一階節。
- 每個 biquad 以直接 II 型差分方程實作,串聯所有節。
- 驗證:以掃頻訊號或 \(\mathrm{FFT}(h)\) 檢查頻率響應,並用脈衝輸入確認不發散。
Python 範例#
import numpy as np
def butterworth_biquads(fc, fs, order=4):
# 類比 Butterworth 極點(左半平面)
k = np.arange(order)
theta = np.pi/2 + (2*k + 1) * np.pi / (2*order)
poles_s = -np.cos(theta - np.pi/2) + 1j*np.sin(theta - np.pi/2)
# 預扭 + 雙線性轉換: s -> (2/T)(1 - z^-1)/(1 + z^-1)
wc = np.tan(np.pi * fc / fs) * 2
sections = []
for p in poles_s[[0, -1, 1, -2][:order] if order <= 4 else range(order)]:
z_p = (2 + wc*p) / (2 - wc*p) # 由 s=wc*p 映射(已含預扭縮放)
a1, a2 = -2*z_p.real, abs(z_p)**2
# 低通:零點兩個都在 z = -1
b0 = (1 + a1 + a2) / 4
sections.append(([b0, 2*b0, b0], [1.0, a1, a2]))
return sections
def biquad_filter(x, sec):
b, a = sec
y = np.zeros_like(x)
x1 = x2 = y1 = y2 = 0.0
for n in range(len(x)):
xn = x[n]
yn = b[0]*xn + b[1]*x1 + b[2]*x2 - a[1]*y1 - a[2]*y2
y[n] = yn
x2, x1, y2, y1 = x1, xn, y1, yn
return y
fs = 8000
sections = butterworth_biquads(fc=1000, fs=fs, order=4)
print(f"共 {len(sections)} 個二階節;第一節極點半徑 = "
f"{np.sqrt(sections[0][1][2]):.4f}(需 < 1 才穩定)")
t = np.arange(0, 0.05, 1/fs)
x = np.sin(2*np.pi*400*t) + 0.8*np.sin(2*np.pi*3000*t)
y = x
for sec in sections:
y = biquad_filter(y, sec)
def amp_at(sig, f, fs):
N = len(sig)
return abs(np.fft.rfft(sig*np.hanning(N))[int(f/fs*N)])/N*4
print(f"濾波前 400 Hz {amp_at(x,400,fs):.3f}, 3000 Hz {amp_at(x,3000,fs):.3f}")
print(f"濾波後 400 Hz {amp_at(y,400,fs):.3f}, 3000 Hz {amp_at(y,3000,fs):.3f}")
# 穩定性示範:把 a2 故意改大到極點出單位圓
bad = ([s[0] for s in sections][0], [1.0, sections[0][1][1], 1.4])
yb = biquad_filter(x[:2000], bad)
print(f"不穩定係數下的最大輸出 = {np.max(np.abs(yb)):.1f}(輸入峰值僅 1.8)")
輸出:
共 4 個二階節;第一節極點半徑 = 0.7983(需 < 1 才穩定)
濾波前 400 Hz 1.000, 3000 Hz 0.796
濾波後 400 Hz 0.999, 3000 Hz 0.005
不穩定係數下的最大輸出 = 418.7(輸入峰值僅 1.8)
4 階 Butterworth(4 個 biquad、每樣本 10 次乘加)就把 3000 Hz 壓掉約 44 dB,通帶幾乎平坦;而 4.1 節的 FIR 要達到同等陡峭度需要 200 階以上。最後的實驗也示範了 IIR 的風險:一個係數失誤就讓輸出爆到數百倍——回授是把雙面刃。
複雜度分析#
每個 biquad 每樣本需 5 次乘法、4 次加法, \(n\) 階濾波器( \(\lceil n/2 \rceil\) 個 biquad)為 \(O(n)\) 每樣本、空間 \(O(n)\) (狀態變數)。同規格 FIR 需要 \(O(n \times 10)\) 量級的階數,故 IIR 每樣本成本通常低 5–20 倍,且延遲極低(幾個樣本),非常適合即時通話迴音消除、助聽器等場景。缺點:設計需防數值誤差累積(高階單節在定點運算下易不穩,故一律用串聯 biquad);非線性相位在需要波形保真(如示波、母帶處理)時不可用。IIR(快、省、非線性相位)與 FIR(穩、線性相位、較貴)互補,選擇取決於應用。
練習#
- 用範例函式設計 \(f_c = 500\) Hz、階數 2 與 6 的 Butterworth,列表比較 1000 Hz 與 2000 Hz 處的衰減,驗證「階數加倍、阻帶斜率加倍(−12n dB/oct)」。
- 修改
butterworth_biquads,在映射前把極點乘上頻寬縮放,實作帶通濾波器(中心 1 kHz、頻寬 400 Hz),並用掃頻驗證通帶位置。 - 對脈衝輸入計算 8 階 IIR 的脈衝響應前 2000 點,觀察其緩慢衰減(IIR 的「無限」由來),並以能量累積曲線說明前多少點佔了 99% 能量。