问题描述:

I need to make a simple bandpass audio filter.

Now I've used this simple C++ class: http://www.cardinalpeak.com/blog/a-c-class-to-implement-low-pass-high-pass-and-band-pass-filters

It works well and cut off the desired bands. But when I try to change upper or lower limit with small steps, on some values of limit I hear the wrong result - attenuated or shifted in frequency (not corresponding to current limits) sound.

Function for calculating impulse response:

`void Filter::designBPF()`

{

int n;

float mm;

for(n = 0; n < m_num_taps; n++){

mm = n - (m_num_taps - 1.0) / 2.0;

if( mm == 0.0 ) m_taps[n] = (m_phi - m_lambda) / M_PI;

else m_taps[n] = ( sin( mm * m_phi ) -

sin( mm * m_lambda ) ) / (mm * M_PI);

}

return;

}

where

`m_lambda = M_PI * Fl / (Fs/2);`

m_phi = M_PI * Fu / (Fs/2);

Fs - sample rate (44.100)

Fl - lower limit

Fu - upper limit

And simple filtering function:

`float Filter::do_sample(float data_sample)`

{

int i;

float result;

if( m_error_flag != 0 ) return(0);

for(i = m_num_taps - 1; i >= 1; i--){

m_sr[i] = m_sr[i-1];

}

m_sr[0] = data_sample;

result = 0;

for(i = 0; i < m_num_taps; i++) result += m_sr[i] * m_taps[i];

return result;

}

Do I need to use any window function (Blackman, etc.)? If yes, how do I do this?

I have tried to multiply my impulse response to Blackman window:

`m_taps[n] *= 0.42 - 0.5 * cos(2.0 * M_PI * n / double(N - 1)) +`

0.08 * cos(4.0 * M_PI * n / double(N - 1));

but the result was wrong.

And do I need to normalize taps?

I found a good free implementation of FIR filter: http://www.iowahills.com/A7ExampleCodePage.html

...This Windowed FIR Filter C Code has two parts, the first is the calculation of the impulse response for a rectangular window (low pass, high pass, band pass, or notch). Then a window (Kaiser, Hanning, etc) is applied to the impulse response. There are several windows to choose from...

y[i] = waveform[i] × (0.42659071 – 0.49656062cos(w) + 0.07684867cos(2w))

where w = (2)i/n and n is the number of elements in the waveform

Try this I got the code from: http://zone.ni.com/reference/en-XX/help/370592P-01/digitizers/blackman_window/

I hope this helps.