From 925839ffdfabecc5a38f7e0ede0a41877f7d5032 Mon Sep 17 00:00:00 2001
From: Eric Kooistra <kooistra@astron.nl>
Date: Wed, 17 Jan 2024 11:10:27 +0100
Subject: [PATCH] Add iir_biquad_butter_coefficients(), for biquads used in
 TBB.

---
 applications/lofar2/model/pfb_os/dsp.py | 41 ++++++++++++++++++++++---
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/applications/lofar2/model/pfb_os/dsp.py b/applications/lofar2/model/pfb_os/dsp.py
index e3a8a068fb..e9e99dac0b 100644
--- a/applications/lofar2/model/pfb_os/dsp.py
+++ b/applications/lofar2/model/pfb_os/dsp.py
@@ -117,7 +117,7 @@ def impulse_at_zero_crossing(x):
 
 
 ###############################################################################
-# Filter design
+# FIR Filter design
 ###############################################################################
 
 def nof_taps_kaiser_window(fs, fpass, fstop, atten_db):
@@ -157,7 +157,7 @@ def ideal_low_pass_filter(Npoints, Npass, bandEdgeGain=1.0):
     # Magnitude frequency reponse
     HF = np.zeros([Npoints])
     HF[0] = bandEdgeGain
-    HF[1 : Npass - 1] = 1
+    HF[1: Npass - 1] = 1
     HF[Npass - 1] = bandEdgeGain
     # Zero center HF to make it even
     HF = np.roll(HF, -(Npass // 2))
@@ -222,6 +222,39 @@ def fourier_interpolate(HFfilter, Ncoefs):
     return hInterpolated.real
 
 
+###############################################################################
+# IIR Filter design
+###############################################################################
+
+def iir_biquad_butter_coefficients(f0, BW, band='bandstop', fs=1):
+    """Calculate b0, b1, b2, a0, a1, a2 for biquad IIR filter section.
+
+    Bilinear transform of Butterworth filters. From
+    https://webaudio.github.io/Audio-EQ-Cookbook/Audio-EQ-Cookbook.txt
+
+    For single biquad bandpass alternatively use signal.iirpeak()
+    For single biquad bandstop alternatively use signal.iirnotch()
+    """
+    w0 = 2 * np.pi * f0 / fs
+    Q = f0 / BW
+    si = np.sin(w0)
+    cs = np.cos(w0)
+    alpha = np.sin(w0) / (2 * Q)
+    a1 = -2 * cs
+    if band == 'lowpass':
+        b0 = 1 - cs
+        b = [b0 / 2, b0, b0 / 2]
+    elif band == 'highpass':
+        b0 = 1 + cs
+        b = [b0 / 2, -b0, b0 / 2]
+    elif band == 'bandstop':
+        b = [1, a1, 1]
+    elif band == 'bandpass':
+        b = [si / 2, 0, -si / 2]
+    a = [1 + alpha, a1, 1 - alpha]
+    return b, a
+
+
 ###############################################################################
 # Hilbert transform filter
 ###############################################################################
@@ -475,7 +508,7 @@ def plot_spectra(f, HF, fs=1.0, fLim=None, dbLim=None):
     plt.grid(True)
 
 
-def plot_power_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, dbLim=None, showRoll=False):
+def plot_power_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, dbLim=None):
     """Plot power spectrum
 
     Input:
@@ -485,7 +518,7 @@ def plot_power_spectrum(f, HF, fmt='r', fs=1.0, fLim=None, dbLim=None, showRoll=
     . fs: sample frequency in Hz, scale f by fs, fs >= 1
     """
     if fs > 1:
-        flabel = 'Frequency [fs / %d]' % fs
+        flabel = 'Frequency'
     else:
         flabel = 'Frequency [fs]'
 
-- 
GitLab