How to set up and run an IIR bandpass filter

How to set up and run an IIR bandpass filter

I have a rather slow signal (256Hz) and I've been using the IPP functions rather nicely to perform FIR-based bandpass filtering on this signal.  I use the 'ippsFIRGenBandpass_xx' methods to generate my taps vector (taps length of 60 and Hamming windowing).

Now I would like to run some IIR-based bandpass filters.  Unfortunately, I've not been able to get this to work.  First, there is no IPP function to generate an IIR-based bandpass taps vector.  I can successfully create and run both low-pass and high-pass filters, but not bandpass.

I've used MATLAB to check my work. The taps vectors for the low-pass and high-pass filters I created using the IPP methods were identical to what MATLAB created for me (as well as the filtered results).

I then created a taps vector for an IIR-based filter in MATLAB and just tried to use that in the IPP filter call (ippsIIRxxx) but the results were not correct.  I'm using a filter order of 12 and taps length of (2 * (order + 1)) = 26.  I tried this with a delay buffer and without, all produced the same results...

Any ideas?

thanks.

12 post / 0 nuovi
Ultimo contenuto
Per informazioni complete sulle ottimizzazioni del compilatore, consultare l'Avviso sull'ottimizzazione

>>...I then created a taps vector for an IIR-based filter in MATLAB and just tried to use that in the IPP filter call (ippsIIRxxx) but
>>the results were not correct. I'm using a filter order of 12 and taps length of (2 * (order + 1)) = 26...

It is not clear how anyone could help you because these are just general details. There are lots of IIR functions in IPP header file for DSP domain ( I think ~100 or so ). Do you have a test-case?

Well, my question is rather general. I was hoping that no one would have responded with, "No, you can't perform an IIR filter using bandpass semanics, only high-pass or low-pass." Since that didn't happen, the code details follow. Error checking removed, also the taps and state variables are held in C++ class structure so they are persisted across 'filter()' calls. The 'initialize()' method is called once, the 'filter' method is called repeatedly with typically 4 samples over many minutes of data (256Hz sample rate data).


// set up

initialize() {

    IppStatus status;

    int _order = 12;

    int _nTaps = 26;

    IppsIIRFilterType _iirwindow = ippChebyshev1;

    Ipp64f * pTaps1 = ippsMalloc_64f(_nTaps);

    pTaps1[0] = 0.0429;

    pTaps1[1] = 0;

    . . .

    IppsIIRState64f_32f * pStateIIR_lo;

    status = ippsIIRInitAlloc64f_32f(&pStateIIR_lo, pTaps1, _order,0);

}
// run filter

filter(float *pSrc, float *pDst, int n) {

    status = ippsIIR64f_32f(pSrc, pDst, n, pStateIIR_lo);

}


1st question. Since IPP supplies taps vector generation for low-pass and high-pass IIR filtering, can we somehow string together two filters, the first doing a low-pass and the second filter takes the result of the first filter and performs a high-pass filter?

2nd question. We created a taps vector in MATLAB with band-pass filter semantics (sample code above) with order 12 (taps length 26) and that failed. The amplitude of the filtered signal quickly oscillated between positive and negative infinity. This same taps vector worked fine in MATLAB. Interesting difference, however, in MATLAB we're filtering a sample signal of about 4000 samples, however, in our code we're just calling the 'ippsIIR64f_32f()' method with 4 samples at a time. Is that the problem using high-order filters?

Thanks again for your help.

I did a quick check of my personal Engineering Notebook records and C/C++ sources ( not IPP based / 2006 year ).

>>...
>>Now I would like to run some IIR-based bandpass filters. Unfortunately, I've not been able to get this to work. First, there is no IPP function to
>>generate an IIR-based bandpass taps vector. I can successfully create and run both low-pass and high-pass filters, but not bandpass.
>>...

I don't see any constraints for a generic not IPP based applications. In practice, for example in optics, two filters, a Low-Pass and High-Pass, with some Cut-off Frequences could be combined in order to create a Band-pass filter or a Band-Reject filter.

In my C/C++ image processing tests ( not IPP based / 2006 year ) I have several paths:
...
case 'n':
printf( "\nSelect Type of Filter ( 1, 2, 3 or 4 ):\n" );
printf( "\t1. Low-Pass\n" );
printf( "\t2. High-Pass\n" );
printf( "\t3. Band-Pass\n" );
printf( "\t4. Band-Reject\n" );
...
case '3':
case '4':
printf( "\nEnter LOWER Cut-off Frequency in Rad/Sec ( <= PI-number ):\n" );
...
printf( "\nEnter UPPER Cut-off Frequency in Rad/Sec ( <= PI-number ):\n" );
...

>>...I then created a taps vector for an IIR-based filter in MATLAB...

A Band-pass?

>>...and just tried to use that in the IPP filter call ( ippsIIRxxx ) but the results were not correct.

I'm not sure that it could work and a response from IPP team is needed on if it is a right attempt to do Band-pass filtering with ippsIIR_xxx functions.

Quote:

Sergey Kostrov wrote:
>>...I then created a taps vector for an IIR-based filter in MATLAB...
A Band-pass?

Yes.
Quote:
Sergey Kostrov wrote:

I'm not sure that it could work and a response from IPP team is needed on if it is a right attempt to do Band-pass filtering with ippsIIR_xxx functions.


Are you saying that I cannot create an IIR taps vector with band-pass semantics in MATLAB and use that in the 'ippsIIR_xxx' functions?

Also, I've seen in other posts that one should 'initialize the delay line as per the MATLAB direct form II documentation. I have looked high and low but cannot find documentation in MATLAB that describes how to initialize the delay line buffer. Can you point me to this documentation?

Thanks.

From what I've read in the IPP documentation it is not necessary to initialize the delay line. It just has to be the same length as the taps vector.

>>...MATLAB that describes how to initialize the delay line buffer. Can you point me to this documentation?

Unfortunately No because I don't have MATLAB.

Quote:

Chuck De Sylva (Intel) wrote:

From what I've read in the IPP documentation it is not necessary to initialize the delay line. It just has to be the same length as the taps vector.


Hmm, Here's what I see in the IIRInit description:

Parameters
pTaps

	Pointer to the array containing the taps. The number of elements in the array is 2*(order+1).
tapsFactor

	Scale factor for the taps of integer data type.
order

	Order of the IIR filter.
pDlyLine

	Pointer to the array containing the delay line values. The number of elements in the array is order.


Looks like the length of the delay line vector is 'order' and taps vector is '2*(order+1)'.

I changed the length of the delay line to 'nTaps' length and got the same values out of the filter. Given the various algorithms I've seen, the delay line vector only needs to be 'order' length.

Quote:

Sergey Kostrov wrote:

I'm not sure that it could work and a response from IPP team is needed on if it is a right attempt to do Band-pass filtering with ippsIIR_xxx functions.


We've been successful at creating taps vectors for low-pass and high-pass IIR filters in MATLAB and using those in IPP. In fact, if we call the ippsIIRGenLowpass_64f and ippsIIRGenHighpass_64f functions we get the same taps values as MATLAB so we're pretty confident with those.

However, if use MATLAB to generate a taps vector with band-pass semantics (order 6) and use those in our IPP filtering call (ippsIIR64f_32f), the filtered signal diverges pretty quickly.

We're going to try bi-quad methods tomorrow....

>>...However, if use MATLAB to generate a taps vector with band-pass semantics (order 6) and use those in our IPP filtering call ( ippsIIR64f_32f ),
>>the filtered signal diverges pretty quickly...

What about a Window function? What if MATLAB uses a Window function A and IPP uses a Window finction B?

Quote:

Sergey Kostrov wrote:

What about a Window function? What if MATLAB uses a Window function A and IPP uses a Window finction B?


Both of my tests (MATLAB and IPP) use the Chebyshev1 window. The IPP code:

status = ippsIIRGenLowpass_64f(hiFreqNormal, _ripple, _order, _pTaps1, ippChebyshev1);


The MATLAB code:

[d,c] = cheby1(6,0.1,[.19140625 .19921875]);

It's all about the biquads for IIR bandpass filters.

We successfully ran two biquad filter prototypes with Chebyshev1 windowing. One used order 2 and one used order 6. For the biquad filter, we used the 'order' to represent the number of biquads. We found a biquad coefficient generator and ran our tests using the 'ippsIIRInitAlloc64f_BiQuad_32f()' method to generate the state variable then the basic 'ippsIIR64f_32f()' to perform the filter.

The results matched exactly what MATLAB provided with the 'cheby1(2,0.1,[.19140625 .19921875]);' and 'cheby1(6,0.1,[.19140625 .19921875]);' functions.

Muuuuch more testing is needed but I'm guessing we'll stick with basic IIR filters for lowpass and highpass filter, but for bandpass we'll use the biquad method.

Accedere per lasciare un commento.