/* ------------------------------------------------------------------------------------ */ /* Copyright (c) 2019 FIRMWARE DEVELOPMENTS SAS */ /* The MIT License (MIT) */ /* Permission is hereby granted, free of charge, to any person obtaining a copy of this */ /* software and associated documentation files (the "Software"), to deal in the Software*/ /* without restriction, including without limitation the rights to use, copy, modify, */ /* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to */ /* permit persons to whom the Software is furnished to do so, subject to the following */ /* conditions: */ /* The above copyright notice and this permission notice shall be included in all copies*/ /* or substantial portions of the Software. */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, */ /* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A */ /* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF */ /* CONTRACT, TORT OR OTHERWISE, ARISING FROM,OUT OF OR IN CONNECTION WITH THE SOFTWARE */ /* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /* ------------------------------------------------------------------------------------ */ /* Purpose : biquad cascaded, float32 * File: : src_biq.c * Author : Laurent Le Faucheur * Created : December 2018 * Description : * * Release : 1.0 * ------------------------------------------------------------------------------------ */ #include "fwd_vlib_types.h" /*--------------------------------------------------------------------------- * APPLICATION EXAMPLE // to avoid the double to float compilation warnings #define F float32_t // 3 biquads in cascade // [b1, a1] = ellip(2, 0.1, 20, 200 / 24000); // [b2, a2] = ellip(2, 0.3, 30, 1000 / 24000); // [b3, a3] = ellip(2, 0.5, 40, 5000 / 24000); #define NB 3 // coefficients of the biquads float32_t C1[NB*5] = { (F) 9.76447e-02,(F) -1.93087e-01,(F) 9.76447e-02,(F) 1.94077e+00,(F) -9.42994e-01, (F) 3.55404e-02,(F) -4.21041e-02,(F) 3.55404e-02,(F) 1.77461e+00,(F) -8.04608e-01, (F) 1.05939e-01,(F) 1.87734e-01,(F) 1.05939e-01,(F) 9.95603e-01,(F) -4.18895e-01, }; // biquad instance biquad_struct B1; // memory area allocated to the filter state float32_t S1[NB*4]; // input samples #define BL 64 float32_t input[BL] = { (F) 2.45396e-01,(F) 4.63777e-01,(F) 6.31103e-01,(F) 7.28953e-01,(F) 7.46556e-01, (F) 6.81973e-01,(F) 5.42314e-01,(F) 3.42954e-01,(F) 1.05840e-01,(F) -1.42926e-01, (F) -3.75958e-01,(F) -5.67602e-01,(F) -6.96761e-01,(F) -7.49216e-01,(F) -7.19193e-01, (F) -6.09997e-01,(F) -4.33649e-01,(F) -2.09562e-01,(F) 3.75953e-02,(F) 2.80613e-01, (F) 4.92740e-01,(F) 6.50623e-01,(F) 7.36881e-01,(F) 7.42019e-01,(F) 6.65471e-01, (F) 5.15663e-01,(F) 3.09089e-01,(F) 6.84879e-02,(F) -1.79653e-01,(F) -4.08016e-01, (F) -5.91462e-01,(F) -7.09797e-01,(F) -7.49993e-01,(F) -7.07625e-01,(F) -5.87357e-01, (F) -4.02430e-01,(F) -1.73200e-01,(F) 7.50960e-02,(F) 3.15125e-01,(F) 5.20464e-01, (F) 6.68506e-01,(F) 7.42956e-01,(F) 7.35616e-01,(F) 6.47295e-01,(F) 4.87716e-01, (F) 2.74446e-01,(F) 3.09636e-02,(F) -2.15927e-01,(F) -4.39048e-01,(F) -6.13835e-01, (F) -7.21048e-01,(F) -7.48883e-01,(F) -6.94277e-01,(F) -5.63240e-01,(F) -3.70199e-01, (F) -1.36404e-01,(F) 1.12408e-01,(F) 3.48845e-01,(F) 5.46879e-01,(F) 6.84709e-01, (F) 7.47162e-01,(F) 7.27363e-01,(F) 6.27492e-01,(F) 4.58542e-01, }; float32_t output[BL]; // reference output computed with float64 arithmetics in Matlab float32_t ref_output[BL]= { (F) 9.02185e-05,(F) 4.70116e-04,(F) 1.34628e-03,(F) 2.88898e-03,(F) 5.25547e-03, (F) 8.51703e-03,(F) 1.25894e-02,(F) 1.72141e-02,(F) 2.19928e-02,(F) 2.64562e-02, (F) 3.01437e-02,(F) 3.26761e-02,(F) 3.38099e-02,(F) 3.34712e-02,(F) 3.17656e-02, (F) 2.89669e-02,(F) 2.54866e-02,(F) 2.18270e-02,(F) 1.85251e-02,(F) 1.60907e-02, (F) 1.49481e-02,(F) 1.53865e-02,(F) 1.75245e-02,(F) 2.12944e-02,(F) 2.64464e-02, (F) 3.25733e-02,(F) 3.91532e-02,(F) 4.56041e-02,(F) 5.13470e-02,(F) 5.58675e-02, (F) 5.87718e-02,(F) 5.98291e-02,(F) 5.89966e-02,(F) 5.64237e-02,(F) 5.24363e-02, (F) 4.75004e-02,(F) 4.21719e-02,(F) 3.70358e-02,(F) 3.26422e-02,(F) 2.94471e-02, (F) 2.77627e-02,(F) 2.77242e-02,(F) 2.92755e-02,(F) 3.21766e-02,(F) 3.60309e-02, (F) 4.03296e-02,(F) 4.45087e-02,(F) 4.80118e-02,(F) 5.03522e-02,(F) 5.11671e-02, (F) 5.02581e-02,(F) 4.76141e-02,(F) 4.34123e-02,(F) 3.80000e-02,(F) 3.18562e-02, (F) 2.55397e-02,(F) 1.96276e-02,(F) 1.46525e-02,(F) 1.10437e-02,(F) 9.08072e-03, (F) 8.86231e-03,(F) 1.02961e-02,(F) 1.31088e-02,(F) 1.68767e-02, }; #undef F void test_biq(void) { int i; fwd_biquad_init (&B1, NB, C1, S1); // create instance // calls with various buffer lengths fwd_biquad (&B1, &input[ 0], &output[ 0], 4); // start processing 4 samples fwd_biquad (&B1, &input[ 4], &output[ 4], 8); // then 8 samples fwd_biquad (&B1, &input[12], &output[12],16); // then 16 samples fwd_biquad (&B1, &input[28], &output[28],32); // then 32 samples fwd_biquad (&B1, &input[60], &output[60], 4); // last 4 samples } * *---------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------- * FUNCTION NAME: fwd_biquad_init * * PURPOSE: Reset the filter memory, initializes the Biquad descriptor * * INPUT: Pointer to the structure * Number of Biquads in cascade * Pointer to the coefficients in the following format : * [ b0 b1 b2 -a1 -a2 b0 b1 b2 -a1 -a2 b0 b1 b2 -a1 -a2 .... ] * <--first biquad -> <--2nd biquad -> <--3rd biquad -> * b0 b1 b2 are the numerator coefficients * a0=1 is skiped and the denominator has the reversed signal * For example the following biquad ellip(2, 0.1, 20, 200 / 24000) will * result in : 0.0976 -0.1931 0.0976 +1.9408 -0.9430 * Pointer to the memory "state" of the filter. There are 4 memory cells * per biquad. The filter structure is DF1. * * OUTPUT: N/A * * RETURN VALUE none * *---------------------------------------------------------------------------*/ void fwd_biquad_init (biquad_struct * S, uint8_t numStages, float32_t * pCoeffs, float32_t * pState); /*--------------------------------------------------------------------------- * FUNCTION NAME: fwd_biquad * * PURPOSE: Filter processing * * INPUT: Pointer to the structure describing the filter instance * Pointer to the input buffer * Pointer to the output buffer (processing can be made in-place) * Number of samples to process * * OUTPUT: N/A * * RETURN VALUE none * *---------------------------------------------------------------------------*/ void fwd_biquad (const biquad_struct * S, float32_t * pSrc, float32_t * pDst, uint32_t nsamp);