Sanket Jain
Sanket Jain

Reputation: 23

Design audio digital filter

I have been working on audio digital signal processing. I wish to design a digital filter. I have attached the screenshot. Of course, I can design band pass or bandstop filter using FIR/IIR filters, but what is special about this filter is that it controls low, mid and high frequencies. So my question, how can I design such filter in python enter image description here manually with this magnitude response as shown. Please help. I dont know how do I limit the filter to those values.

Another alternartive could be to such filter in MATLAB's filterdesigner tool and export the coefficients to python. But again, I dont know how to design such filter there. So please help.

Upvotes: 2

Views: 1233

Answers (1)

SleuthEye
SleuthEye

Reputation: 14579

There are a number of design options to match more arbitrary frequency band specifications than the simple lowpass/bandpass/bandstop/hipass classification. The most common ones are :

The first two are readily available from scipy.signal as scipy.firls and scipy.remez respectively, whereas the third can be done by taking the inverse FFT of the sampled frequency response curve.

Sample implementation using the least-square method:

from scipy import signal
import matplotlib.pyplot as plt
import numpy as np

bands = [0, fL1, fL2, fH1, fH2, fs/2]
desired = [Bl, Bl, 1, 1, Bh, Bh]
y = signal.firls(numtaps, bands, desired, fs=fs)
f,h = signal.freqz(y, fs=fs)

plt.plot(bands, desired, 'k', linewidth=2)
plt.plot(f, np.abs(h), 'r')

Sample implementation using the Parks-McClellan algorithm:

from scipy import signal
import matplotlib.pyplot as plt
import numpy as np

bands = [0, fL1, fL2, fH1, fH2, fs/2]
desired = [Bl, 1, Bh]
y = signal.remez(numtaps, bands, desired, fs=fs)
f,h = signal.freqz(y, fs=fs)

plt.plot(bands, desired, 'k', linewidth=2)
plt.plot(f, np.abs(h), 'b')

Sample implementation using the frequency sampling method:

from scipy import interpolate, fft
import matplotlib.pyplot as plt
import numpy as np

# interpolate desired response at equally spaced frequency points
interpolator = interpolate.interp1d(bands, desired)
N = 1024
fsampling = np.linspace(0, fs/2, N)
sampled = interpolator(fsampling)
# take the inverse FFT
y = fft.fftshift(fft.irfft(sampled))
# truncate response to keep numtaps coefficients
n1 = N-numtaps//2
n2 = n1 + numtaps
y = y[n1:n2]

For sake of illustration, using the following set of parameters

numtaps = 19
fL1 = 100
fL2 = 200
fH1 = 500
fH2 = 600
fs  = 1600
Bl  = 2
Bh  = 2.3

would yield the corresponding designs:

Frequency responses using least-squares, Parks-McClellan and frequency sampling design methods

Note that if your frequency specification curves are do-not-exceed values (rather than nominal ones), you can still use the above methods in an iterative fashion each time tweaking the bands and desired parameters until you converge to an acceptable response. With the initial set of parameters above, using the least-squares method, you could end up with tweaked parameters such as

bands   = [0, 100, 180, 520, 600, fs/2]
desired = [1.966,1.966,0.980,0.980,2.225,2.225]

with the corresponding response:

enter image description here

Upvotes: 1

Related Questions