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