Zero-phase digital filtering
y = filtfilt(b,a,x)
y = filtfilt(sos,g,x)
y = filtfilt(d,x)
performs zero-phase digital filtering by processing the input data,
y = filtfilt(
x, in both the forward and reverse directions. After
filtering the data in the forward direction,
the filtered sequence and runs it back through the filter. The result has the
Zero phase distortion.
A filter transfer function equal to the squared magnitude of the original filter transfer function.
A filter order that is double the order of the filter specified by
filtfilt minimizes start-up and ending transients
by matching initial conditions. Do not use
differentiator and Hilbert FIR filters, because the operation of these filters
depends heavily on their phase response.
Zero-phase filtering helps preserve features in a filtered time waveform exactly where they occur in the unfiltered signal.
To illustrate the use of
filtfilt for zero-phase filtering, consider an electrocardiogram waveform.
wform = ecg(500); plot(wform) axis([0 500 -1.25 1.25]) text(155,-0.4,'Q') text(180,1.1,'R') text(205,-1,'S')
The QRS complex is an important feature in the ECG. Here it begins around time point 160.
Corrupt the ECG with additive noise. Reset the random number generator for reproducible results. Construct a lowpass FIR equiripple filter and filter the noisy waveform using both zero-phase and conventional filtering.
rng default x = wform' + 0.25*randn(500,1); d = designfilt('lowpassfir', ... 'PassbandFrequency',0.15,'StopbandFrequency',0.2, ... 'PassbandRipple',1,'StopbandAttenuation',60, ... 'DesignMethod','equiripple'); y = filtfilt(d,x); y1 = filter(d,x); subplot(2,1,1) plot([y y1]) title('Filtered Waveforms') legend('Zero-phase Filtering','Conventional Filtering') subplot(2,1,2) plot(wform) title('Original Waveform')
Zero-phase filtering reduces noise in the signal and preserves the QRS complex at the same time it occurs in the original. Conventional filtering reduces noise in the signal, but delays the QRS complex.
Repeat the above using a Butterworth second-order section filter.
d1 = designfilt('lowpassiir','FilterOrder',12, ... 'HalfPowerFrequency',0.15,'DesignMethod','butter'); y = filtfilt(d1,x); subplot(1,1,1) plot(x) hold on plot(y,'LineWidth',3) legend('Noisy ECG','Zero-Phase Filtering')
a— Transfer function coefficients
Transfer function coefficients, specified as vectors. If you use an
all-pole filter, enter
you use an all-zero (FIR) filter, enter
b = [1 3 3 1]/6 and
a = [3 0 1
0]/3 specify a third-order Butterworth filter with a
normalized 3-dB frequency of 0.5π rad/sample.
x— Input signal
Input signal, specified as a real-valued or complex-valued vector, matrix,
or N-D array.
filtfilt operates along the first array
x with size greater than 1.
cos(pi/4*(0:159))+randn(1,160) is a
single-channel row-vector signal.
cos(pi./[4;2]*(0:159))'+randn(160,2) is a
Complex Number Support: Yes
sos— Second-order section coefficients
Second-order section coefficients, specified as a matrix.
sos is a K-by-6 matrix, where
the number of sections, K, must be greater than or equal
to 2. If the number of sections is less than 2, then
filtfilt treats the input as a numerator vector.
Each row of
sos corresponds to the coefficients of a
second-order (biquad) filter. The ith row of
sos corresponds to
[bi(1) bi(2) bi(3)
ai(1) ai(2) ai(3)].
s = [2 4 2 6 0 2;3 3 0 6 0 0] specifies a
third-order Butterworth filter with a normalized 3-dB frequency of 0.5π
g— Scale factors
Scale factors, specified as a vector.
d— Digital filter
specifies a third-order Butterworth filter with a normalized 3-dB frequency
of 0.5π rad/sample.
y— Filtered signal
Filtered signal, returned as a vector, matrix, or N-D array.
 Oppenheim, Alan V., Ronald W. Schafer, and John R. Buck. Discrete-Time Signal Processing. 2nd Ed. Upper Saddle River, NJ: Prentice Hall, 1999.
 Mitra, Sanjit K. Digital Signal Processing. 2nd Ed. New York: McGraw-Hill, 2001.
 Gustafsson, F. “Determining the initial states in forward-backward filtering.” IEEE® Transactions on Signal Processing. Vol. 44, April 1996, pp. 988–992.
Usage notes and limitations:
All inputs must be constants. Expressions or variables are allowed if their values do not change.
Code generation does not support second-order sections as input. You must use transfer functions.