Filtering Fundamentals
Est. read time: 1 minute | Last updated: July 15, 2025 by John Gentile
Contents
- Filter Design
- FIR Filters
- Windowing
- Filter Implementation
- Parallel/Vectorized Filter/Convolution
- References
import numpy as np
from scipy import signal
import matplotlib.pyplot as plt
from rfproto import filter, utils
Filter Design
Estimate Filter Order
One practical estimate comes from fred harris’ rule-of-thumb:
Where:
- is the desired stopband attenuation, in dB.
- is the normalized transition band, or
FIR Filters
The discrete-time convolution of filter coefficients with input samples can be seen as:
test_filt = filter.fir_filter([0, 0, 1, 0, 0])
for i in range(10):
print(test_filt.step(i+1))
0.0 0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0
Windowing
- Window function - Wikipedia: includes list of window functions with example of time and frequency domain responses.
plt.figure()
num_pts = 51
windows = {}
windows['Rectangular'] = signal.windows.boxcar(num_pts)
windows['Hamming'] = signal.windows.hamming(num_pts)
windows['Flattop'] = signal.windows.flattop(num_pts)
windows['Blackman'] = signal.windows.blackman(num_pts)
windows['Blackman-Harris (4-term)'] = signal.windows.blackmanharris(num_pts)
for window in windows:
A = np.fft.rfft(windows[window], n=2048) / (num_pts/2.0)
response = np.abs(A / abs(A).max())
response = 20 * np.log10(np.maximum(response, 1e-10))
freq = np.linspace(0, 1, len(response))
plt.plot(freq, response, label=window, linewidth=0.5)
plt.axis([0, 1.0, -120, 0])
plt.ylabel("Normalized Magnitude (dB)")
plt.xlabel(r"Normalized Frequency ($\times\pi$ rad/sample)")
plt.legend()
plt.show()
Filter Implementation
Complex-Valued Filters
Rarely you’ll need to use a complex-valued filter- often you’re looking to apply a filter on complex-valued input signals. In this case, the same real filter tap values and convolution process can happen in parallel on both real and imaginary parts of the signal.