1 /* ----------------------------------------------------------------------
2  * Project:      CMSIS DSP Library
3  * Title:        arm_biquad_cascade_df2T_init_f32.c
4  * Description:  Initialization function for floating-point transposed direct form II Biquad cascade filter
5  *
6  * $Date:        23 April 2021
7  * $Revision:    V1.9.0
8  *
9  * Target Processor: Cortex-M and Cortex-A cores
10  * -------------------------------------------------------------------- */
11 /*
12  * Copyright (C) 2010-2021 ARM Limited or its affiliates. All rights reserved.
13  *
14  * SPDX-License-Identifier: Apache-2.0
15  *
16  * Licensed under the Apache License, Version 2.0 (the License); you may
17  * not use this file except in compliance with the License.
18  * You may obtain a copy of the License at
19  *
20  * www.apache.org/licenses/LICENSE-2.0
21  *
22  * Unless required by applicable law or agreed to in writing, software
23  * distributed under the License is distributed on an AS IS BASIS, WITHOUT
24  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25  * See the License for the specific language governing permissions and
26  * limitations under the License.
27  */
28 
29 #include "dsp/filtering_functions.h"
30 
31 /**
32   @ingroup groupFilters
33  */
34 
35 /**
36   @addtogroup BiquadCascadeDF2T
37   @{
38  */
39 
40 
41 
42 #if defined(ARM_MATH_NEON)
43 /**
44   @brief         Compute new coefficient arrays for use in vectorized filter (Neon only).
45   @param[in]     numStages         number of 2nd order stages in the filter.
46   @param[in]     pCoeffs           points to the original filter coefficients.
47   @param[in]     pComputedCoeffs   points to the new computed coefficients for the vectorized Neon version.
48 
49   @par   Size of coefficient arrays:
50             pCoeffs has size 5 * numStages
51 
52             pComputedCoeffs has size 8 * numStages
53 
54             pComputedCoeffs is the array to be used in arm_biquad_cascade_df2T_init_f32.
55 
56 */
arm_biquad_cascade_df2T_compute_coefs_f32(uint8_t numStages,const float32_t * pCoeffs,float32_t * pComputedCoeffs)57 void arm_biquad_cascade_df2T_compute_coefs_f32(
58   uint8_t numStages,
59   const float32_t * pCoeffs,
60   float32_t * pComputedCoeffs)
61 {
62    uint8_t cnt;
63    float32_t b0[4],b1[4],b2[4],a1[4],a2[4];
64 
65    cnt = numStages >> 2;
66    while(cnt > 0)
67    {
68       for(int i=0;i<4;i++)
69       {
70         b0[i] = pCoeffs[0];
71         b1[i] = pCoeffs[1];
72         b2[i] = pCoeffs[2];
73         a1[i] = pCoeffs[3];
74         a2[i] = pCoeffs[4];
75         pCoeffs += 5;
76       }
77 
78       /* Vec 1 */
79       *pComputedCoeffs++ = 0;
80       *pComputedCoeffs++ = b0[1];
81       *pComputedCoeffs++ = b0[2];
82       *pComputedCoeffs++ = b0[3];
83 
84       /* Vec 2 */
85       *pComputedCoeffs++ = 0;
86       *pComputedCoeffs++ = 0;
87       *pComputedCoeffs++ = b0[1] * b0[2];
88       *pComputedCoeffs++ = b0[2] * b0[3];
89 
90       /* Vec 3 */
91       *pComputedCoeffs++ = 0;
92       *pComputedCoeffs++ = 0;
93       *pComputedCoeffs++ = 0;
94       *pComputedCoeffs++ = b0[1] * b0[2] * b0[3];
95 
96       /* Vec 4 */
97       *pComputedCoeffs++ = b0[0];
98       *pComputedCoeffs++ = b0[0] * b0[1];
99       *pComputedCoeffs++ = b0[0] * b0[1] * b0[2];
100       *pComputedCoeffs++ = b0[0] * b0[1] * b0[2] * b0[3];
101 
102       /* Vec 5 */
103       *pComputedCoeffs++ = b1[0];
104       *pComputedCoeffs++ = b1[1];
105       *pComputedCoeffs++ = b1[2];
106       *pComputedCoeffs++ = b1[3];
107 
108       /* Vec 6 */
109       *pComputedCoeffs++ = b2[0];
110       *pComputedCoeffs++ = b2[1];
111       *pComputedCoeffs++ = b2[2];
112       *pComputedCoeffs++ = b2[3];
113 
114       /* Vec 7 */
115       *pComputedCoeffs++ = a1[0];
116       *pComputedCoeffs++ = a1[1];
117       *pComputedCoeffs++ = a1[2];
118       *pComputedCoeffs++ = a1[3];
119 
120       /* Vec 8 */
121       *pComputedCoeffs++ = a2[0];
122       *pComputedCoeffs++ = a2[1];
123       *pComputedCoeffs++ = a2[2];
124       *pComputedCoeffs++ = a2[3];
125 
126       cnt--;
127    }
128 
129    cnt = numStages & 0x3;
130    while(cnt > 0)
131    {
132       *pComputedCoeffs++ = *pCoeffs++;
133       *pComputedCoeffs++ = *pCoeffs++;
134       *pComputedCoeffs++ = *pCoeffs++;
135       *pComputedCoeffs++ = *pCoeffs++;
136       *pComputedCoeffs++ = *pCoeffs++;
137       cnt--;
138    }
139 
140 }
141 #endif
142 
143 /**
144   @brief         Initialization function for the floating-point transposed direct form II Biquad cascade filter.
145   @param[in,out] S           points to an instance of the filter data structure.
146   @param[in]     numStages   number of 2nd order stages in the filter.
147   @param[in]     pCoeffs     points to the filter coefficients.
148   @param[in]     pState      points to the state buffer.
149 
150   @par           Coefficient and State Ordering
151                    The coefficients are stored in the array <code>pCoeffs</code> in the following order
152                    in the not Neon version.
153   <pre>
154       {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
155   </pre>
156 
157   @par
158                    where <code>b1x</code> and <code>a1x</code> are the coefficients for the first stage,
159                    <code>b2x</code> and <code>a2x</code> are the coefficients for the second stage,
160                    and so on.  The <code>pCoeffs</code> array contains a total of <code>5*numStages</code> values.
161 
162                    For Neon version, this array is bigger. If numstages = 4x + y, then the array has size:
163                    32*x + 5*y
164                    and it must be initialized using the function
165                    arm_biquad_cascade_df2T_compute_coefs_f32 which is taking the
166                    standard array coefficient as parameters.
167 
168                    But, an array of 8*numstages is a good approximation.
169 
170                    Then, the initialization can be done with:
171   <pre>
172                    arm_biquad_cascade_df2T_compute_coefs_f32(nbCascade,coefs,computedCoefs);
173                    arm_biquad_cascade_df2T_init_f32(&SNeon, nbCascade, computedCoefs, stateNeon);
174   </pre>
175 
176   @par             In this example, computedCoefs is a bigger array of size 8 * numStages.
177                    coefs is the standard array:
178 
179   <pre>
180       {b10, b11, b12, a11, a12, b20, b21, b22, a21, a22, ...}
181   </pre>
182 
183 
184   @par
185                    The <code>pState</code> is a pointer to state array.
186                    Each Biquad stage has 2 state variables <code>d1,</code> and <code>d2</code>.
187                    The 2 state variables for stage 1 are first, then the 2 state variables for stage 2, and so on.
188                    The state array has a total length of <code>2*numStages</code> values.
189                    The state variables are updated after each block of data is processed; the coefficients are untouched.
190  */
arm_biquad_cascade_df2T_init_f32(arm_biquad_cascade_df2T_instance_f32 * S,uint8_t numStages,const float32_t * pCoeffs,float32_t * pState)191 void arm_biquad_cascade_df2T_init_f32(
192         arm_biquad_cascade_df2T_instance_f32 * S,
193         uint8_t numStages,
194   const float32_t * pCoeffs,
195         float32_t * pState)
196 {
197   /* Assign filter stages */
198   S->numStages = numStages;
199 
200   /* Assign coefficient pointer */
201   S->pCoeffs = pCoeffs;
202 
203   /* Clear state buffer and size is always 2 * numStages */
204   memset(pState, 0, (2U * (uint32_t) numStages) * sizeof(float32_t));
205 
206   /* Assign state pointer */
207   S->pState = pState;
208 }
209 
210 /**
211   @} end of BiquadCascadeDF2T group
212  */
213