@ -3,7 +3,9 @@
* ( floating point audio ) .
* ( floating point audio ) .
* MIT License on changed portions
* MIT License on changed portions
* Bob Larkin March 2021 original write
* Bob Larkin March 2021 original write
* Rev 21 Jan 2022 Major redo and ready to publish . RSL
* Rev 21 Jan 2022 Major redo and ready to publish . Bob L
* Rev 15 March 2023 - Added dynamic sample rate control ; added 12 ksps ; corrected
* receiveWritable_f32 ( ) for block with output . Bob L
*
*
* This is specific for the CTCSS tone system
* This is specific for the CTCSS tone system
* with tones in the 67.0 to 254.1 Hz range .
* with tones in the 67.0 to 254.1 Hz range .
@ -127,7 +129,7 @@
* filtering and to reduce processing load . The filter parameters of the decimation
* filtering and to reduce processing load . The filter parameters of the decimation
* LPF can be used at any sampling rate from 44 to 100 kHz . Other rates will need
* LPF can be used at any sampling rate from 44 to 100 kHz . Other rates will need
* a new design for the LPF . See the discussion below for " iirLpfCoeffs " showing
* a new design for the LPF . See the discussion below for " iirLpfCoeffs " showing
* how to design such a filter .
* how to design such a filter . ( Mar 2023 : Decimate by 8 for 12 ksps ) .
*
*
* The bandpass filter to cover 67 to 254 Hz is predesigned for sample rates near
* The bandpass filter to cover 67 to 254 Hz is predesigned for sample rates near
* 44 , 48 , 96 or 100 kHz . The discussion below " BPF iir Coefficients " has
* 44 , 48 , 96 or 100 kHz . The discussion below " BPF iir Coefficients " has
@ -138,7 +140,7 @@
*
*
* Note - Pieces of this support block sizes other than 128 , but not all .
* Note - Pieces of this support block sizes other than 128 , but not all .
* Work needs to be done to implement and test variable block size . The same is
* Work needs to be done to implement and test variable block size . The same is
* true for sample rates outside the 44.1 to 100 kHz range .
* true for sample rates outside the 12 and 44.1 to 100 kHz range .
*/
*/
# ifndef analyze_CTCSS_F32_h_
# ifndef analyze_CTCSS_F32_h_
@ -165,42 +167,83 @@ public:
initCTCSS ( ) ;
initCTCSS ( ) ;
}
}
// This is called at instantation and also if either freq or sample_rate_Hz is changed
void initCTCSS ( void )
void initCTCSS ( void )
{
{
frequency ( 103.5f , 300.0f ) ; // Defaults
gEnabled = true ;
setNotchX4 ( 103.5f ) ;
float32_t nDecimatef = ( float32_t ) nDecimate ; // Later use
// Initialize BiQuad instance (ARM DSP Math Library)
// INFO: I nitialize BiQuad instance (ARM DSP Math Library)
//https://www.keil.com/pack/doc/CMSIS/DSP/html/group__BiquadCascadeDF1.html
//https://www.keil.com/pack/doc/CMSIS/DSP/html/group__BiquadCascadeDF1.html
arm_biquad_cascade_df1_init_f32 ( & iir_lpf_inst , 2 , & iirLpfCoeffs [ 0 ] , & StateLpf32 [ 0 ] ) ;
// First, select the BPF for measuring the noise level
if ( iirUserBpfCoeffs ! = NULL )
iirBpfCoeffs = iirUserBpfCoeffs ; // From INO, always use if supplied
//else if(sample_rate_Hz>11000.0f && sample_rate_Hz<11050.0f)
//iirBpfCoeffs = coeff32bp11; Not currently implemented
else if ( sample_rate_Hz > 11975.0f & & sample_rate_Hz < 12025.0f )
iirBpfCoeffs = coeff32bp12 ;
//else if(sample_rate_Hz>23950.0f && sample_rate_Hz<24050.0f)
//iirBpfCoeffs = coeff32bp24; Not currently implemented
else if ( sample_rate_Hz > 43900.0f & & sample_rate_Hz < 44200.0f )
iirBpfCoeffs = coeff32bp44 ;
else if ( sample_rate_Hz > 47900.0f & & sample_rate_Hz < 48100.0f )
iirBpfCoeffs = coeff32bp48 ;
else if ( sample_rate_Hz > 95800.0f & & sample_rate_Hz < 96200.0f )
iirBpfCoeffs = coeff32bp96 ;
else if ( sample_rate_Hz > 99800.0f & & sample_rate_Hz < 100200.0f )
iirBpfCoeffs = coeff32bp100 ;
else gEnabled = false ;
arm_biquad_cascade_df1_init_f32 ( & iir_bpf_inst , 4 , iirBpfCoeffs , & StateBpf32 [ 0 ] ) ;
arm_biquad_cascade_df1_init_f32 ( & iir_bpf_inst , 4 , iirBpfCoeffs , & StateBpf32 [ 0 ] ) ;
for ( int i = 0 ; i < 8 ; i + + )
if ( sample_rate_Hz > 11900 & & sample_rate_Hz < 24100 ) // Now choose a pre-decimation LPF
{
{
d16a [ i ] = 0.0f ;
nDecimate = 8 ;
d16b [ i ] = 0.0f ;
arm_biquad_cascade_df1_init_f32 ( & iir_lpf_inst , 4 , & iirLpfCoeffs12 [ 0 ] , & StateLpf32 [ 0 ] ) ;
}
}
arm_biquad_cascade_df1_init_f32 ( & iir_nulls_inst , 4 , & iirNullsCoeffs [ 0 ] , & StateNullsF32 [ 0 ] ) ;
else if ( sample_rate_Hz > 44000 & & sample_rate_Hz < 100100 )
thresholds ( 0.1f , 1.0f ) ;
{
gEnabled = true ;
nDecimate = 16 ;
setCTCSS_BP ( NULL ) ; // May be invalid if Sample rate is not provided for here.
arm_biquad_cascade_df1_init_f32 ( & iir_lpf_inst , 4 , & iirLpfCoeffs44 [ 0 ] , & StateLpf32 [ 0 ] ) ;
}
}
else gEnabled = false ;
nDecimatef = ( float32_t ) nDecimate ;
sampleRate2 = sample_rate_Hz / nDecimatef ;
// Set frequency and length of Goertzel in Hz and milliseconds.
for ( int i = 0 ; i < 16 ; i + + ) // Need 8 when decimate is 16 or 16 if decimate is 8
void frequency ( float freq ) { // Defaults to 300 mSec
{
frequency ( freq , 300.0f ) ;
d16a [ i ] = 0.0f ;
d16b [ i ] = 0.0f ;
}
}
arm_biquad_cascade_df1_init_f32 ( & iir_nulls_inst , 4 , & iirNullsCoeffs [ 0 ] , & StateNullsF32 [ 0 ] ) ;
void frequency ( float freq , float tMeas ) {
// e.g. freq=103.5, tMeas=250, sample_rate_Hz = 44100, gLength=689
// e.g. freq=103.5, tMeas=250, sample_rate_Hz = 44100, gLength=689
gLength = ( uint16_t ) ( 0.5 + sample_rate_Hz * tMeas / ( 1000.0f * 16 ) ) ; // reinstated
gLength = ( uint16_t ) ( 0.5 + sample_rate_Hz * tMeas / ( 1000.0f * nDecimatef ) ) ; // reinstated
// Now set the notch filters for the four-biquad notch filters
// Now set the notch filters for the four-biquad notch filters
setNotchX4 ( freq ) ;
setNotchX4 ( freq ) ;
// and the sub-audible general BP filter
setCTCSS_BP ( NULL ) ;
// e.g., freq=103.5, sample_rate_Hz=44100, gCoefficient=2*cos(0.23594)=1.944634
// e.g., freq=103.5, sample_rate_Hz=44100, gCoefficient=2*cos(0.23594)=1.944634
gCoefficient = 2.0f * cosf ( 6.28318530718f * 16.0 f* freq / sample_rate_Hz ) ;
gCoefficient = 2.0f * cosf ( 6.28318530718f * nDecimate f* freq / sample_rate_Hz ) ;
// Another constant for ending calculation is exp(-j 2*pi*16*freq*(glength-1)/sample_rate_Hz)
// Another constant for ending calculation is exp(-j 2*pi*16*freq*(glength-1)/sample_rate_Hz)
ccRe = cos ( 6.28318530718f * 16.0f * freq / sample_rate_Hz ) ;
ccRe = cos ( 6.28318530718f * nDecimatef * freq / sample_rate_Hz ) ;
ccIm = - sin ( 6.28318530718f * 16.0f * freq / sample_rate_Hz ) ;
ccIm = - sin ( 6.28318530718f * nDecimatef * freq / sample_rate_Hz ) ;
thresholds ( 0.1f , 1.0f ) ;
}
// Set frequency and length of Goertzel detect tone in Hz and milliseconds.
void frequency ( float32_t _freq ) { // Defaults to 300 mSec
frequency ( _freq , 300.0f ) ;
}
void frequency ( float32_t _freq , float32_t _tMeas ) {
freq = _freq ;
tMeas = _tMeas ;
initCTCSS ( ) ;
}
// Sample rates 12, 44.1, 48, 96 and 100 ksps are supported.
void setSampleRate_Hz ( const float32_t & fs_Hz ) {
sample_rate_Hz = fs_Hz ;
initCTCSS ( ) ;
}
}
bool available ( void ) {
bool available ( void ) {
@ -212,9 +255,9 @@ public:
return flag ;
return flag ;
}
}
floa t readTonePower ( void ) { return powerTone ; }
float32_ t readTonePower ( void ) { return powerTone ; }
floa t readRefPower ( void ) { return powerRef ; }
float32_ t readRefPower ( void ) { return powerRef ; }
const uint16_t isAbsThreshold = 1 ;
const uint16_t isAbsThreshold = 1 ;
const uint16_t isRelThreshold = 2 ;
const uint16_t isRelThreshold = 2 ;
@ -229,7 +272,7 @@ public:
else return false ; // Something was wrong about call
else return false ; // Something was wrong about call
}
}
void thresholds ( float levelAbs , floa t levelRel ) {
void thresholds ( float32_t levelAbs , float32_ t levelRel ) {
// The absolute threshold is compared with tonePower
// The absolute threshold is compared with tonePower
if ( levelAbs < 0.000001f ) threshAbs = 0.000001f ;
if ( levelAbs < 0.000001f ) threshAbs = 0.000001f ;
else threshAbs = levelAbs ;
else threshAbs = levelAbs ;
@ -244,29 +287,16 @@ public:
virtual void update ( void ) ;
virtual void update ( void ) ;
/* The bandpass filter covers 67 to 254 Hz to allow a comparison
/* The bandpass filter covers 67 to 254 Hz to allow a comparison
* measurement for the tone . This changes with sample rate . Four
* measurement for the tone . This changes with sample rate . Five
* precomputed filters are provided for 44.1 , 48 , 96 and 100 kHz .
* precomputed filters are provided for 12 , 44.1 , 48 , 96 and 100 kHz .
* Supply a NULL for the filterCoeffs to use these 4 .
* Supply a NULL for the filterCoeffs to use these five .
* filterCoeffs points to an array of 20 floats that are IIR
* _ filterCoeffs points to an array of 20 floats that are IIR
* coefficients for four BiQuad Stages . To use caller supplied
* coefficients for four BiQuad Stages . To use caller supplied
* filter coefficients , call with a pointer to that 4 x BiQuad filter at
* filter coefficients , call with a pointer to that 4 x BiQuad filter at
* filterCoeffs .
* filterCoeffs .
*/
*/
float * setCTCSS_BP ( float * filterCoeffs )
float * setCTCSS_BP ( float32_t * _filterCoeffs ) {
{
iirUserBpfCoeffs = _filterCoeffs ; // Caller supplied
if ( filterCoeffs = = NULL )
{
if ( sample_rate_Hz > 43900.0f & & sample_rate_Hz < 44200.0f )
iirBpfCoeffs = coeff32bp44 ;
else if ( sample_rate_Hz > 47900.0f & & sample_rate_Hz < 48100.0f )
iirBpfCoeffs = coeff32bp48 ;
else if ( sample_rate_Hz > 95800.0f & & sample_rate_Hz < 96200.0f )
iirBpfCoeffs = coeff32bp96 ;
else if ( sample_rate_Hz > 99800.0f & & sample_rate_Hz < 100200.0f )
iirBpfCoeffs = coeff32bp100 ;
else return NULL ;
}
else iirBpfCoeffs = filterCoeffs ; // Caller supplied
return iirBpfCoeffs ;
return iirBpfCoeffs ;
}
}
@ -275,7 +305,7 @@ public:
* Call this function with a pointer to that array . To stop windowing ,
* Call this function with a pointer to that array . To stop windowing ,
* call this function with NULL as an argument .
* call this function with NULL as an argument .
* / Windowing not yet implemented < < < - - - - - - - - - - - - - - - - - - -
* / Windowing not yet implemented < < < - - - - - - - - - - - - - - - - - - -
void setGWindow ( floa t * pWinCoeff )
void setGWindow ( float32_ t * pWinCoeff )
{
{
windowCoeff = pWinCoeff ; // Point to the caller supplied window function
windowCoeff = pWinCoeff ; // Point to the caller supplied window function
if ( pWinCoeff ! = NULL )
if ( pWinCoeff ! = NULL )
@ -287,35 +317,39 @@ public:
private :
private :
int16_t count16 = 0 ; unsigned long cnt = 0UL ;
int16_t count16 = 0 ; unsigned long cnt = 0UL ;
float ccRe = 0.0f ;
float32_t ccRe = 0.0f ;
float ccIm = 0.0f ;
float32_t ccIm = 0.0f ;
float freq = 103.5f ;
float32_t freq = 103.5f ;
float tMeas = 300.0f ;
float32_t tMeas = 300.0f ;
float d16a [ 8 ] ; // Small data blocks, after decimation
uint16_t nDecimate = 16 ;
float d16b [ 8 ] ;
float32_t sampleRate2 = 2756.25f ; // 44100/16 etc.
float gCoefficient = 1.9f ; // Goertzel algorithm coefficient
float32_t d16a [ 16 ] ; // Small data blocks, after decimation
float gs1 , gs2 ; // Goertzel algorithm state
float32_t d16b [ 16 ] ; // Reference power sum
float out1 , out2 ; // Goertzel algorithm state output
float32_t gCoefficient = 1.9f ; // Goertzel algorithm coefficient
float powerTone ;
float32_t gs1 , gs2 ; // Goertzel algorithm state
float powerRef ;
float32_t out1 , out2 ; // Goertzel algorithm state output
float32_t powerTone ;
float32_t powerRef ;
uint16_t gLength ; // number of samples to analyze
uint16_t gLength ; // number of samples to analyze
uint16_t gCount ; // how many left to analyze
uint16_t gCount ; // how many left to analyze
floa t powerSum = 0.0f ;
float32_ t powerSum = 0.0f ;
uint16_t powerSumCount = 0 ;
uint16_t powerSumCount = 0 ;
floa t threshAbs = 0.1f ; // absolute threshold, 0.01 to 0.99
float32_ t threshAbs = 0.1f ; // absolute threshold, 0.01 to 0.99
floa t threshRel = 1.0f ; // noise relative threshold
float32_ t threshRel = 1.0f ; // noise relative threshold
bool gEnabled = false ;
bool gEnabled = false ;
volatile bool new_output = false ;
volatile bool new_output = false ;
audio_block_f32_t * inputQueueArray_f32 [ 1 ] ;
audio_block_f32_t * inputQueueArray_f32 [ 1 ] ;
floa t sample_rate_Hz = AUDIO_SAMPLE_RATE ;
float32_ t sample_rate_Hz = AUDIO_SAMPLE_RATE ;
uint16_t block_size = 128 ;
uint16_t block_size = 128 ;
float iirNullsCoeffs [ 20 ] ;
float32_t iirNullsCoeffs [ 20 ] ;
float * iirBpfCoeffs ;
float32_t * iirBpfCoeffs ;
float32_t * iirUserBpfCoeffs ;
// windowCoeff needs to store half of values (symmetry) for up to
// windowCoeff needs to store half of values (symmetry) for up to
// 0.25 second at 100KHz sample rate, or 0.25*0.5*100000/16=782 pts.
// 0.25 second at 100KHz sample rate, or 0.25*0.5*100000/16=782 pts.
// This is extravagant and needs to be in caller area to allow
// This is extravagant and needs to be in caller area to allow
// frugality when there is no window at all.
// frugality when there is no window at all.
// float *windowCoeff; <<- Windowing is not currently implemented
// float32_t *windowCoeff; <<- Windowing is not currently implemented
// uint16_t nWindow = 0; <<- ditto
// uint16_t nWindow = 0; <<- ditto
/* Info - The structure from arm_biquad_casd_df1_inst_f32 instance consists of
/* Info - The structure from arm_biquad_casd_df1_inst_f32 instance consists of
* uint32_t numStages ;
* uint32_t numStages ;
@ -336,43 +370,47 @@ private:
* The state variables are updated after each block of data is processed ; the
* The state variables are updated after each block of data is processed ; the
* coefficients are untouched .
* coefficients are untouched .
*/
*/
float StateLpf32 [ 2 * 4 ] ;
float32_t StateLpf32 [ 4 * 4 ] ;
floa t StateBpf32 [ 4 * 4 ] ;
float32_ t StateBpf32 [ 4 * 4 ] ;
floa t StateNullsF32 [ 4 * 4 ] ;
float32_ t StateNullsF32 [ 4 * 4 ] ;
// The coefficients are stored in the array pCoeffs in the following order:
// {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
// where b1x and a1x are the coefficients for the first stage, b2x and a2x are
// the coefficients for the second stage, and so on. The pCoeffs array
// contains a total of 5*numStages values.
// a10, a20, etc are all 1.000 and not listed.
/*
/*
* LPF for decimation before CTCSS tone detector .
* LPF for decimation before CTCSS tone detector .
* Pick cutoff frequency to pass 254 Hz with fs = 44.1 kHz
* Pick cutoff frequency to pass 254 Hz with fs = 44.1 kHz
* or fc = 2 * 254 / 44100 = 0.01152 . This passes highest tone
* or fc = 2 * 254 / 44100 = 0.01152 . This passes highest tone
* frequency at the lowest sample rate . Octave code :
* frequency at the lowest sample rate . These
* FSample = 44100 ;
* were calculated by Iowa Hills routines .
* halfFSample = 0.5 * FSample
* [ z , p , g ] = ellip ( 4 , 0.1 , 60 , 254 / halfFSample ) ;
* sos = zp2sos ( z , p , g ) ;
* sos1 = sos ( 1 : 1 , : ) % 1 st row
* sos2 = sos ( 2 : 2 , : ) % 2 nd row
* % This puts the stop band at 0.02 * fs or for fs = 100 KHz
* % at 2 kHz . This , in turn , supports an 4 kHz
* % sampling rate after decimation . Thus a single LPF design
* % can be used for sample rates from 44.1 to 100 kHz .
* % See notes below on how to convert Octave output to coefficients :
*/
*/
float iirLpfCoeffs [ 10 ] = // See lp1ForCtcss.gif
//12000 260Hz -60 dB double elliptic 8 pole -60 dB at 300 Hz
{ 9.937058251573265e-04 f , - 1.898847656031816e-03 f , 9.937058251573265e-04 f ,
float32_t iirLpfCoeffs12 [ 20 ] = {
1.953233139252097e+00 f , - 9.540781328043288e-01 f ,
0.182145523f , - 0.359763551f , 0.182145523f , 1.888598461f , - 0.893125955f ,
1.000000000000000e+00 f , - 1.983872743032985e+00 f , 9.999999999999998e-01 f ,
0.350161286f , - 0.689819799f , 0.350161286f , 1.922991947f , - 0.933494720f ,
1.980584507653506e+00 f , - 9.822943824311938e-01 f } ;
0.293698317f , - 0.571683303f , 0.293698317f , 1.954562781f , - 0.970276113f ,
0.053599924f , - 0.089098167f , 0.053599924f , 1.973912800f , - 0.992014481f } ;
float32_t iirLpfCoeffs44 [ 20 ] = {
0.188636212f , - 0.376924253f , 0.188636212f , 1.969403901f , - 0.969752071f ,
0.357249908f , - 0.713703189f , 0.357249908f , 1.980638291f , - 0.981434917f ,
0.294316431f , - 0.587455758f , 0.294316431f , 1.990628020f , - 0.991805124f ,
0.049761875f , - 0.098177786f , 0.049761875f , 1.996468755f , - 0.997814718f } ;
/* There is a band pass filter that is used after decimation to limit the
/* There is a band pass filter that is used after decimation to limit the
* spectrum that is seen by the CTCSS detector to ( 67 , 254 ) Hz . This
* spectrum that is seen by the CTCSS detector to ( 67 , 254 ) Hz . This
* provides the entire CTCSS band to compare against to see if any other
* provides the entire CTCSS band to compare against to see if any other
* tones are present . It also restricts the amount of voice spectrum
* tones are present . It also restricts the amount of voice spectrum
* presented to the CTCSS detector . This filter is sample rate dependent
* presented to the CTCSS detector . This filter is sample rate dependent
* this routine allows for four different " built-in " rates .
* this routine allows for five different " built-in " rates .
*
*
* Sample LPF Decimation CTCSS BPF
* Sample LPF Decimation CTCSS BPF
* Rate Fco Ratio Samp Rate Name
* Rate Fco Ratio Samp Rate Name
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* 12.0 kHz 260 Hz 8 1500.0 Hz BP12
* 44.1 kHz 254 Hz 16 2756.2 Hz BP44
* 44.1 kHz 254 Hz 16 2756.2 Hz BP44
* 48.0 kHz 276 Hz 16 3000.0 Hz BP48
* 48.0 kHz 276 Hz 16 3000.0 Hz BP48
* 96.0 kHz 553 Hz 16 6000.0 Hz BP96
* 96.0 kHz 553 Hz 16 6000.0 Hz BP96
@ -381,7 +419,7 @@ private:
* The following allow computing a bandpass filter for any sample rate in
* The following allow computing a bandpass filter for any sample rate in
* the 44 to 100 kHz range ( gnu octave script ) .
* the 44 to 100 kHz range ( gnu octave script ) .
*
*
% = = = = = = = = = = = = = = = = = = = = = BPF iir Coefficients = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
% = = = = = = = = = = Sidebar : BPF iir Coefficients = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
% This GNU Octave m script will generate the BPF iir coefficients
% This GNU Octave m script will generate the BPF iir coefficients
% for other sample rates than the four listed here . It will probably
% for other sample rates than the four listed here . It will probably
% run under Matlab , but that is untested .
% run under Matlab , but that is untested .
@ -430,11 +468,19 @@ private:
% 1.797650895821358e+00 , - 8.356641238925192e-01 ,
% 1.797650895821358e+00 , - 8.356641238925192e-01 ,
% 1.000000000000000e+00 , - 1.999398698654737e+00 , 1.000000000000000e+00 ,
% 1.000000000000000e+00 , - 1.999398698654737e+00 , 1.000000000000000e+00 ,
% 1.941833848024410e+00 , - 9.614543316508065e-01 } ;
% 1.941833848024410e+00 , - 9.614543316508065e-01 } ;
%
% = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = */
*/
// The four predefined bandpass filters:
// The five predefined bandpass filters:
// BP12 Decimated fSample = 1500 sps
// 65 to 260, 0.1 dB rip, -60 dB elliptic, -7.5 dB at 300 Hz, -60 at 475
float32_t coeff32bp12 [ 20 ] = {
0.386816925f , - 0.769638284f , 0.386816925f , 1.586751090f , - 0.706113049f ,
0.265346713f , 0.247789162f , 0.265346713f , 0.996735842f , - 0.484375851f ,
0.461314461f , - 0.921736474f , 0.461314461f , 1.864126624f , - 0.928392720f ,
0.380685155f , 0.664524969f , 0.380685155f , 0.720627184f , - 0.766126702f } ;
// BP44 Decimated fSample = 2756.2 Hz
// BP44 Decimated fSample = 2756.2 Hz
float coeff32bp44 [ 20 ] = {
float32_ t coeff32bp44 [ 20 ] = {
4.386558177463118e-03 f , 4.835083945591431e-03 f , 4.386558177463117e-03 f ,
4.386558177463118e-03 f , 4.835083945591431e-03 f , 4.386558177463117e-03 f ,
1.503280453219001e+00 f , - 8.498498588788136e-01 f ,
1.503280453219001e+00 f , - 8.498498588788136e-01 f ,
1.000000000000000e+00 f , - 4.234328155653108e-01 f , 1.000000000000000e+00 f ,
1.000000000000000e+00 f , - 4.234328155653108e-01 f , 1.000000000000000e+00 f ,
@ -445,17 +491,15 @@ private:
1.941833848024410e+00 f , - 9.614543316508065e-01 f } ;
1.941833848024410e+00 f , - 9.614543316508065e-01 f } ;
// BP48 Decimated fSample = 3000 Hz
// BP48 Decimated fSample = 3000 Hz
float coeff32bp48 [ 20 ] = {
// 67 to 254 Band Pass 60 dB reject elliptic -7.5 at 300 Hz -35 at 450 Hz
3.764439090680418e-03 f , 3.650362666517592e-03 f , 3.764439090680417e-03 f ,
float32_t coeff32bp48 [ 20 ] = {
1.000000000000000e+00 f , - 5.926113222413726e-01 f , 1.000000000000000e+00 f ,
0.272147027f , - 0.543594385f , 0.272147027f , 1.819349787f , - 0.850367415f ,
1.569400123464342e+00 f , - 7.055760636246757e-01 f ,
0.226417971f , - 0.138869864f , 0.226417971f , 1.574952243f , - 0.707479581f ,
1.000000000000000e+00 f , - 1.997300534603388e+00 f , 9.999999999999998e-01 f ,
0.261002559f , - 0.521878771f , 0.261002559f , 1.949332941f , - 0.965207141f ,
1.816002936969042e+00 f , - 8.483092827984080e-01 f ,
0.232822864f , 0.221820730f , 0.232822864f , 1.572088740f , - 0.860996505 } ;
1.000000000000000e+00 f , - 1.999491318923814e+00 f , 1.000000000000000e+00 f ,
1.947984087804752e+00 f , - 9.645809301964445e-01 f } ;
// BP96 Decimated fSample = 6000 Hz
// BP96 Decimated fSample = 6000 Hz
floa t coeff32bp96 [ 20 ] = {
float32_ t coeff32bp96 [ 20 ] = {
1.554430361573611e-03 f , 5.765630035510897e-04 f , 1.554430361573611e-03 f ,
1.554430361573611e-03 f , 5.765630035510897e-04 f , 1.554430361573611e-03 f ,
1.803990601116592e+00 f , - 8.406882700444890e-01 f ,
1.803990601116592e+00 f , - 8.406882700444890e-01 f ,
1.000000000000000e+00 f , - 1.541034615722940e+00 f , 9.999999999999998e-01 f ,
1.000000000000000e+00 f , - 1.541034615722940e+00 f , 9.999999999999998e-01 f ,
@ -466,7 +510,7 @@ private:
1.978038062492293e+00 f , - 9.822341038950552e-01 f } ;
1.978038062492293e+00 f , - 9.822341038950552e-01 f } ;
// BP100 Decimated fSample = 6250 Hz
// BP100 Decimated fSample = 6250 Hz
floa t coeff32bp100 [ 20 ] = {
float32_ t coeff32bp100 [ 20 ] = {
1.504180063396739e-03 f , - 6.773089598829345e-04 f , 1.504180063396738e-03 f ,
1.504180063396739e-03 f , - 6.773089598829345e-04 f , 1.504180063396738e-03 f ,
1.812635069874353e+00 f , - 8.465624856328144e-01 f ,
1.812635069874353e+00 f , - 8.465624856328144e-01 f ,
1.000000000000000e+00 f , - 1.573630872142354e+00 f , 1.000000000000000e+00 f ,
1.000000000000000e+00 f , - 1.573630872142354e+00 f , 1.000000000000000e+00 f ,
@ -482,14 +526,14 @@ private:
* filter is always designed here and there is no need for
* filter is always designed here and there is no need for
* caller - designed filters .
* caller - designed filters .
*/
*/
void setNotchX4 ( floa t frequency )
void setNotchX4 ( float32_ t frequency )
{
{
floa t kf [ ] = { 0.9955f , 0.9982f , 1.0018f , 1.0045f } ; // Offset ratios
float32_ t kf [ ] = { 0.9955f , 0.9982f , 1.0018f , 1.0045f } ; // Offset ratios
floa t Q = 60.0f ;
float32_ t Q = 60.0f ;
floa t w0 , sinW0 , alpha , cosW0 , scale ;
float32_ t w0 , sinW0 , alpha , cosW0 , scale ;
for ( int ii = 0 ; ii < 4 ; ii + + ) // Over 4 cascaded BiQuad filters
for ( int ii = 0 ; ii < 4 ; ii + + ) // Over 4 cascaded BiQuad filters
{
{
w0 = kf [ ii ] * frequency * ( 2.0f * 3.141592654f * 16.0f / sample_rate_Hz ) ;
w0 = kf [ ii ] * frequency * ( 2.0f * 3.141592654f * nDecimate / sample_rate_Hz ) ;
sinW0 = sin ( w0 ) ;
sinW0 = sin ( w0 ) ;
alpha = sinW0 / ( Q * 2.0f ) ;
alpha = sinW0 / ( Q * 2.0f ) ;
cosW0 = cos ( w0 ) ;
cosW0 = cos ( w0 ) ;