FIR filters

import numpy as np
import matplotlib.pyplot as plt

import sdr

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

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.00095881 -0.00175008 -0.00423912 -0.00588237 -0.00615087 -0.00474585
 -0.00170436  0.0025481   0.00721629  0.01123216  0.01342329  0.01273174
  0.00845039  0.00043678 -0.01073645 -0.02372925 -0.03650167 -0.04650553
 -0.05098414 -0.04734541 -0.03355823 -0.00851466  0.0276993   0.07367186
  0.12670168  0.18306847  0.2381038   0.28726435  0.32607284  0.3509308
  0.35948882  0.3509308   0.32607284  0.28726435  0.2381038   0.18306847
  0.12670168  0.07367186  0.0276993  -0.00851466 -0.03355823 -0.04734541
 -0.05098414 -0.04650553 -0.03650167 -0.02372925 -0.01073645  0.00043678
  0.00845039  0.01273174  0.01342329  0.01123216  0.00721629  0.0025481
 -0.00170436 -0.00474585 -0.00615087 -0.00588237 -0.00423912 -0.00175008
  0.00095881]

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

plt.figure(figsize=(10, 5))
sdr.plot.impulse_response(fir.taps, marker=".")
plt.show()
../../_images/ba176406a8563f02235be3772089790a5f9de557f39239da67667e497700df36.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.00095881 -0.00175008 -0.00423912 -0.00588237 -0.00615087 -0.00474585
 -0.00170436  0.0025481   0.00721629  0.01123216  0.01342329  0.01273174
  0.00845039  0.00043678 -0.01073645 -0.02372925 -0.03650167 -0.04650553
 -0.05098414 -0.04734541 -0.03355823 -0.00851466  0.0276993   0.07367186
  0.12670168  0.18306847  0.2381038   0.28726435  0.32607284  0.3509308
  0.35948882  0.3509308   0.32607284  0.28726435  0.2381038   0.18306847
  0.12670168  0.07367186  0.0276993  -0.00851466 -0.03355823 -0.04734541
 -0.05098414 -0.04650553 -0.03650167 -0.02372925 -0.01073645  0.00043678
  0.00845039  0.01273174  0.01342329  0.01123216  0.00721629  0.0025481
 -0.00170436 -0.00474585 -0.00615087 -0.00588237 -0.00423912 -0.00175008
  0.00095881]

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

plt.figure(figsize=(10, 5))
sdr.plot.step_response(fir.taps, marker=".")
plt.show()
../../_images/ea3859cf79dbe448db1ed3f409bafb26c220d7ab66f3c026d6f8c2b69a33e4f8.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.frequency_response() function.

plt.figure(figsize=(10, 5))
sdr.plot.frequency_response(fir.taps)
plt.show()
../../_images/51a94d203c712e772df51565690e35ae22278bab51342ba7985f70d816e745d6.png

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

plt.figure(figsize=(10, 5))
sdr.plot.frequency_response(fir.taps, x_axis="log", decades=2)
plt.show()
../../_images/880e4dd6bb05533ce8d25af996fc87ce08b3f8a04cbb96e05cc32646d64cfac1.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(figsize=(10, 5))
sdr.plot.group_delay(fir.taps)
plt.ylim(fir.delay - 2, fir.delay + 2)
plt.show()
../../_images/6d71f512dacc86919e2dd219d44e1b5bdb72697f8078de45686469b533c80c23.png
plt.figure(figsize=(10, 5))
sdr.plot.group_delay(fir.taps, x_axis="log")
plt.ylim(fir.delay - 2, fir.delay + 2)
plt.show()
../../_images/21748dda776aecac74d47797264d07100184dc628d6b25ab33d950b17d7fc6ee.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=(10, 8))
sdr.plot.filter(fir.taps)
plt.show()
../../_images/4c52b83041e7c128b69804779d9e83858f489c817d6690ecaa1998ef506ec132.png

Last update: Jul 15, 2023