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