1
$\begingroup$

I'm trying to create a real bandpass filter (17-point) in Python by calculating the coefficients b of a signal. This is the formula I'm using: $$b = \cos(ω(k-k_m))$$ for $k = 0,1,..,L-1$, where $k_m$ is the midpoint of the impulse response, $$k_m = 1/2(L-1)$$ I calculated omega with this formula: $$ω = 2πf/f_s$$ where $f_s=16000$ Hz and $f= 960$ Hz and therefore $ω = 0.12π$. The bandpass should be a 17 point bandpass filter. I suppose thats the $L$ in the formula if I'm correct, and therefore $$k_m = 1/2(L-1) = 1/2(17-1) = 8$$ So when putting all calculated variables in the formula i get: $$b = \cos(0.12π(k-8))$$ where $k$ is $0,1,...,16$. When calculating the coefficients for every $k$ until $16$ i get this coefficients array, which I use to filter my signal:

coefficients = np.array((-0.9921147013144778, -0.8763066800438634,-0.6374239897486894,-0.30901699437494734,0.06279051952931353,0.4257792915650728, 0.7289686274214116, 0.9297764858882515, 1.0, 0.9297764858882515, 0.7289686274214116,  0.4257792915650728,  0.06279051952931353,-0.30901699437494734,-0.6374239897486894, -0.8763066800438634, -0.9921147013144778))

However, this real bandpass should also have the center frequency 2000 Hz. My questions is how do I implement the center frequency, because I already have the coefficients(if I did it right) and if there is an easier way to calculate all this?

$\endgroup$

1 Answer 1

1
$\begingroup$

The easiest ways to generate a bandpass FIR filter in Python are to use one of firwin or remez.

Below are four filters: your original (blue), another like your original that is centered on 2000 Hz (green), a remez design (orange), and an firwin design (red).

The impulse responses are:

Impulse responses

The frequency responses are:

Frequency responses

Depending on your requirements, either the orange (remez) or red (firwin) designs are closer to what you want.


Python code below

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import remez, freqz, firwin

L = 17
k = np.arange(L)
km = (L-1)/2
fs = 16000
f = 960
f_center = 2000
omega = 2*f/fs*np.pi
omega_center = 2*f_center/fs*np.pi

b = np.cos(omega*(k-km))
b2 = np.cos(omega_center*(k-km))
           

edges = [0, f_center-f/2-160, f_center-f/2+160, f_center+f/2-160, f_center+f/2+160, fs/2 ]
b1 = remez(L, edges, [0, 1, 0], Hz=fs)
b3 = firwin(L, [f_center-f/2, f_center+f/2], pass_zero=False, fs=fs)

plt.figure(1)
plt.plot(b)
plt.plot(b1)
plt.plot(b2)
plt.plot(b3)

plt.figure(2)
w, mag = freqz(b, fs=fs)
w, mag1 = freqz(b1, fs=fs)
w, mag2 = freqz(b2, fs=fs)
w, mag3 = freqz(b3, fs=fs)
plt.plot(w,np.abs(mag)/np.abs(mag).max())
plt.plot(w, np.abs(mag1)/np.abs(mag1).max())
plt.plot(w, np.abs(mag2)/np.abs(mag2).max())
plt.plot(w, np.abs(mag3)/np.abs(mag3).max())
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.