1 /*
2 * Copyright (C) 2004-2010 NXP Software
3 * Copyright (C) 2010 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /****************************************************************************************/
19 /* */
20 /* Includes */
21 /* */
22 /****************************************************************************************/
23
24 #include "LVEQNB.h"
25 #include "LVEQNB_Private.h"
26 #include "VectorArithmetic.h"
27 #include "BIQUAD.h"
28
29
30 /****************************************************************************************/
31 /* */
32 /* Defines */
33 /* */
34 /****************************************************************************************/
35
36 #define SHIFT 13
37
38 /****************************************************************************************/
39 /* */
40 /* FUNCTION: LVEQNB_Process */
41 /* */
42 /* DESCRIPTION: */
43 /* Process function for the N-Band Equaliser module. */
44 /* */
45 /* PARAMETERS: */
46 /* hInstance Instance handle */
47 /* pInData Pointer to the input data */
48 /* pOutData Pointer to the output data */
49 /* NumSamples Number of samples in the input buffer */
50 /* */
51 /* RETURNS: */
52 /* LVEQNB_SUCCESS Succeeded */
53 /* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */
54 /* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */
55 /* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
56 /* */
57 /* NOTES: */
58 /* */
59 /****************************************************************************************/
60 #ifdef BUILD_FLOAT
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,LVM_UINT16 NumSamples)61 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
62 const LVM_FLOAT *pInData,
63 LVM_FLOAT *pOutData,
64 LVM_UINT16 NumSamples)
65 {
66
67 LVM_UINT16 i;
68 Biquad_FLOAT_Instance_t *pBiquad;
69 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
70 LVM_FLOAT *pScratch;
71
72
73 /* Check for NULL pointers */
74 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
75 {
76 return LVEQNB_NULLADDRESS;
77 }
78
79 /* Check if the input and output data buffers are 32-bit aligned */
80 if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
81 {
82 return LVEQNB_ALIGNMENTERROR;
83 }
84
85 pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
86
87 /*
88 * Check the number of samples is not too large
89 */
90 if (NumSamples > pInstance->Capabilities.MaxBlockSize)
91 {
92 return(LVEQNB_TOOMANYSAMPLES);
93 }
94
95 if (pInstance->Params.OperatingMode == LVEQNB_ON)
96 {
97 /*
98 * Copy input data in to scratch buffer
99 */
100
101 Copy_Float((LVM_FLOAT *)pInData, /* Source */
102 pScratch, /* Destination */
103 (LVM_INT16)(2 * NumSamples)); /* Left and Right */
104 /*
105 * For each section execte the filter unless the gain is 0dB
106 */
107 if (pInstance->NBands != 0)
108 {
109 for (i = 0; i < pInstance->NBands; i++)
110 {
111 /*
112 * Check if band is non-zero dB gain
113 */
114 if (pInstance->pBandDefinitions[i].Gain != 0)
115 {
116 /*
117 * Get the address of the biquad instance
118 */
119 pBiquad = &pInstance->pEQNB_FilterState_Float[i];
120
121
122 /*
123 * Select single or double precision as required
124 */
125 switch (pInstance->pBiquadType[i])
126 {
127 case LVEQNB_SinglePrecision_Float:
128 {
129 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
130 (LVM_FLOAT *)pScratch,
131 (LVM_FLOAT *)pScratch,
132 (LVM_INT16)NumSamples);
133 break;
134 }
135 default:
136 break;
137 }
138 }
139 }
140 }
141
142
143 if(pInstance->bInOperatingModeTransition == LVM_TRUE){
144 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
145 (LVM_FLOAT *)pScratch,
146 (LVM_FLOAT *)pInData,
147 (LVM_FLOAT *)pScratch,
148 (LVM_INT16)(2 * NumSamples));
149 Copy_Float((LVM_FLOAT*)pScratch, /* Source */
150 pOutData, /* Destination */
151 (LVM_INT16)(2 * NumSamples)); /* Left and Right samples */
152 }
153 else{
154 Copy_Float(pScratch, /* Source */
155 pOutData, /* Destination */
156 (LVM_INT16 )(2 * NumSamples)); /* Left and Right */
157 }
158 }
159 else
160 {
161 /*
162 * Mode is OFF so copy the data if necessary
163 */
164 if (pInData != pOutData)
165 {
166 Copy_Float(pInData, /* Source */
167 pOutData, /* Destination */
168 (LVM_INT16)(2 * NumSamples)); /* Left and Right samples */
169 }
170 }
171 return(LVEQNB_SUCCESS);
172
173 }
174 #else
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 * pOutData,LVM_UINT16 NumSamples)175 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
176 const LVM_INT16 *pInData,
177 LVM_INT16 *pOutData,
178 LVM_UINT16 NumSamples)
179 {
180
181 LVM_UINT16 i;
182 Biquad_Instance_t *pBiquad;
183 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
184 LVM_INT32 *pScratch;
185
186
187 /* Check for NULL pointers */
188 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
189 {
190 return LVEQNB_NULLADDRESS;
191 }
192
193 /* Check if the input and output data buffers are 32-bit aligned */
194 if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
195 {
196 return LVEQNB_ALIGNMENTERROR;
197 }
198
199 pScratch = (LVM_INT32 *)pInstance->pFastTemporary;
200
201 /*
202 * Check the number of samples is not too large
203 */
204 if (NumSamples > pInstance->Capabilities.MaxBlockSize)
205 {
206 return(LVEQNB_TOOMANYSAMPLES);
207 }
208
209 if (pInstance->Params.OperatingMode == LVEQNB_ON)
210 {
211 /*
212 * Convert from 16-bit to 32-bit
213 */
214 Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */
215 pScratch, /* Destination */
216 (LVM_INT16)(2*NumSamples), /* Left and Right */
217 SHIFT); /* Scaling shift */
218
219 /*
220 * For each section execte the filter unless the gain is 0dB
221 */
222 if (pInstance->NBands != 0)
223 {
224 for (i=0; i<pInstance->NBands; i++)
225 {
226 /*
227 * Check if band is non-zero dB gain
228 */
229 if (pInstance->pBandDefinitions[i].Gain != 0)
230 {
231 /*
232 * Get the address of the biquad instance
233 */
234 pBiquad = &pInstance->pEQNB_FilterState[i];
235
236
237 /*
238 * Select single or double precision as required
239 */
240 switch (pInstance->pBiquadType[i])
241 {
242 case LVEQNB_SinglePrecision:
243 {
244 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
245 (LVM_INT32 *)pScratch,
246 (LVM_INT32 *)pScratch,
247 (LVM_INT16)NumSamples);
248 break;
249 }
250
251 case LVEQNB_DoublePrecision:
252 {
253 PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
254 (LVM_INT32 *)pScratch,
255 (LVM_INT32 *)pScratch,
256 (LVM_INT16)NumSamples);
257 break;
258 }
259 default:
260 break;
261 }
262 }
263 }
264 }
265
266
267 if(pInstance->bInOperatingModeTransition == LVM_TRUE){
268 /*
269 * Convert from 32-bit to 16- bit and saturate
270 */
271 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
272 (LVM_INT16 *)pScratch, /* Destination */
273 (LVM_INT16)(2*NumSamples), /* Left and Right */
274 SHIFT); /* Scaling shift */
275
276 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
277 (LVM_INT16 *)pScratch,
278 (LVM_INT16 *)pInData,
279 (LVM_INT16 *)pScratch,
280 (LVM_INT16)(2*NumSamples));
281
282 Copy_16((LVM_INT16*)pScratch, /* Source */
283 pOutData, /* Destination */
284 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
285 }
286 else{
287
288 /*
289 * Convert from 32-bit to 16- bit and saturate
290 */
291 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
292 pOutData, /* Destination */
293 (LVM_INT16 )(2*NumSamples), /* Left and Right */
294 SHIFT); /* Scaling shift */
295 }
296 }
297 else
298 {
299 /*
300 * Mode is OFF so copy the data if necessary
301 */
302 if (pInData != pOutData)
303 {
304 Copy_16(pInData, /* Source */
305 pOutData, /* Destination */
306 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
307 }
308 }
309
310
311
312 return(LVEQNB_SUCCESS);
313
314 }
315 #endif