Community
cancel
Showing results for 
Search instead for 
Did you mean: 
John_J_2
Beginner
127 Views

Examples of IPP Bi-Quad Filter?

Hi All,

I'm trying to use IPP to run a bandpass filter one some audio data (single channel).

I've written the following class and helper function, but my results seem to be way off the mark. I hope this isn't too much code to dump

// BiQuad Coefs
// http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
struct BiQuad
{
float coefs[6];
};

// Return bandpass coefficients
BiQuad getBandPass( float f0, float Fs, float Q )
{
	float omega = IPP_2PI * f0 / Fs;
	float alpha = sinf( omega ) / ( 2.f*Q );

	float b0 = sinf( omega ) / 2.f;
	float b1 = 0.f;
	float b2 = -b0;
	float a0 = 1.f + alpha;
	float a1 = -2.f*cosf( omega );
	float a2 = 1.f - alpha;

	// Divide all by a0, set a0 to 1.f
	return{ {b0 / a0, b1 / a0, b2 / a0, 1.f, a1 / a0, a2 / a0} };
}

class IppBiquad
{
	int pBufSize{ 0 };
	int nBQ{ 0 };
	IppsIIRState_32f * m_State{ nullptr };
	Ipp8u * m_pBuf{ nullptr };
public:
	// Default constructor, takes # of cascaded filters
	IppBiquad( int N = 2 )
		: nBQ( N )
	{
		if ( nBQ > 0 )
		{
			ippsIIRGetStateSize_BiQuad_32f( 2, &pBufSize );
			m_pBuf = ippsMalloc_8u( pBufSize );
		}
	}
	// Set the filter components
	inline void setFilt( float f0, float Fs, float Q )
	{
		vector<BiQuad> taps( nBQ, getBandPass( f0, Fs, Q ) );
		ippsIIRInit_BiQuad_DF1_32f( &m_State, (Ipp32f *) taps.data( ), taps.size( ), 0, m_pBuf );
	}
	// Free work buf (Do I need to free the state?)
	~IppBiquad( )
	{
		if ( m_pBuf != nullptr )
			ippsFree( m_pBuf );
	}
	// Run the filter
	inline IppStatus operator()( float * input, float * output, int size )
	{
		if ( input && output && size > 0 && m_State )
			return ippsIIR_32f( input, output, size, m_State );
		return IppStatus::ippStsNullPtrErr;
	}
};

I use the BiQuad Struct to store my 6 float coefficients (taps, according to the docs), the getBandPass function to return the correct normalized taps for a Bandpass filter centered around f0 given the sample rate Fs and Q value, and I use the class in order to manage the work buffer without actually having to manage that.

When I need to run the filter, I invoke the () (parentheses) operator, sort of making my class like a function. To test the class I made an audio sample with several 500Hz sine wave "chirps" to see if I could get isolate the chirps. However I see the chirps most at very low frequencies (f0=100Hz), and it seems like the amplitude of my output has been changed somehow.

Am I interpreting the use of the BiQuad functions wrong? None of the examples in the docs actually use a BiQuad, they all use an arbitrary IIR filter (as far as I can tell).

I apologize in advance if the example is too object oriented; I'm happy to provide some straight C code, I just thought this was a bit clearer. Sorry for the use of std::vector, if anyone is averse to that...

Thanks for your help,

John

0 Kudos
2 Replies
Igor_A_Intel
Employee
127 Views

Hi John,

I don't see any problems in your code (for the 1st glance). IIR BQ always can be represented as AR filter, 1 BQ is an AR filter of the 2nd order. IPP IIR filters work in the same manner as Matlab filters - could you check your approach with Matlab (or any other reference code) and provide some more data: (1) taps in numerical form, (2) input data (also in numerical form) (3) desired output data (in numerical form, from Matlab or some reference code) and (4) output data from IPP function (also in numerical form). If there is any difference between (3) and (4) - I'll help you with correct IPP invoking.

regards, Igor

John_J_2
Beginner
127 Views

Hi Igor, thanks for the response.

Actually I was mistaken, the filter seems correct, however I'm doing some heavy downsampling to the output and that seems to throw off the results. I suppose I should look into the polyphase resampling functions...

 

Anyway, thanks for your help, and sorry to waste your time. I'm glad the class is OK. 

Reply