濾波器只是一串樣本的加權和
想像一個雜訊很多的溫度讀數,明明房間幾乎沒變,數字卻每秒上下亂跳。最古老的招數就是把最近幾筆讀數平均一下:用昨天的值把今天的值磨平。這種直覺——*把鄰近的樣本組合起來,讓訊號變平滑或變銳利*——就是數位濾波器的全部精神。濾波器拿一串輸入的離散時間樣本 x[n],把輸入的縮放、延遲副本(有時還加上它自己過去的輸出)加總起來,產生輸出 y[n]。
在這條路徑裡我們在乎的每個濾波器都是線性非時變的——也就是一個LTI 系統——而這是個美妙的限制。它代表整個濾波器可以被一個物件完整描述:它的脈衝響應 h[n],也就是你用一個值為 1 的單一樣本去戳它時得到的輸出。給濾波器任何輸入,輸出就是 x[n] 與 h[n] 的卷積。所以整場遊戲就是:選對 h[n]。
Difference equation (the recipe a filter actually runs):
y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] + ... (feed-forward: input taps)
- a1*y[n-1] - a2*y[n-2] - ... (feedback: output taps)
b coefficients -> ZEROS a coefficients -> POLES
If all a's are zero -> no feedback -> FIR (finite memory)
If any a is nonzero -> feedback -> IIR (infinite memory)FIR:堅不可摧、誠實,但有點貴
有限脈衝響應濾波器完全沒有迴授。它的脈衝響應就是 b 係數那串清單——丟進一個 1,輸出就是 b0、b1、b2…,之後永遠是死寂的零。這個「有限」給你兩項超能力。第一,FIR 濾波器 永遠穩定:沒有迴授迴路,就沒有東西會失控暴衝,所以有界的輸入永遠不會產生無界的輸出。第二,只要你把係數做成對稱的,濾波器就有完全線性的相位——每個頻率都被延遲同樣的樣本數,因此訊號的形狀被完整保留、不會被抹糊。
看看第 3 階介紹的極點—零點圖,故事很乾淨:FIR 濾波器只有零點(外加一堆無關緊要、坐落在原點的極點,不影響穩定性)。只有零點,你能在頻譜上刻出凹槽,卻永遠造不出尖銳的共振峰——所以要做出陡峭的截止,就得用很多係數。在音訊取樣率下,一個近乎磚牆的低通濾波器很容易需要 100 個以上的抽頭,而每個抽頭都是對每一個樣本做一次乘加運算。這就是 FIR 稅:行為穩如磐石,但算術量很大。
5-point moving-average FIR (all b = 1/5, no feedback):
y[n] = (x[n] + x[n-1] + x[n-2] + x[n-3] + x[n-4]) / 5
Impulse response h = [0.2, 0.2, 0.2, 0.2, 0.2]
Frequency response H(e^jw) magnitude:
|H|
1.0 *._
| \._ nulls at f = fs/5, 2fs/5 (zeros on unit circle)
| \.
| \. .-'\. low-pass, but GENTLE roll-off
| '-' '-.__
0.0 +------------------------> frequencyIIR:便宜、銳利,但危險
現在把迴授打開。無限脈衝響應濾波器把自己過去的輸出餵回加總裡,而那個迴路就是全部的差別。因為每個輸出在迴路裡徘徊、慢慢衰減,單一個輸入的戳動基本上會永遠迴響下去——所以叫無限脈衝響應。回報是驚人的效率:一個IIR 濾波器只要 4 到 8 個係數,就能比得上 100 個抽頭的 FIR 的選擇性,因為迴授讓你能放置極點。
在極點—零點圖上,極點就是峰:把一個極點拖到靠近單位圓,頻率響應就會在那個角度衝高,幾乎不花成本地給你一個尖銳的共振或陡峭的帶緣。但這就是刀鋒所在——極點落在單位圓上或圓外,就是一個不穩定的濾波器。 那個迴授迴路,正是所有效率的來源,屆時會無止境地放大自己的輸出,數字就爆掉了。所以 IIR 設計的生死,就繫於讓每一個極點都嚴格地留在單位圓內。
One-pole IIR low-pass (the workhorse smoother):
y[n] = a * y[n-1] + (1 - a) * x[n] with 0 < a < 1
- Single pole at z = a, on the real axis, inside the unit circle.
- a near 1 -> pole hugs the circle -> very smooth, slow, long memory.
- a near 0 -> pole near origin -> barely filters at all.
Impulse response (set x = 1 at n=0):
h = (1-a) * [1, a, a^2, a^3, a^4, ...] <- decays forever (INFINITE)
Two adds, two multiplies, one stored value -> a whole low-pass filter.設計 FIR:窗函數法
你到底怎麼挑係數?對 FIR 來說,最直覺的路線是窗函數法,它直接從前幾階的傅立葉概念延伸而來。先寫下你夢寐以求的頻率響應——例如一個完美的磚牆低通,通帶為 1、阻帶為 0。對它做反傅立葉轉換,你會得到理想的脈衝響應:一個 sinc 函數,惱人的是它向兩邊無限延伸。你沒辦法跑一個無限長的濾波器,所以必須把它切短。
設計 IIR:向類比借光
IIR 設計走的是一條完全不同、相當優雅的捷徑:工程師花了一個世紀把類比濾波器磨到爐火純青,何必重新發明?標準流程是從經典的類比原型出發——Butterworth(通帶最平坦)、Chebyshev(更陡,代價是通帶漣波)、或橢圓型(最陡,兩帶都有漣波)——在連續的 s 域裡設計它(那裡的極點與零點都很清楚),再把它映射到離散的 z 平面。
最常用的映射是雙線性轉換:s ← (2/T)·(1−z⁻¹)/(1+z⁻¹)。它有一個美妙的性質:它把整個穩定的 s 平面左半平面映射到單位圓內部,所以穩定的類比濾波器會自動變成穩定的數位濾波器——沒有極點能溜到圓外。代價是頻率扭曲:這個映射把無限長的類比頻率軸擠進有限的數位頻率軸,使靠近頻帶頂端的頻率被彎折。你可以在設計前對關鍵頻率做預扭曲來修正它,讓截止頻率精準落在你要的位置。
The two design flows side by side:
FIR (window method) IIR (analog-prototype mapping)
------------------- -----------------------------
desired |H(f)| spec choose Butterworth/Chebyshev/elliptic
| |
inverse FT -> sinc h[n] design analog poles/zeros in s-plane
| |
truncate to N taps pre-warp critical frequencies
| |
apply window (Hamming...) bilinear transform s -> z
| |
-> linear-phase FIR -> cascade of biquads (stable IIR)卷積:FIR 究竟如何執行
撥開設計理論,一個運轉中的 FIR 濾波器就只是同一個動作永遠重複:卷積。把係數清單 h[] 想成一個沿著輸入滑動的小模板。每來一個新樣本,你就把翻轉後的模板對齊到最近的那幾筆輸入上,逐對相乘、加總,那個總和就是你的下一個輸出。滑一步、再重複。工程師稱這為乘加(MAC)迴圈,它是整個 DSP 裡執行次數最多的指令。
// Direct-form FIR in C: convolution as a MAC loop
float fir(float x_new, const float h[], float state[], int N) {
// shift the delay line (oldest sample falls off the end)
for (int i = N - 1; i > 0; i--) state[i] = state[i - 1];
state[0] = x_new;
float y = 0.0f;
for (int i = 0; i < N; i++)
y += h[i] * state[i]; // multiply-accumulate: the heart of DSP
return y;
}這裡也正是這條路徑各條線索收束之處。直接卷積每個輸出樣本要花 N 次乘法,對長濾波器來說會變得殘酷——所以對非常長的 FIR,工程師改在頻域裡算卷積,用 FFT 把頻譜相乘(快速卷積),因為頻域裡的相乘就是時域裡的卷積。同時,同一個卷積透過 z 轉換來看就變成單純的多項式相乘,而那個多項式的根正是濾波器的零點。取樣、z 轉換、頻率響應、卷積——它們從來不是分開的主題,而是望向同一台機器的四扇窗。