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 #ifdef HIGHER_FS
144 extern const LVM_UINT32 LVEQNB_SampleRateTab[]; /* Sample rate table */
145 #else
146 extern const LVM_UINT16 LVEQNB_SampleRateTab[]; /* Sample rate table */
147 #endif
148
149 LVM_UINT16 i; /* Filter band index */
150 LVM_UINT32 fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate]; /* Sample rate */
151 LVM_UINT32 fc; /* Filter centre frequency */
152 LVM_INT16 QFactor; /* Filter Q factor */
153
154
155 pInstance->NBands = pParams->NBands;
156
157 for (i=0; i<pParams->NBands; i++)
158 {
159 /*
160 * Get the filter settings
161 */
162 fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency; /* Get the band centre frequency */
163 QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor; /* Get the band Q factor */
164
165 #ifdef BUILD_FLOAT
166 pInstance->pBiquadType[i] = LVEQNB_SinglePrecision_Float; /* Default to single precision */
167 #else
168 /*
169 * For each filter set the type of biquad required
170 */
171 pInstance->pBiquadType[i] = LVEQNB_SinglePrecision; /* Default to single precision */
172 #endif
173 #ifndef BUILD_FLOAT
174 if ((fc << 15) <= (LOW_FREQ * fs))
175 {
176 /*
177 * fc <= fs/110
178 */
179 pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
180 }
181 else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300))
182 {
183 /*
184 * (fs/110 < fc < fs/85) & (Q>3)
185 */
186 pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
187 }
188 #endif
189
190 /*
191 * Check for out of range frequencies
192 */
193 if (fc > (fs >> 1))
194 {
195 pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
196 }
197
198
199 /*
200 * Copy the filter definition to persistant memory
201 */
202 pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
203
204 }
205 }
206
207
208 /************************************************************************************/
209 /* */
210 /* FUNCTION: LVEQNB_SetCoefficients */
211 /* */
212 /* DESCRIPTION: */
213 /* Sets the filter coefficients. This uses the type to select single or double */
214 /* precision coefficients. */
215 /* */
216 /* PARAMETERS: */
217 /* pInstance Pointer to the instance */
218 /* pParams Initialisation parameters */
219 /* */
220 /************************************************************************************/
221
LVEQNB_SetCoefficients(LVEQNB_Instance_t * pInstance)222 void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance)
223 {
224
225 LVM_UINT16 i; /* Filter band index */
226 LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */
227
228
229 /*
230 * Set the coefficients for each band by the init function
231 */
232 for (i=0; i<pInstance->Params.NBands; i++)
233 {
234
235 /*
236 * Check band type for correct initialisation method and recalculate the coefficients
237 */
238 BiquadType = pInstance->pBiquadType[i];
239 switch (BiquadType)
240 {
241 #ifdef BUILD_FLOAT
242 case LVEQNB_SinglePrecision_Float:
243 {
244 PK_FLOAT_Coefs_t Coefficients;
245 /*
246 * Calculate the single precision coefficients
247 */
248 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
249 &pInstance->pBandDefinitions[i],
250 &Coefficients);
251 /*
252 * Set the coefficients
253 */
254 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
255 &pInstance->pEQNB_Taps_Float[i],
256 &Coefficients);
257 break;
258 }
259 #else
260 case LVEQNB_DoublePrecision:
261 {
262 PK_C32_Coefs_t Coefficients;
263
264 /*
265 * Calculate the double precision coefficients
266 */
267 LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
268 &pInstance->pBandDefinitions[i],
269 &Coefficients);
270
271 /*
272 * Set the coefficients
273 */
274 PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
275 &pInstance->pEQNB_Taps[i],
276 &Coefficients);
277 break;
278 }
279
280 case LVEQNB_SinglePrecision:
281 {
282 PK_C16_Coefs_t Coefficients;
283
284 /*
285 * Calculate the single precision coefficients
286 */
287 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
288 &pInstance->pBandDefinitions[i],
289 &Coefficients);
290
291 /*
292 * Set the coefficients
293 */
294 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
295 &pInstance->pEQNB_Taps[i],
296 &Coefficients);
297 break;
298 }
299 #endif
300 default:
301 break;
302 }
303 }
304
305 }
306
307
308 /************************************************************************************/
309 /* */
310 /* FUNCTION: LVEQNB_ClearFilterHistory */
311 /* */
312 /* DESCRIPTION: */
313 /* Clears the filter data history */
314 /* */
315 /* PARAMETERS: */
316 /* pInstance Pointer to the instance */
317 /* */
318 /************************************************************************************/
319 #ifndef BUILD_FLOAT
LVEQNB_ClearFilterHistory(LVEQNB_Instance_t * pInstance)320 void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance)
321 {
322 LVM_INT16 *pTapAddress;
323 LVM_INT16 NumTaps;
324
325
326 pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps;
327 NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16));
328
329 if (NumTaps != 0)
330 {
331 LoadConst_16(0, /* Clear the history, value 0 */
332 pTapAddress, /* Destination */
333 NumTaps); /* Number of words */
334 }
335 }
336 #else
LVEQNB_ClearFilterHistory(LVEQNB_Instance_t * pInstance)337 void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance)
338 {
339 LVM_FLOAT *pTapAddress;
340 LVM_INT16 NumTaps;
341
342 pTapAddress = (LVM_FLOAT *)pInstance->pEQNB_Taps_Float;
343 NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * \
344 sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) / sizeof(LVM_FLOAT));
345
346 if (NumTaps != 0)
347 {
348 LoadConst_Float(0, /* Clear the history, value 0 */
349 pTapAddress, /* Destination */
350 NumTaps); /* Number of words */
351 }
352 }
353 #endif
354 /****************************************************************************************/
355 /* */
356 /* FUNCTION: LVEQNB_Control */
357 /* */
358 /* DESCRIPTION: */
359 /* Sets or changes the LifeVibes module parameters. */
360 /* */
361 /* PARAMETERS: */
362 /* hInstance Instance handle */
363 /* pParams Pointer to a parameter structure */
364 /* */
365 /* RETURNS: */
366 /* LVEQNB_Success Always succeeds */
367 /* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */
368 /* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */
369 /* number of bands is non-zero */
370 /* */
371 /* NOTES: */
372 /* 1. This function may be interrupted by the LVEQNB_Process function */
373 /* */
374 /****************************************************************************************/
375
LVEQNB_Control(LVEQNB_Handle_t hInstance,LVEQNB_Params_t * pParams)376 LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance,
377 LVEQNB_Params_t *pParams)
378 {
379
380 LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance;
381 LVM_INT16 bChange = LVM_FALSE;
382 LVM_INT16 i = 0;
383 LVEQNB_Mode_en OperatingModeSave ;
384
385 /*
386 * Check for error conditions
387 */
388 if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
389 {
390 return LVEQNB_NULLADDRESS;
391 }
392
393 if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
394 {
395 return LVEQNB_NULLADDRESS;
396 }
397
398 OperatingModeSave = pInstance->Params.OperatingMode;
399
400 /* Set the alpha factor of the mixer */
401 if (pParams->SampleRate != pInstance->Params.SampleRate)
402 {
403 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
404 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
405 }
406
407
408 if( (pInstance->Params.NBands != pParams->NBands ) ||
409 (pInstance->Params.OperatingMode != pParams->OperatingMode ) ||
410 (pInstance->Params.pBandDefinition != pParams->pBandDefinition ) ||
411 (pInstance->Params.SampleRate != pParams->SampleRate ) ||
412 (pInstance->Params.SourceFormat != pParams->SourceFormat ))
413 {
414
415 bChange = LVM_TRUE;
416 }
417 else
418 {
419 for(i = 0; i < pParams->NBands; i++)
420 {
421
422 if((pInstance->pBandDefinitions[i].Frequency != pParams->pBandDefinition[i].Frequency )||
423 (pInstance->pBandDefinitions[i].Gain != pParams->pBandDefinition[i].Gain )||
424 (pInstance->pBandDefinitions[i].QFactor != pParams->pBandDefinition[i].QFactor ))
425 {
426
427 bChange = LVM_TRUE;
428 }
429 }
430 }
431
432
433 // During operating mode transition, there is a race condition where the mode
434 // is still LVEQNB_ON, but the effect is considered disabled in the upper layers.
435 // modeChange handles this special race condition.
436 const int /* bool */ modeChange = pParams->OperatingMode != OperatingModeSave
437 || (OperatingModeSave == LVEQNB_ON
438 && pInstance->bInOperatingModeTransition
439 && LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
440
441 if (bChange || modeChange) {
442
443 /*
444 * If the sample rate has changed clear the history
445 */
446 if (pInstance->Params.SampleRate != pParams->SampleRate)
447 {
448 LVEQNB_ClearFilterHistory(pInstance); /* Clear the history */
449 }
450
451 /*
452 * Update the instance parameters
453 */
454 pInstance->Params = *pParams;
455
456
457 /*
458 * Reset the filters except if the algo is switched off
459 */
460 if(pParams->OperatingMode != LVEQNB_BYPASS){
461 /*
462 * Reset the filters as all parameters could have changed
463 */
464 LVEQNB_SetFilters(pInstance, /* Instance pointer */
465 pParams); /* New parameters */
466
467 /*
468 * Update the filters
469 */
470 LVEQNB_SetCoefficients(pInstance); /* Instance pointer */
471 }
472
473 if (modeChange) {
474 if(pParams->OperatingMode == LVEQNB_ON)
475 {
476 #ifdef BUILD_FLOAT
477 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 1.0f);
478 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 0.0f);
479 #else
480 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
481 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
482 #endif
483 pInstance->BypassMixer.MixerStream[0].CallbackSet = 1;
484 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
485 }
486 else
487 {
488 /* Stay on the ON operating mode until the transition is done */
489 // This may introduce a state race condition if the effect is enabled again
490 // while in transition. This is fixed in the modeChange logic.
491 pInstance->Params.OperatingMode = LVEQNB_ON;
492 #ifdef BUILD_FLOAT
493 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 0.0f);
494 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 1.0f);
495 #else
496 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
497 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
498 #endif
499 pInstance->BypassMixer.MixerStream[0].CallbackSet = 1;
500 pInstance->BypassMixer.MixerStream[1].CallbackSet = 1;
501 }
502 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
503 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
504 pInstance->bInOperatingModeTransition = LVM_TRUE;
505 }
506
507 }
508 return(LVEQNB_SUCCESS);
509 }
510
511
512 /****************************************************************************************/
513 /* */
514 /* FUNCTION: LVEQNB_BypassMixerCallBack */
515 /* */
516 /* DESCRIPTION: */
517 /* CallBack function of the mixer */
518 /* transition */
519 /* */
520 /****************************************************************************************/
LVEQNB_BypassMixerCallBack(void * hInstance,void * pGeneralPurpose,LVM_INT16 CallbackParam)521 LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
522 void *pGeneralPurpose,
523 LVM_INT16 CallbackParam)
524 {
525 LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance;
526 LVM_Callback CallBack = pInstance->Capabilities.CallBack;
527
528 (void) pGeneralPurpose;
529
530 /*
531 * Send an ALGOFF event if the ON->OFF switch transition is finished
532 */
533 #ifdef BUILD_FLOAT
534 if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0) &&
535 (CallbackParam == 0)){
536 #else
537 if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
538 (CallbackParam == 0)){
539 #endif
540 pInstance->Params.OperatingMode = LVEQNB_BYPASS;
541 if (CallBack != LVM_NULL){
542 CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
543 }
544 }
545
546 /*
547 * Exit transition state
548 */
549 pInstance->bInOperatingModeTransition = LVM_FALSE;
550
551 return 1;
552 }
553