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 LOW_FREQ 298 /* 32768/110 for low test frequency */
37 #define HIGH_FREQ 386 /* 32768/85 for high test frequency */
38
39 /****************************************************************************************/
40 /* */
41 /* FUNCTION: LVEQNB_GetParameters */
42 /* */
43 /* DESCRIPTION: */
44 /* Request the N-Band equaliser parameters. The current parameter set is returned via */
45 /* the parameter pointer. */
46 /* */
47 /* PARAMETERS: */
48 /* hInstance Instance handle */
49 /* pParams Pointer to an empty parameter structure */
50 /* */
51 /* RETURNS: */
52 /* LVEQNB_SUCCESS Succeeds */
53 /* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
54 /* */
55 /* NOTES: */
56 /* 1. This function may be interrupted by the LVEQNB_Process function */
57 /* */
58 /****************************************************************************************/
59
LVEQNB_GetParameters(LVEQNB_Handle_t hInstance,LVEQNB_Params_t * pParams)60 LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t hInstance,
61 LVEQNB_Params_t *pParams)
62 {
63
64 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
65
66 /*
67 * Check for error conditions
68 */
69 if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
70 {
71 return LVEQNB_NULLADDRESS;
72 }
73
74 *pParams = pInstance->Params;
75
76 return(LVEQNB_SUCCESS);
77 }
78
79
80 /************************************************************************************/
81 /* */
82 /* FUNCTION: LVEQNB_GetCapabilities */
83 /* */
84 /* DESCRIPTION: */
85 /* Get the N-Band equaliser capabilities. The current capabilities are returned */
86 /* via the pointer. */
87 /* */
88 /* PARAMETERS: */
89 /* hInstance Instance handle */
90 /* pCapabilities Pointer to an empty capability structure */
91 /* */
92 /* RETURNS: */
93 /* LVEQNB_Success Succeeds */
94 /* LVEQNB_NULLADDRESS hInstance or pCapabilities is NULL */
95 /* */
96 /* NOTES: */
97 /* 1. This function may be interrupted by the LVEQNB_Process function */
98 /* */
99 /************************************************************************************/
100
LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance,LVEQNB_Capabilities_t * pCapabilities)101 LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance,
102 LVEQNB_Capabilities_t *pCapabilities)
103 {
104
105 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
106
107 if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
108 {
109 return LVEQNB_NULLADDRESS;
110 }
111
112 *pCapabilities = pInstance->Capabilities;
113
114 return(LVEQNB_SUCCESS);
115 }
116
117
118 /************************************************************************************/
119 /* */
120 /* FUNCTION: LVEQNB_SetFilters */
121 /* */
122 /* DESCRIPTION: */
123 /* Sets the filter type based on the definition. */
124 /* */
125 /* PARAMETERS: */
126 /* pInstance Pointer to the instance */
127 /* pParams Initialisation parameters */
128 /* */
129 /* RETURNS: */
130 /* void Nothing */
131 /* */
132 /* NOTES: */
133 /* 1. To select the biquad type the follow rules are applied: */
134 /* Double precision if (fc <= fs/110) */
135 /* Double precision if (fs/110 < fc < fs/85) & (Q>3) */
136 /* Single precision otherwise */
137 /* */
138 /************************************************************************************/
139
LVEQNB_SetFilters(LVEQNB_Instance_t * pInstance,LVEQNB_Params_t * pParams)140 void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance,
141 LVEQNB_Params_t *pParams)
142 {
143
144 extern const LVM_UINT16 LVEQNB_SampleRateTab[]; /* Sample rate table */
145 LVM_UINT16 i; /* Filter band index */
146 LVM_UINT32 fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate]; /* Sample rate */
147 LVM_UINT32 fc; /* Filter centre frequency */
148 LVM_INT16 QFactor; /* Filter Q factor */
149
150
151 pInstance->NBands = pParams->NBands;
152
153 for (i=0; i<pParams->NBands; i++)
154 {
155 /*
156 * Get the filter settings
157 */
158 fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency; /* Get the band centre frequency */
159 QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor; /* Get the band Q factor */
160
161
162 /*
163 * For each filter set the type of biquad required
164 */
165 pInstance->pBiquadType[i] = LVEQNB_SinglePrecision; /* Default to single precision */
166 if ((fc << 15) <= (LOW_FREQ * fs))
167 {
168 /*
169 * fc <= fs/110
170 */
171 pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
172 }
173 else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300))
174 {
175 /*
176 * (fs/110 < fc < fs/85) & (Q>3)
177 */
178 pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
179 }
180
181
182 /*
183 * Check for out of range frequencies
184 */
185 if (fc > (fs >> 1))
186 {
187 pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
188 }
189
190
191 /*
192 * Copy the filter definition to persistant memory
193 */
194 pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
195
196 }
197 }
198
199
200 /************************************************************************************/
201 /* */
202 /* FUNCTION: LVEQNB_SetCoefficients */
203 /* */
204 /* DESCRIPTION: */
205 /* Sets the filter coefficients. This uses the type to select single or double */
206 /* precision coefficients. */
207 /* */
208 /* PARAMETERS: */
209 /* pInstance Pointer to the instance */
210 /* pParams Initialisation parameters */
211 /* */
212 /************************************************************************************/
213
LVEQNB_SetCoefficients(LVEQNB_Instance_t * pInstance)214 void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance)
215 {
216
217 LVM_UINT16 i; /* Filter band index */
218 LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
219
220
221 /*
222 * Set the coefficients for each band by the init function
223 */
224 for (i=0; i<pInstance->Params.NBands; i++)
225 {
226
227 /*
228 * Check band type for correct initialisation method and recalculate the coefficients
229 */
230 BiquadType = pInstance->pBiquadType[i];
231 switch (BiquadType)
232 {
233 case LVEQNB_DoublePrecision:
234 {
235 PK_C32_Coefs_t Coefficients;
236
237 /*
238 * Calculate the double precision coefficients
239 */
240 LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
241 &pInstance->pBandDefinitions[i],
242 &Coefficients);
243
244 /*
245 * Set the coefficients
246 */
247 PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
248 &pInstance->pEQNB_Taps[i],
249 &Coefficients);
250 break;
251 }
252
253 case LVEQNB_SinglePrecision:
254 {
255 PK_C16_Coefs_t Coefficients;
256
257 /*
258 * Calculate the single precision coefficients
259 */
260 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
261 &pInstance->pBandDefinitions[i],
262 &Coefficients);
263
264 /*
265 * Set the coefficients
266 */
267 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
268 &pInstance->pEQNB_Taps[i],
269 &Coefficients);
270 break;
271 }
272 default:
273 break;
274 }
275 }
276
277 }
278
279
280 /************************************************************************************/
281 /* */
282 /* FUNCTION: LVEQNB_ClearFilterHistory */
283 /* */
284 /* DESCRIPTION: */
285 /* Clears the filter data history */
286 /* */
287 /* PARAMETERS: */
288 /* pInstance Pointer to the instance */
289 /* */
290 /************************************************************************************/
291
LVEQNB_ClearFilterHistory(LVEQNB_Instance_t * pInstance)292 void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance)
293 {
294 LVM_INT16 *pTapAddress;
295 LVM_INT16 NumTaps;
296
297
298 pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps;
299 NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16));
300
301 if (NumTaps != 0)
302 {
303 LoadConst_16(0, /* Clear the history, value 0 */
304 pTapAddress, /* Destination */
305 NumTaps); /* Number of words */
306 }
307 }
308
309
310 /****************************************************************************************/
311 /* */
312 /* FUNCTION: LVEQNB_Control */
313 /* */
314 /* DESCRIPTION: */
315 /* Sets or changes the LifeVibes module parameters. */
316 /* */
317 /* PARAMETERS: */
318 /* hInstance Instance handle */
319 /* pParams Pointer to a parameter structure */
320 /* */
321 /* RETURNS: */
322 /* LVEQNB_Success Always succeeds */
323 /* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
324 /* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */
325 /* number of bands is non-zero */
326 /* */
327 /* NOTES: */
328 /* 1. This function may be interrupted by the LVEQNB_Process function */
329 /* */
330 /****************************************************************************************/
331
LVEQNB_Control(LVEQNB_Handle_t hInstance,LVEQNB_Params_t * pParams)332 LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance,
333 LVEQNB_Params_t *pParams)
334 {
335
336 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
337 LVM_INT16 bChange = LVM_FALSE;
338 LVM_INT16 i = 0;
339 LVEQNB_Mode_en OperatingModeSave ;
340
341 /*
342 * Check for error conditions
343 */
344 if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
345 {
346 return LVEQNB_NULLADDRESS;
347 }
348
349 if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
350 {
351 return LVEQNB_NULLADDRESS;
352 }
353
354 OperatingModeSave = pInstance->Params.OperatingMode;
355
356 /* Set the alpha factor of the mixer */
357 if (pParams->SampleRate != pInstance->Params.SampleRate)
358 {
359 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
360 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
361 }
362
363
364 if( (pInstance->Params.NBands != pParams->NBands ) ||
365 (pInstance->Params.OperatingMode != pParams->OperatingMode ) ||
366 (pInstance->Params.pBandDefinition != pParams->pBandDefinition ) ||
367 (pInstance->Params.SampleRate != pParams->SampleRate ) ||
368 (pInstance->Params.SourceFormat != pParams->SourceFormat ))
369 {
370
371 bChange = LVM_TRUE;
372 }
373 else
374 {
375 for(i = 0; i < pParams->NBands; i++)
376 {
377
378 if((pInstance->pBandDefinitions[i].Frequency != pParams->pBandDefinition[i].Frequency )||
379 (pInstance->pBandDefinitions[i].Gain != pParams->pBandDefinition[i].Gain )||
380 (pInstance->pBandDefinitions[i].QFactor != pParams->pBandDefinition[i].QFactor ))
381 {
382
383 bChange = LVM_TRUE;
384 }
385 }
386 }
387
388
389 if(bChange){
390
391 /*
392 * If the sample rate has changed clear the history
393 */
394 if (pInstance->Params.SampleRate != pParams->SampleRate)
395 {
396 LVEQNB_ClearFilterHistory(pInstance); /* Clear the history */
397 }
398
399 /*
400 * Update the instance parameters
401 */
402 pInstance->Params = *pParams;
403
404
405 /*
406 * Reset the filters except if the algo is switched off
407 */
408 if(pParams->OperatingMode != LVEQNB_BYPASS){
409 /*
410 * Reset the filters as all parameters could have changed
411 */
412 LVEQNB_SetFilters(pInstance, /* Instance pointer */
413 pParams); /* New parameters */
414
415 /*
416 * Update the filters
417 */
418 LVEQNB_SetCoefficients(pInstance); /* Instance pointer */
419 }
420
421 if(pParams->OperatingMode != OperatingModeSave)
422 {
423 if(pParams->OperatingMode == LVEQNB_ON)
424 {
425 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
426 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
427
428 pInstance->BypassMixer.MixerStream[0].CallbackSet = 1;
429 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
430 }
431 else
432 {
433 /* Stay on the ON operating mode until the transition is done */
434 pInstance->Params.OperatingMode = LVEQNB_ON;
435
436 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
437 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
438 pInstance->BypassMixer.MixerStream[0].CallbackSet = 1;
439 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
440 }
441 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
442 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
443
444 pInstance->bInOperatingModeTransition = LVM_TRUE;
445 }
446
447 }
448 return(LVEQNB_SUCCESS);
449 }
450
451
452 /****************************************************************************************/
453 /* */
454 /* FUNCTION: LVEQNB_BypassMixerCallBack */
455 /* */
456 /* DESCRIPTION: */
457 /* CallBack function of the mixer */
458 /* transition */
459 /* */
460 /****************************************************************************************/
LVEQNB_BypassMixerCallBack(void * hInstance,void * pGeneralPurpose,LVM_INT16 CallbackParam)461 LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
462 void *pGeneralPurpose,
463 LVM_INT16 CallbackParam)
464 {
465 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
466 LVM_Callback CallBack = pInstance->Capabilities.CallBack;
467
468 (void) pGeneralPurpose;
469
470 /*
471 * Send an ALGOFF event if the ON->OFF switch transition is finished
472 */
473 if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
474 (CallbackParam == 0)){
475 pInstance->Params.OperatingMode = LVEQNB_BYPASS;
476 if (CallBack != LVM_NULL){
477 CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
478 }
479 }
480
481 /*
482 * Exit transition state
483 */
484 pInstance->bInOperatingModeTransition = LVM_FALSE;
485
486 return 1;
487 }
488
489
490
491
492
493
494