2019-05-28 19:57:05 +03:00
/* SPDX-License-Identifier: GPL-2.0-only */
2008-10-07 08:41:46 +04:00
/*
* SpanDSP - a series of DSP components for telephony
*
* fir . h - General telephony FIR routines
*
* Written by Steve Underwood < steveu @ coppice . org >
*
* Copyright ( C ) 2002 Steve Underwood
*
* All rights reserved .
*/
# if !defined(_FIR_H_)
# define _FIR_H_
/*
Ideas for improvement :
1 / Rewrite filter for dual MAC inner loop . The issue here is handling
history sample offsets that are 16 bit aligned - the dual MAC needs
32 bit aligmnent . There are some good examples in libbfdsp .
2 / Use the hardware circular buffer facility tohalve memory usage .
3 / Consider using internal memory .
Using less memory might also improve speed as cache misses will be
reduced . A drop in MIPs and memory approaching 50 % should be
possible .
The foreground and background filters currenlty use a total of
about 10 MIPs / ch as measured with speedtest . c on a 256 TAP echo
can .
*/
2009-08-26 09:07:56 +04:00
/*
* 16 bit integer FIR descriptor . This defines the working state for a single
* instance of an FIR filter using 16 bit integer coefficients .
*/
2008-10-31 02:26:59 +03:00
struct fir16_state_t {
2008-10-07 08:41:46 +04:00
int taps ;
int curr_pos ;
const int16_t * coeffs ;
int16_t * history ;
2008-10-31 02:26:59 +03:00
} ;
2008-10-07 08:41:46 +04:00
2009-08-26 09:07:56 +04:00
/*
* 32 bit integer FIR descriptor . This defines the working state for a single
* instance of an FIR filter using 32 bit integer coefficients , and filtering
* 16 bit integer data .
*/
2008-10-31 02:26:59 +03:00
struct fir32_state_t {
2008-10-07 08:41:46 +04:00
int taps ;
int curr_pos ;
const int32_t * coeffs ;
int16_t * history ;
2008-10-31 02:26:59 +03:00
} ;
2008-10-07 08:41:46 +04:00
2009-08-26 09:07:56 +04:00
/*
* Floating point FIR descriptor . This defines the working state for a single
* instance of an FIR filter using floating point coefficients and data .
*/
2008-10-31 02:26:59 +03:00
struct fir_float_state_t {
2008-10-07 08:41:46 +04:00
int taps ;
int curr_pos ;
const float * coeffs ;
float * history ;
2008-10-31 02:26:59 +03:00
} ;
2008-10-07 08:41:46 +04:00
2009-03-12 03:32:45 +03:00
static inline const int16_t * fir16_create ( struct fir16_state_t * fir ,
const int16_t * coeffs , int taps )
2008-10-07 08:41:46 +04:00
{
fir - > taps = taps ;
fir - > curr_pos = taps - 1 ;
fir - > coeffs = coeffs ;
2008-10-17 21:55:03 +04:00
fir - > history = kcalloc ( taps , sizeof ( int16_t ) , GFP_KERNEL ) ;
2008-10-07 08:41:46 +04:00
return fir - > history ;
}
2009-03-12 03:32:45 +03:00
static inline void fir16_flush ( struct fir16_state_t * fir )
2008-10-07 08:41:46 +04:00
{
2008-10-21 03:01:31 +04:00
memset ( fir - > history , 0 , fir - > taps * sizeof ( int16_t ) ) ;
2008-10-07 08:41:46 +04:00
}
2009-03-12 03:32:45 +03:00
static inline void fir16_free ( struct fir16_state_t * fir )
2008-10-07 08:41:46 +04:00
{
2008-10-17 21:55:03 +04:00
kfree ( fir - > history ) ;
2008-10-07 08:41:46 +04:00
}
2009-03-12 03:32:45 +03:00
static inline int16_t fir16 ( struct fir16_state_t * fir , int16_t sample )
2008-10-07 08:41:46 +04:00
{
2008-10-21 03:01:31 +04:00
int32_t y ;
int i ;
int offset1 ;
int offset2 ;
fir - > history [ fir - > curr_pos ] = sample ;
offset2 = fir - > curr_pos ;
offset1 = fir - > taps - offset2 ;
y = 0 ;
for ( i = fir - > taps - 1 ; i > = offset1 ; i - - )
y + = fir - > coeffs [ i ] * fir - > history [ i - offset1 ] ;
for ( ; i > = 0 ; i - - )
y + = fir - > coeffs [ i ] * fir - > history [ i + offset2 ] ;
if ( fir - > curr_pos < = 0 )
fir - > curr_pos = fir - > taps ;
fir - > curr_pos - - ;
return ( int16_t ) ( y > > 15 ) ;
2008-10-07 08:41:46 +04:00
}
2009-03-12 03:32:45 +03:00
static inline const int16_t * fir32_create ( struct fir32_state_t * fir ,
const int32_t * coeffs , int taps )
2008-10-07 08:41:46 +04:00
{
2008-10-21 03:01:31 +04:00
fir - > taps = taps ;
fir - > curr_pos = taps - 1 ;
fir - > coeffs = coeffs ;
fir - > history = kcalloc ( taps , sizeof ( int16_t ) , GFP_KERNEL ) ;
return fir - > history ;
2008-10-07 08:41:46 +04:00
}
2009-03-12 03:32:45 +03:00
static inline void fir32_flush ( struct fir32_state_t * fir )
2008-10-07 08:41:46 +04:00
{
2008-10-21 03:01:31 +04:00
memset ( fir - > history , 0 , fir - > taps * sizeof ( int16_t ) ) ;
2008-10-07 08:41:46 +04:00
}
2009-03-12 03:32:45 +03:00
static inline void fir32_free ( struct fir32_state_t * fir )
2008-10-07 08:41:46 +04:00
{
2008-10-21 03:01:31 +04:00
kfree ( fir - > history ) ;
2008-10-07 08:41:46 +04:00
}
2009-03-12 03:32:45 +03:00
static inline int16_t fir32 ( struct fir32_state_t * fir , int16_t sample )
2008-10-07 08:41:46 +04:00
{
2008-10-21 03:01:31 +04:00
int i ;
int32_t y ;
int offset1 ;
int offset2 ;
fir - > history [ fir - > curr_pos ] = sample ;
offset2 = fir - > curr_pos ;
offset1 = fir - > taps - offset2 ;
y = 0 ;
for ( i = fir - > taps - 1 ; i > = offset1 ; i - - )
y + = fir - > coeffs [ i ] * fir - > history [ i - offset1 ] ;
for ( ; i > = 0 ; i - - )
y + = fir - > coeffs [ i ] * fir - > history [ i + offset2 ] ;
if ( fir - > curr_pos < = 0 )
fir - > curr_pos = fir - > taps ;
fir - > curr_pos - - ;
return ( int16_t ) ( y > > 15 ) ;
2008-10-07 08:41:46 +04:00
}
# endif