一、FIR滤波器时延 = 滤波器阶数 / 采样频率(单位:s)
(参考:补偿 FIR 滤波器引入的延迟)
二、仿真代码
fs = 1000; % 采样频率
ts = 1 / fs; % 采样间隔
t = 0 : ts: 2;
A1 = 5; f1 = 10; % 信号1的幅值和频率
A2 = 10; f2 = 20; % 信号2的幅值和频率
s1 = A1 * sin(2*pi*f1*t); % 信号1
s2 = A2 * sin(2*pi*f2*t); % 信号1
s = s1 + s2; % 两个频率的信号叠加
load 'lp_fir_0to18Hz.mat';
delay_fir = 388 / fs; % fir阶数除以采样频率是延时时间(s)
delay_fir_ind = 388;
s_fir = filter(b, 1, s); % fir滤波后的信号
s1_delay = s1(1, 1:end-delay_fir_ind);
s_fir_delay = s_fir(1, delay_fir_ind+1:end);
figure(1);
sp1 = subplot(4, 1, 1);
plot(t, s1, 'r', 'linewidth', 1.2); hold on;
plot(t, s2, 'b', 'linewidth', 1.2); hold off;
legend('信号1', '信号2'); title('原始信号'); axis('tight');
sp2 = subplot(4, 1, 2);
plot(t, s, 'linewidth', 1.2); axis('tight');
title('叠加信号');
sp3 = subplot(4, 1, 3);
plot(t, s_fir, 'linewidth', 1.2); axis('tight');
title('FIR滤波后的信号');
linkaxes([sp1, sp2, sp3], 'x');
figure(2);
sp11 = subplot(2, 1, 1);
plot(s1_delay, 'b', 'linewidth', 1.2); axis('tight');
title('弥补延时后的信号1');
sp21 = subplot(2, 1, 2);
plot(s_fir_delay, 'linewidth', 1.2); axis('tight');
title('弥补延时后的FIR滤波信号');
linkaxes([sp11, sp21], 'x');
三、理解 FIR 纠正时间延迟的 “左对齐” 和 “居中对齐”
工作中使用到 60 阶的 FIR 滤波器,下图中最后一行是滤波后的相位信号。可以看出滤波后相对前两个信号产生了延迟。
使用上面的 [60阶 / 10Hz采样频率] 计算得到时间延迟为 6s, 纠正 6s 时间延迟后的相位信号见下图。
可以看出纠正后的滤波相位信号好像被过纠正了,并没有达到理想的和原始信号完全对齐的效果。这是因为纠正 6s 的相位延迟为左对齐,如果想要理想的对齐效果,可采用居中对齐,这只需纠正 3s 延迟即可。
可以这样理解滤波器:如下图,滤波器到 AB 为进入异常段的最后一个稳态,BE 是进入异常段的第一个稳态,FC 为即将离开异常段的最后一个稳态,CD 是离开异常段的第一个稳态。而在 AB 到 BE 的过程中并不是稳态,所以从 B 到 E 的这一段异常段在滤波后的相位信号里不是稳态,可能表现不出来异常段的特征;从 F 到 C 段同理。
因此滤波后的异常段要短于滤波前的异常段,所以才会出现如果采用 “左对齐” 的方式就会出现 “明显偏差” 的异常,此时选用 “居中对齐” 即可。“左对齐” 的纠正时间延迟为 [滤波器阶数 / 采样频率],“居中对齐” 的纠正时间延迟为 “左对齐” 的纠正时间延迟的一半。
注意:上面都是基于 Maltlab 做的,Python中的 scipy.signal() 做出来是不需要弥补延时的!对此,我做过相关的实验,结果如下图:
可以看出,scipy.signal.filtfilt() 不需要弥补时延~