1. 程式人生 > >實時零相位濾波的神話(1)

實時零相位濾波的神話(1)

做控制的人大概都夢想做到輸出和輸入訊號保持完全同步,相移為0。如果能做到,那該多酷。

MATLAB有個神奇的函式filtfilt,可以對資料做離線的濾波,實現零相移。原理就是先做一個方向的濾波,比如先forward 濾波,然後把濾波後的序列逆序,再用同一個濾波器做backward濾波,濾波得到的序列最後再逆序,得到最終結果。嘗試了一下,濾波效果那真是賞心悅目。可惜,不能實現線上訊號的實時零相移濾波。怎麼做呢?焦慮之際,在百度上搜到這個文章:http://blog.csdn.net/shenziheng1/article/details/53415642,作者的手段讓我萬分佩服:既然相移導致的group delay不為0,那咱就設計個group delay與其完全相反的全通濾波器,二者級聯,groupdelay兩兩相消,不就搞定了嗎?多麼完美!!

感謝這位博主,在相關文章裡把程式碼給的相當完整,某些略去的地方其實比較容易補全。按照這個思路做下去,確實得到了相移接近0 的結果,圖片如下:

但是當我興沖沖地把low pass 和all pass級聯進行濾波,得到了讓人鬱悶的玩意:濾波結果是震盪的,資料越來越大。。。。痛苦地找了好久,某篇英文文章說,級聯allpass濾波器,只能增大相移,尤其是在將iir整成線性相位濾波器時的典型應用時,group delay在通帶內雖然可以保持恆定,但只能讓group delay變大,即輸出結果比輸入delay更多個samples。這個震盪,應該是all pass的零極點與單位圓的關係導致系統不穩定造成的。

iir+all pass常用來進行相位均衡,這個均衡並不是要做到零相位,而是使得通帶內的訊號保持固定的group delay。下面是從某個大學課件上搞來的iir+all pass的程式碼,講解了相位均衡的常規應用:

t = 0:0.001:1;


w = pi*t; % normalized frequencies
alpha = 0.5; % LPF parameter
blp = (1-alpha)/2*[1 1]; % numerator coefficients
alp = [1 -alpha]; % denominator coefficients
hlp = freqz(blp,alp,w); % compute DTFT
glp = grpdelay(blp,alp,w); % compute group delay


N = 4; % all-pass filter order
F = w(1:501)/pi; % normalized frequencies
edges = [0 1/2]; % band-edge frequencies
Gd = max(glp)-glp(1:501); % desired group-delays of APF (>0)
[bap,aap] = iirgrpdelay(N,F,edges,Gd); % make all-pass filter
hap = freqz(bap,aap,w); % compute DTFT
gap = grpdelay(bap,aap,w); % compute group-delay

b = conv(blp,bap); % product of numerators
a = conv(alp,aap); % product of denominators
h = freqz(b,a,w); % compute DTFT
g = grpdelay(b,a,w); % compute group delay
subplot(3,1,1)
plot(w,abs(h));
ylabel('magnitude response');
subplot(3,1,2);
plot(w,unwrap(angle(h)));
ylabel('phase response (rad)');
subplot(3,1,3);
plot(w,g);
xlabel('normalized freq (rad/sample)');
ylabel('group delay (samples)');

已經確定了,all pass 級聯不能讓group delay 變成0,反而是更大。於是,我的第一次充滿勇氣的尋找零相位實時濾波器行動宣告破產。