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 #include <log/log.h>
30
31 /****************************************************************************************/
32 /* */
33 /* Defines */
34 /* */
35 /****************************************************************************************/
36
37 #define SHIFT 13
38
39 /****************************************************************************************/
40 /* */
41 /* FUNCTION: LVEQNB_Process */
42 /* */
43 /* DESCRIPTION: */
44 /* Process function for the N-Band Equaliser module. */
45 /* */
46 /* PARAMETERS: */
47 /* hInstance Instance handle */
48 /* pInData Pointer to the input data */
49 /* pOutData Pointer to the output data */
50 /* NumSamples Number of samples in the input buffer */
51 /* */
52 /* RETURNS: */
53 /* LVEQNB_SUCCESS Succeeded */
54 /* LVEQNB_NULLADDRESS When hInstance, pInData or pOutData are NULL */
55 /* LVEQNB_ALIGNMENTERROR When pInData or pOutData are not 32-bit aligned */
56 /* LVEQNB_TOOMANYSAMPLES NumSamples was larger than the maximum block size */
57 /* */
58 /* NOTES: */
59 /* */
60 /****************************************************************************************/
61 #ifdef BUILD_FLOAT
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_FLOAT * pInData,LVM_FLOAT * pOutData,const LVM_UINT16 NrFrames)62 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
63 const LVM_FLOAT *pInData,
64 LVM_FLOAT *pOutData,
65 const LVM_UINT16 NrFrames)
66 { // updated to use samples = frames * channels.
67 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
68
69 #ifdef SUPPORT_MC
70 // Mono passed in as stereo
71 const LVM_INT32 NrChannels = pInstance->Params.NrChannels == 1
72 ? 2 : pInstance->Params.NrChannels;
73 #else
74 const LVM_INT32 NrChannels = 2; // FCC_2
75 #endif
76 const LVM_INT32 NrSamples = NrChannels * NrFrames;
77
78 /* Check for NULL pointers */
79 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
80 {
81 return LVEQNB_NULLADDRESS;
82 }
83
84 /* Check if the input and output data buffers are 32-bit aligned */
85 if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
86 {
87 return LVEQNB_ALIGNMENTERROR;
88 }
89
90 LVM_FLOAT * const pScratch = (LVM_FLOAT *)pInstance->pFastTemporary;
91
92 /*
93 * Check the number of frames is not too large
94 */
95 if (NrFrames > pInstance->Capabilities.MaxBlockSize)
96 {
97 return LVEQNB_TOOMANYSAMPLES;
98 }
99
100 if (pInstance->Params.OperatingMode == LVEQNB_ON)
101 {
102 /*
103 * Copy input data in to scratch buffer
104 */
105 Copy_Float(pInData, /* Source */
106 pScratch, /* Destination */
107 (LVM_INT16)NrSamples);
108
109 /*
110 * For each section execte the filter unless the gain is 0dB
111 */
112 if (pInstance->NBands != 0)
113 {
114 for (LVM_UINT16 i = 0; i < pInstance->NBands; i++)
115 {
116 /*
117 * Check if band is non-zero dB gain
118 */
119 if (pInstance->pBandDefinitions[i].Gain != 0)
120 {
121 /*
122 * Get the address of the biquad instance
123 */
124 Biquad_FLOAT_Instance_t *pBiquad = &pInstance->pEQNB_FilterState_Float[i];
125
126
127 /*
128 * Select single or double precision as required
129 */
130 switch (pInstance->pBiquadType[i])
131 {
132 case LVEQNB_SinglePrecision_Float:
133 {
134 #ifdef SUPPORT_MC
135 PK_Mc_D32F32C14G11_TRC_WRA_01(pBiquad,
136 pScratch,
137 pScratch,
138 (LVM_INT16)NrFrames,
139 (LVM_INT16)NrChannels);
140 #else
141 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
142 pScratch,
143 pScratch,
144 (LVM_INT16)NrFrames);
145 #endif
146 break;
147 }
148 default:
149 break;
150 }
151 }
152 }
153 }
154
155
156 if(pInstance->bInOperatingModeTransition == LVM_TRUE){
157 #ifdef SUPPORT_MC
158 LVC_MixSoft_2Mc_D16C31_SAT(&pInstance->BypassMixer,
159 pScratch,
160 pInData,
161 pScratch,
162 (LVM_INT16)NrFrames,
163 (LVM_INT16)NrChannels);
164 #else
165 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
166 pScratch,
167 pInData,
168 pScratch,
169 (LVM_INT16)NrSamples);
170 #endif
171 // duplicate with else clause(s)
172 Copy_Float(pScratch, /* Source */
173 pOutData, /* Destination */
174 (LVM_INT16)NrSamples); /* All channel samples */
175 }
176 else{
177 Copy_Float(pScratch, /* Source */
178 pOutData, /* Destination */
179 (LVM_INT16)NrSamples); /* All channel samples */
180 }
181 }
182 else
183 {
184 /*
185 * Mode is OFF so copy the data if necessary
186 */
187 if (pInData != pOutData)
188 {
189 Copy_Float(pInData, /* Source */
190 pOutData, /* Destination */
191 (LVM_INT16)NrSamples); /* All channel samples */
192 }
193 }
194 return LVEQNB_SUCCESS;
195
196 }
197 #else
LVEQNB_Process(LVEQNB_Handle_t hInstance,const LVM_INT16 * pInData,LVM_INT16 * pOutData,LVM_UINT16 NumSamples)198 LVEQNB_ReturnStatus_en LVEQNB_Process(LVEQNB_Handle_t hInstance,
199 const LVM_INT16 *pInData,
200 LVM_INT16 *pOutData,
201 LVM_UINT16 NumSamples)
202 {
203
204 LVM_UINT16 i;
205 Biquad_Instance_t *pBiquad;
206 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
207 LVM_INT32 *pScratch;
208
209
210 /* Check for NULL pointers */
211 if((hInstance == LVM_NULL) || (pInData == LVM_NULL) || (pOutData == LVM_NULL))
212 {
213 return LVEQNB_NULLADDRESS;
214 }
215
216 /* Check if the input and output data buffers are 32-bit aligned */
217 if ((((uintptr_t)pInData % 4) != 0) || (((uintptr_t)pOutData % 4) != 0))
218 {
219 return LVEQNB_ALIGNMENTERROR;
220 }
221
222 pScratch = (LVM_INT32 *)pInstance->pFastTemporary;
223
224 /*
225 * Check the number of samples is not too large
226 */
227 if (NumSamples > pInstance->Capabilities.MaxBlockSize)
228 {
229 return(LVEQNB_TOOMANYSAMPLES);
230 }
231
232 if (pInstance->Params.OperatingMode == LVEQNB_ON)
233 {
234 /*
235 * Convert from 16-bit to 32-bit
236 */
237 Int16LShiftToInt32_16x32((LVM_INT16 *)pInData, /* Source */
238 pScratch, /* Destination */
239 (LVM_INT16)(2*NumSamples), /* Left and Right */
240 SHIFT); /* Scaling shift */
241
242 /*
243 * For each section execte the filter unless the gain is 0dB
244 */
245 if (pInstance->NBands != 0)
246 {
247 for (i=0; i<pInstance->NBands; i++)
248 {
249 /*
250 * Check if band is non-zero dB gain
251 */
252 if (pInstance->pBandDefinitions[i].Gain != 0)
253 {
254 /*
255 * Get the address of the biquad instance
256 */
257 pBiquad = &pInstance->pEQNB_FilterState[i];
258
259
260 /*
261 * Select single or double precision as required
262 */
263 switch (pInstance->pBiquadType[i])
264 {
265 case LVEQNB_SinglePrecision:
266 {
267 PK_2I_D32F32C14G11_TRC_WRA_01(pBiquad,
268 (LVM_INT32 *)pScratch,
269 (LVM_INT32 *)pScratch,
270 (LVM_INT16)NumSamples);
271 break;
272 }
273
274 case LVEQNB_DoublePrecision:
275 {
276 PK_2I_D32F32C30G11_TRC_WRA_01(pBiquad,
277 (LVM_INT32 *)pScratch,
278 (LVM_INT32 *)pScratch,
279 (LVM_INT16)NumSamples);
280 break;
281 }
282 default:
283 break;
284 }
285 }
286 }
287 }
288
289
290 if(pInstance->bInOperatingModeTransition == LVM_TRUE){
291 /*
292 * Convert from 32-bit to 16- bit and saturate
293 */
294 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
295 (LVM_INT16 *)pScratch, /* Destination */
296 (LVM_INT16)(2*NumSamples), /* Left and Right */
297 SHIFT); /* Scaling shift */
298
299 LVC_MixSoft_2St_D16C31_SAT(&pInstance->BypassMixer,
300 (LVM_INT16 *)pScratch,
301 (LVM_INT16 *)pInData,
302 (LVM_INT16 *)pScratch,
303 (LVM_INT16)(2*NumSamples));
304
305 Copy_16((LVM_INT16*)pScratch, /* Source */
306 pOutData, /* Destination */
307 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
308 }
309 else{
310
311 /*
312 * Convert from 32-bit to 16- bit and saturate
313 */
314 Int32RShiftToInt16_Sat_32x16(pScratch, /* Source */
315 pOutData, /* Destination */
316 (LVM_INT16 )(2*NumSamples), /* Left and Right */
317 SHIFT); /* Scaling shift */
318 }
319 }
320 else
321 {
322 /*
323 * Mode is OFF so copy the data if necessary
324 */
325 if (pInData != pOutData)
326 {
327 Copy_16(pInData, /* Source */
328 pOutData, /* Destination */
329 (LVM_INT16)(2*NumSamples)); /* Left and Right samples */
330 }
331 }
332
333
334
335 return(LVEQNB_SUCCESS);
336
337 }
338 #endif
339