0
$\begingroup$

I am designing an FIR filter to attenuate the frequencies below 300Hz. I designed the filter using the scipy functions and the code is as below.

from numpy import cos, sin, pi, absolute, arange
from scipy.signal import kaiserord, lfilter, firwin, freqz
from pylab import figure, clf, plot, xlabel, ylabel, xlim, ylim, title, grid, 
axes, show

nyq_rate = 48000 / 2
width = 100 / nyq_rate
ripple_db = 60.0
cutoff_hz = 300.0

N, beta = kaiserord(ripple_db, width)
taps = firwin(N, cutoff_hz/nyq_rate, window=('kaiser', beta), pass_zero='highpass')
w, h = freqz(taps, worN=512)

plot((w/pi)*nyq_rate, absolute(h), linewidth=2)
xlabel('Frequency (Hz)')
ylabel('Gain')
title('Frequency Response')
ylim(-0.05, 1.05)
grid(True)

show()

When I a execute it, the following error pops up.

ValueError: A filter with an even number of coefficients must have zero response at the Nyquist frequency.

I am not sure what is going wrong. Any help is appreciated.

$\endgroup$
  • $\begingroup$ Okay. I think the error is using even number of filter coefficients. Adding 1 to N gets rid of the error. $\endgroup$ – Dennis.M Jul 30 at 11:52
  • $\begingroup$ Possible duplicate of Low Pass FIR Filter $\endgroup$ – Jonas Schwarz Jul 30 at 15:18
0
$\begingroup$

As you've already figured out, you need to choose an odd filter length. I'll explain why. You're designing a linear phase FIR filter, and such filters satisfy certain symmetry conditions. See this answer explaining the four types of linear phase FIR filters (even/odd length, even/odd symmetry).

For frequency selective filters, such as the one you're trying to design, you need filters with even symmetry (type I or type II). An even length (type II) filter necessarily has a zero at Nyquist, so you can't use it to design a high pass filter. A type I filter (even symmetry, odd filter length) doesn't have this restriction, so in order to design a linear phase high pass filter you need to choose an odd filter length, i.e., a type I linear phase FIR filter.

$\endgroup$
  • $\begingroup$ How can I pass the attenuation factor for stop band as an input while deisgning filter in Python? In the scipy provided functions like kaiserord, there is an argument called ripple. But after assigining that argument to 12 dB I don't see the relative change in the frequency response. $\endgroup$ – Dennis.M Jul 31 at 12:16
  • $\begingroup$ @Dennis.M: I don't use Python, but I think I know what ´kaiserord´ is doing. You should try a higher value for 'ripple', maybe 60 dB. $\endgroup$ – Matt L. Aug 1 at 9:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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