Filtering a signal introduces a delay. This means that the output signal is shifted in time with respect to the input.
When the shift is constant, you can correct for the delay by shifting the signal in time.
Sometimes the filter delays some frequency components more than others. This phenomenon is called phase distortion. To compensate for this effect, you can perform zero-phase filtering using the
Take an electrocardiogram reading sampled at 500 Hz for 1 s. Add random noise. Reset the random number generator for reproducible results
Fs = 500; N = 500; rng default xn = ecg(N)+0.1*randn([1 N]); tn = (0:N-1)/Fs;
Remove some of the noise using a filter that stops frequencies above 75 Hz. Use
designfilt to design an FIR filter of order 70.
Nfir = 70; Fst = 75; firf = designfilt('lowpassfir','FilterOrder',Nfir, ... 'CutoffFrequency',Fst,'SampleRate',Fs);
Filter the signal and plot it. The result is smoother than the original, but lags behind it.
xf = filter(firf,xn); plot(tn,xn,tn,xf) title 'Electrocardiogram' xlabel 'Time (s)' legend('Original','FIR Filtered') grid
grpdelay to check that the delay caused by the filter equals half the filter order.
delay = mean(grpdelay(firf))
delay = 35
Line up the data. Shift the filtered signal by removing its first
delay samples. Remove the last
delay samples of the original and of the time vector.
tt = tn(1:end-delay); sn = xn(1:end-delay); sf = xf; sf(1:delay) = ;
Plot the signals and verify that they are aligned.
plot(tt,sn,tt,sf) title 'Electrocardiogram' xlabel('Time (s)') legend('Original Signal','Filtered Shifted Signal') grid
Repeat the computation using a 7th-order IIR filter.
Niir = 7; iir = designfilt('lowpassiir','FilterOrder',Niir, ... 'HalfPowerFrequency',Fst,'SampleRate',Fs);
Filter the signal. The filtered signal is cleaner than the original, but lags in time with respect to it. It is also distorted due to the nonlinear phase of the filter.
xfilter = filter(iir,xn); plot(tn,xn,tn,xfilter) title 'Electrocardiogram' xlabel 'Time (s)' legend('Original','Filtered') axis([0.25 0.55 -1 1.5]) grid
A look at the group delay introduced by the filter shows that the delay is frequency-dependent.
Filter the signal using
filtfilt. The delay and distortion have been effectively removed. Use
filtfilt when it is critical to keep the phase information of a signal intact.
xfiltfilt = filtfilt(iir,xn); plot(tn,xn) hold on plot(tn,xfilter) plot(tn,xfiltfilt) title 'Electrocardiogram' xlabel 'Time (s)' legend('Original','''filter''','''filtfilt''') axis([0.25 0.55 -1 1.5]) grid