FIR filters

import matplotlib.pyplot as plt
import numpy as np

import sdr

%config InlineBackend.print_figure_kwargs = {"facecolor" : "w"}
%matplotlib inline
# %matplotlib widget

sdr.plot.use_style()

Create an FIR filter

The user creates an FIR filter with the sdr.FIR class by specifying the feedforward coefficients \(h_i\).

Below is an square-root raised cosine FIR filter.

h = sdr.root_raised_cosine(0.5, 6, 10)
fir = sdr.FIR(h)

Examine the impulse response, \(h[n]\)

The impulse response of the FIR filter is computed and returned from the sdr.FIR.impulse_response() method. The impulse response \(h[n]\) is the output of the filter when the input is an impulse \(\delta[n]\).

For FIR filters, the impulse response is the same as the feedforward taps.

h = fir.impulse_response()
print(h)
[ 0.00095883 -0.00175012 -0.00423921 -0.0058825  -0.006151   -0.00474595
 -0.0017044   0.00254816  0.00721645  0.0112324   0.01342358  0.01273202
  0.00845058  0.0004368  -0.01073669 -0.02372977 -0.03650247 -0.04650654
 -0.05098525 -0.04734644 -0.03355896 -0.00851486  0.02769991  0.07367348
  0.12670446  0.18301321  0.23810898  0.28727058  0.32607991  0.35093841
  0.35949665  0.35093841  0.32607991  0.28727058  0.23810898  0.18301321
  0.12670446  0.07367348  0.02769991 -0.00851486 -0.03355896 -0.04734644
 -0.05098525 -0.04650654 -0.03650247 -0.02372977 -0.01073669  0.0004368
  0.00845058  0.01273202  0.01342358  0.0112324   0.00721645  0.00254816
 -0.0017044  -0.00474595 -0.006151   -0.0058825  -0.00423921 -0.00175012
  0.00095883]

The impulse response is conveniently plotted using the sdr.plot.impulse_response() function.

plt.figure()
sdr.plot.impulse_response(fir, marker=".")
plt.show()
../../_images/6c8880a05780afb07438cda1e6ea18e7e9536113a3d6e2dfe79637f05319de8d.png

Examine the step response, \(s[n]\)

The step response of the FIR filter is computed and returned from the sdr.FIR.step_response() method. The step response \(s[n]\) is the output of the filter when the input is a unit step \(u[n]\).

s = fir.step_response()
print(s)
[ 0.00095883 -0.00175012 -0.00423921 -0.0058825  -0.006151   -0.00474595
 -0.0017044   0.00254816  0.00721645  0.0112324   0.01342358  0.01273202
  0.00845058  0.0004368  -0.01073669 -0.02372977 -0.03650247 -0.04650654
 -0.05098525 -0.04734644 -0.03355896 -0.00851486  0.02769991  0.07367348
  0.12670446  0.18301321  0.23810898  0.28727058  0.32607991  0.35093841
  0.35949665  0.35093841  0.32607991  0.28727058  0.23810898  0.18301321
  0.12670446  0.07367348  0.02769991 -0.00851486 -0.03355896 -0.04734644
 -0.05098525 -0.04650654 -0.03650247 -0.02372977 -0.01073669  0.0004368
  0.00845058  0.01273202  0.01342358  0.0112324   0.00721645  0.00254816
 -0.0017044  -0.00474595 -0.006151   -0.0058825  -0.00423921 -0.00175012
  0.00095883]

The step response is conveniently plotted using the sdr.plot.step_response() function.

plt.figure()
sdr.plot.step_response(fir, marker=".")
plt.show()
../../_images/5f93504a8755c02b255eb10a9dcdeb20d47559ade1b133de013f8bdea886ec8d.png

Examine the frequency response, \(H(\omega)\)

The frequency response is the transfer function \(H(z)\) evaluated at the complex exponential \(e^{j \omega}\), where \(\omega = 2 \pi f / f_s\).

The two-sided frequency response is conveniently plotted using the sdr.plot.magnitude_response() function.

plt.figure()
sdr.plot.magnitude_response(fir)
plt.show()
../../_images/932d4dc691cee99452b3a7049f9d12f88cd78b5e3171a3bbddc10d4a0819b11f.png

The one-sided frequency response, with logarithmic scale, can be plotted using the x_axis="log" keyword argument.

plt.figure()
sdr.plot.magnitude_response(fir, x_axis="log", decades=2)
plt.show()
../../_images/573597dcf3c30164f1bee02c17ffd304fb69baf3db1a17732333868bbd50c0b3.png

Examine the group delay, \(\tau_g(\omega)\)

The group delay \(\tau_g(\omega)\) is the time shift of the envelope of a signal passed through the filter as a function of its frequency \(\omega\).

The group delay is conveniently plotted using the sdr.plot.group_delay() function.

plt.figure()
sdr.plot.group_delay(fir)
plt.ylim(29, 31)
plt.show()
../../_images/f336241f3a525d9d3ae006d9bb026ef1e65c40e7cb58825d8ccef7afd6a7693c.png
plt.figure()
sdr.plot.group_delay(fir, x_axis="log")
plt.ylim(29, 31)
plt.show()
../../_images/112440b2b0a26a8f323929820473ecc1e68783c79c2ca13c1744997944af8af4.png

Fully analyze a FIR filter

The user can easily analyze the perform of a given IIR filter using the sdr.plot.filter() function.

Here is an FIR filter with one real zero and 8 complex poles.

h = sdr.root_raised_cosine(0.1, 12, 10)
fir = sdr.FIR(h)
plt.figure(figsize=(8, 6))
sdr.plot.filter(fir)
plt.show()
../../_images/69d0ac32a064b67d353bd40c0d183da2abcc2a03c6d160d6eaa11815dec329c5.png

Last update: Jan 21, 2024