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 /* */
21 /* Includes */
22 /* */
23 /****************************************************************************************/
24
25 #include "VectorArithmetic.h"
26 #include "ScalarArithmetic.h"
27 #include "LVM_Coeffs.h"
28 #include "LVM_Tables.h"
29 #include "LVM_Private.h"
30
31 #include <log/log.h>
32
33 /****************************************************************************************/
34 /* */
35 /* FUNCTION: LVM_SetControlParameters */
36 /* */
37 /* DESCRIPTION: */
38 /* Sets or changes the LifeVibes module parameters. */
39 /* */
40 /* PARAMETERS: */
41 /* hInstance Instance handle */
42 /* pParams Pointer to a parameter structure */
43 /* */
44 /* RETURNS: */
45 /* LVM_SUCCESS Succeeded */
46 /* LVM_NULLADDRESS When hInstance, pParams or any control pointers are NULL */
47 /* LVM_OUTOFRANGE When any of the control parameters are out of range */
48 /* */
49 /* NOTES: */
50 /* 1. This function may be interrupted by the LVM_Process function */
51 /* */
52 /****************************************************************************************/
53
LVM_SetControlParameters(LVM_Handle_t hInstance,LVM_ControlParams_t * pParams)54 LVM_ReturnStatus_en LVM_SetControlParameters(LVM_Handle_t hInstance,
55 LVM_ControlParams_t *pParams)
56 {
57 LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
58
59
60 if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
61 {
62 return (LVM_NULLADDRESS);
63 }
64
65 pInstance->NewParams = *pParams;
66
67 if(
68 /* General parameters */
69 ((pParams->OperatingMode != LVM_MODE_OFF) && (pParams->OperatingMode != LVM_MODE_ON)) ||
70 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
71 ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000) &&
72 (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000) &&
73 (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000) &&
74 (pParams->SampleRate != LVM_FS_88200) && (pParams->SampleRate != LVM_FS_96000) &&
75 (pParams->SampleRate != LVM_FS_176400) && (pParams->SampleRate != LVM_FS_192000)) ||
76 #else
77 ((pParams->SampleRate != LVM_FS_8000) && (pParams->SampleRate != LVM_FS_11025) && (pParams->SampleRate != LVM_FS_12000) &&
78 (pParams->SampleRate != LVM_FS_16000) && (pParams->SampleRate != LVM_FS_22050) && (pParams->SampleRate != LVM_FS_24000) &&
79 (pParams->SampleRate != LVM_FS_32000) && (pParams->SampleRate != LVM_FS_44100) && (pParams->SampleRate != LVM_FS_48000)) ||
80 #endif
81 #ifdef SUPPORT_MC
82 ((pParams->SourceFormat != LVM_STEREO) &&
83 (pParams->SourceFormat != LVM_MONOINSTEREO) &&
84 (pParams->SourceFormat != LVM_MONO) &&
85 (pParams->SourceFormat != LVM_MULTICHANNEL)) ||
86 #else
87 ((pParams->SourceFormat != LVM_STEREO) && (pParams->SourceFormat != LVM_MONOINSTEREO) && (pParams->SourceFormat != LVM_MONO)) ||
88 #endif
89 (pParams->SpeakerType > LVM_EX_HEADPHONES))
90 {
91 return (LVM_OUTOFRANGE);
92 }
93
94 #ifdef SUPPORT_MC
95 pInstance->Params.NrChannels = pParams->NrChannels;
96 pInstance->Params.ChMask = pParams->ChMask;
97 #endif
98 /*
99 * Cinema Sound parameters
100 */
101 if((pParams->VirtualizerOperatingMode != LVM_MODE_OFF) && (pParams->VirtualizerOperatingMode != LVM_MODE_ON))
102 {
103 return (LVM_OUTOFRANGE);
104 }
105
106 if(pParams->VirtualizerType != LVM_CONCERTSOUND)
107 {
108 return (LVM_OUTOFRANGE);
109 }
110
111 if(pParams->VirtualizerReverbLevel > LVM_VIRTUALIZER_MAX_REVERB_LEVEL)
112 {
113 return (LVM_OUTOFRANGE);
114 }
115
116 if(pParams->CS_EffectLevel < LVM_CS_MIN_EFFECT_LEVEL)
117 {
118 return (LVM_OUTOFRANGE);
119 }
120
121 /*
122 * N-Band Equalizer
123 */
124 if(pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands)
125 {
126 return (LVM_OUTOFRANGE);
127 }
128
129 /* Definition pointer */
130 if ((pParams->pEQNB_BandDefinition == LVM_NULL) &&
131 (pParams->EQNB_NBands != 0))
132 {
133 return (LVM_NULLADDRESS);
134 }
135
136 /*
137 * Copy the filter definitions for the Equaliser
138 */
139 {
140 LVM_INT16 i;
141
142 if (pParams->EQNB_NBands != 0)
143 {
144 for (i=0; i<pParams->EQNB_NBands; i++)
145 {
146 pInstance->pEQNB_BandDefs[i] = pParams->pEQNB_BandDefinition[i];
147 }
148 pInstance->NewParams.pEQNB_BandDefinition = pInstance->pEQNB_BandDefs;
149 }
150 }
151 if( /* N-Band Equaliser parameters */
152 ((pParams->EQNB_OperatingMode != LVM_EQNB_OFF) && (pParams->EQNB_OperatingMode != LVM_EQNB_ON)) ||
153 (pParams->EQNB_NBands > pInstance->InstParams.EQNB_NumBands))
154 {
155 return (LVM_OUTOFRANGE);
156 }
157 /* Band parameters*/
158 {
159 LVM_INT16 i;
160 for(i = 0; i < pParams->EQNB_NBands; i++)
161 {
162 if(((pParams->pEQNB_BandDefinition[i].Frequency < LVM_EQNB_MIN_BAND_FREQ) ||
163 (pParams->pEQNB_BandDefinition[i].Frequency > LVM_EQNB_MAX_BAND_FREQ)) ||
164 ((pParams->pEQNB_BandDefinition[i].Gain < LVM_EQNB_MIN_BAND_GAIN) ||
165 (pParams->pEQNB_BandDefinition[i].Gain > LVM_EQNB_MAX_BAND_GAIN)) ||
166 ((pParams->pEQNB_BandDefinition[i].QFactor < LVM_EQNB_MIN_QFACTOR) ||
167 (pParams->pEQNB_BandDefinition[i].QFactor > LVM_EQNB_MAX_QFACTOR)))
168 {
169 return (LVM_OUTOFRANGE);
170 }
171 }
172 }
173
174 /*
175 * Bass Enhancement parameters
176 */
177 if(((pParams->BE_OperatingMode != LVM_BE_OFF) && (pParams->BE_OperatingMode != LVM_BE_ON)) ||
178 ((pParams->BE_EffectLevel < LVM_BE_MIN_EFFECTLEVEL ) || (pParams->BE_EffectLevel > LVM_BE_MAX_EFFECTLEVEL ))||
179 ((pParams->BE_CentreFreq != LVM_BE_CENTRE_55Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_66Hz) &&
180 (pParams->BE_CentreFreq != LVM_BE_CENTRE_78Hz) && (pParams->BE_CentreFreq != LVM_BE_CENTRE_90Hz)) ||
181 ((pParams->BE_HPF != LVM_BE_HPF_OFF) && (pParams->BE_HPF != LVM_BE_HPF_ON)))
182 {
183 return (LVM_OUTOFRANGE);
184 }
185
186 /*
187 * Volume Control parameters
188 */
189 if((pParams->VC_EffectLevel < LVM_VC_MIN_EFFECTLEVEL ) || (pParams->VC_EffectLevel > LVM_VC_MAX_EFFECTLEVEL ))
190 {
191 return (LVM_OUTOFRANGE);
192 }
193 if((pParams->VC_Balance < LVM_VC_BALANCE_MIN ) || (pParams->VC_Balance > LVM_VC_BALANCE_MAX ))
194 {
195 return (LVM_OUTOFRANGE);
196 }
197
198 /*
199 * PSA parameters
200 */
201 if( (pParams->PSA_PeakDecayRate > LVPSA_SPEED_HIGH) ||
202 (pParams->PSA_Enable > LVM_PSA_ON))
203 {
204 return (LVM_OUTOFRANGE);
205 }
206
207
208 /*
209 * Set the flag to indicate there are new parameters to use
210 *
211 * Protect the copy of the new parameters from interrupts to avoid possible problems
212 * with loss control parameters. This problem can occur if this control function is called more
213 * than once before a call to the process function. If the process function interrupts
214 * the copy to NewParams then one frame may have mixed parameters, some old and some new.
215 */
216 pInstance->ControlPending = LVM_TRUE;
217
218 return(LVM_SUCCESS);
219 }
220
221
222 /****************************************************************************************/
223 /* */
224 /* FUNCTION: LVM_GetControlParameters */
225 /* */
226 /* DESCRIPTION: */
227 /* Request the LifeVibes module parameters. The current parameter set is returned */
228 /* via the parameter pointer. */
229 /* */
230 /* PARAMETERS: */
231 /* hInstance Instance handle */
232 /* pParams Pointer to an empty parameter structure */
233 /* */
234 /* RETURNS: */
235 /* LVM_SUCCESS Succeeded */
236 /* LVM_NULLADDRESS when any of hInstance or pParams is NULL */
237 /* */
238 /* NOTES: */
239 /* 1. This function may be interrupted by the LVM_Process function */
240 /* */
241 /****************************************************************************************/
242
LVM_GetControlParameters(LVM_Handle_t hInstance,LVM_ControlParams_t * pParams)243 LVM_ReturnStatus_en LVM_GetControlParameters(LVM_Handle_t hInstance,
244 LVM_ControlParams_t *pParams)
245 {
246 LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
247
248
249 /*
250 * Check pointer
251 */
252 if ((pParams == LVM_NULL) || (hInstance == LVM_NULL))
253 {
254 return (LVM_NULLADDRESS);
255 }
256 *pParams = pInstance->NewParams;
257
258 /*
259 * Copy the filter definitions for the Equaliser
260 */
261 {
262 LVM_INT16 i;
263
264 if (pInstance->NewParams.EQNB_NBands != 0)
265 for (i=0; i<pInstance->NewParams.EQNB_NBands; i++)
266 {
267 pInstance->pEQNB_UserDefs[i] = pInstance->pEQNB_BandDefs[i];
268 }
269 pParams->pEQNB_BandDefinition = pInstance->pEQNB_UserDefs;
270 }
271
272 return(LVM_SUCCESS);
273 }
274
275
276 /****************************************************************************************/
277 /* */
278 /* FUNCTION: LVM_SetTrebleBoost */
279 /* */
280 /* DESCRIPTION: */
281 /* Enable the treble boost when the settings are appropriate, i.e. non-zero gain */
282 /* and the sample rate is high enough for the effect to be heard. */
283 /* */
284 /* PARAMETERS: */
285 /* pInstance Pointer to the instance structure */
286 /* pParams Pointer to the parameters to use */
287 /* */
288 /****************************************************************************************/
LVM_SetTrebleBoost(LVM_Instance_t * pInstance,LVM_ControlParams_t * pParams)289 void LVM_SetTrebleBoost(LVM_Instance_t *pInstance,
290 LVM_ControlParams_t *pParams)
291 {
292 #ifdef BUILD_FLOAT
293 extern FO_FLOAT_LShx_Coefs_t LVM_TrebleBoostCoefs[];
294 #else
295 extern FO_C16_LShx_Coefs_t LVM_TrebleBoostCoefs[];
296 #endif
297
298 LVM_INT16 Offset;
299 LVM_INT16 EffectLevel = 0;
300
301 /*
302 * Load the coefficients
303 */
304 if ((pParams->TE_OperatingMode == LVM_TE_ON) &&
305 (pParams->SampleRate >= TrebleBoostMinRate) &&
306 (pParams->OperatingMode == LVM_MODE_ON) &&
307 (pParams->TE_EffectLevel > 0))
308 {
309 if((pParams->TE_EffectLevel == LVM_TE_LOW_MIPS) &&
310 ((pParams->SpeakerType == LVM_HEADPHONES)||
311 (pParams->SpeakerType == LVM_EX_HEADPHONES)))
312 {
313 pInstance->TE_Active = LVM_FALSE;
314 }
315 else
316 {
317 EffectLevel = pParams->TE_EffectLevel;
318 pInstance->TE_Active = LVM_TRUE;
319 }
320
321 if(pInstance->TE_Active == LVM_TRUE)
322 {
323 /*
324 * Load the coefficients and enabled the treble boost
325 */
326 Offset = (LVM_INT16)(EffectLevel - 1 + TrebleBoostSteps * (pParams->SampleRate - TrebleBoostMinRate));
327 #ifdef BUILD_FLOAT
328 FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
329 &pInstance->pTE_Taps->TrebleBoost_Taps,
330 &LVM_TrebleBoostCoefs[Offset]);
331
332 /*
333 * Clear the taps
334 */
335 LoadConst_Float((LVM_FLOAT)0, /* Value */
336 (void *)&pInstance->pTE_Taps->TrebleBoost_Taps, /* Destination.\
337 Cast to void: no dereferencing in function */
338 (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps) / \
339 sizeof(LVM_FLOAT))); /* Number of words */
340 #else
341 FO_2I_D16F32Css_LShx_TRC_WRA_01_Init(&pInstance->pTE_State->TrebleBoost_State,
342 &pInstance->pTE_Taps->TrebleBoost_Taps,
343 &LVM_TrebleBoostCoefs[Offset]);
344
345 /*
346 * Clear the taps
347 */
348 LoadConst_16((LVM_INT16)0, /* Value */
349 (void *)&pInstance->pTE_Taps->TrebleBoost_Taps, /* Destination.\
350 Cast to void: no dereferencing in function */
351 (LVM_UINT16)(sizeof(pInstance->pTE_Taps->TrebleBoost_Taps)/sizeof(LVM_INT16))); /* Number of words */
352 #endif
353 }
354 }
355 else
356 {
357 /*
358 * Disable the treble boost
359 */
360 pInstance->TE_Active = LVM_FALSE;
361 }
362
363 return;
364 }
365
366
367 /************************************************************************************/
368 /* */
369 /* FUNCTION: LVM_SetVolume */
370 /* */
371 /* DESCRIPTION: */
372 /* Converts the input volume demand from dBs to linear. */
373 /* */
374 /* PARAMETERS: */
375 /* pInstance Pointer to the instance */
376 /* pParams Initialisation parameters */
377 /* */
378 /************************************************************************************/
LVM_SetVolume(LVM_Instance_t * pInstance,LVM_ControlParams_t * pParams)379 void LVM_SetVolume(LVM_Instance_t *pInstance,
380 LVM_ControlParams_t *pParams)
381 {
382
383 LVM_UINT16 dBShifts; /* 6dB shifts */
384 LVM_UINT16 dBOffset; /* Table offset */
385 LVM_INT16 Volume = 0; /* Required volume in dBs */
386 #ifdef BUILD_FLOAT
387 LVM_FLOAT Temp;
388 #endif
389
390 /*
391 * Limit the gain to the maximum allowed
392 */
393 if (pParams->VC_EffectLevel > 0)
394 {
395 Volume = 0;
396 }
397 else
398 {
399 Volume = pParams->VC_EffectLevel;
400 }
401
402 /* Compensate this volume in PSA plot */
403 if(Volume > -60) /* Limit volume loss to PSA Limits*/
404 pInstance->PSA_GainOffset=(LVM_INT16)(-Volume);/* Loss is compensated by Gain*/
405 else
406 pInstance->PSA_GainOffset=(LVM_INT16)60;/* Loss is compensated by Gain*/
407
408 pInstance->VC_AVLFixedVolume = 0;
409
410 /*
411 * Set volume control and AVL volumes according to headroom and volume user setting
412 */
413 if(pParams->OperatingMode == LVM_MODE_ON)
414 {
415 /* Default Situation with no AVL and no RS */
416 if(pParams->EQNB_OperatingMode == LVM_EQNB_ON)
417 {
418 if(Volume > -pInstance->Headroom)
419 Volume = (LVM_INT16)-pInstance->Headroom;
420 }
421 }
422
423 /*
424 * Activate volume control if necessary
425 */
426 pInstance->VC_Active = LVM_TRUE;
427 if (Volume != 0)
428 {
429 pInstance->VC_VolumedB = Volume;
430 }
431 else
432 {
433 pInstance->VC_VolumedB = 0;
434 }
435
436 /*
437 * Calculate the required gain and shifts
438 */
439 dBOffset = (LVM_UINT16)((-Volume) % 6); /* Get the dBs 0-5 */
440 dBShifts = (LVM_UINT16)(Volume / -6); /* Get the 6dB shifts */
441
442
443 /*
444 * Set the parameters
445 */
446 if(dBShifts == 0)
447 {
448 #ifdef BUILD_FLOAT
449 LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
450 (LVM_FLOAT)LVM_VolumeTable[dBOffset]);
451 #else
452 LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
453 (LVM_INT32)LVM_VolumeTable[dBOffset]);
454 #endif
455 }
456 else
457 {
458 #ifdef BUILD_FLOAT
459 Temp = LVM_VolumeTable[dBOffset];
460 while(dBShifts) {
461 Temp = Temp / 2.0f;
462 dBShifts--;
463 }
464 LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0], Temp);
465 #else
466 LVC_Mixer_SetTarget(&pInstance->VC_Volume.MixerStream[0],
467 (((LVM_INT32)LVM_VolumeTable[dBOffset])>>dBShifts));
468 #endif
469 }
470 pInstance->VC_Volume.MixerStream[0].CallbackSet = 1;
471 if(pInstance->NoSmoothVolume == LVM_TRUE)
472 {
473 #ifdef BUILD_FLOAT
474 LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0], 0,
475 pInstance->Params.SampleRate, 2);
476 #else
477 LVC_Mixer_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],0,pInstance->Params.SampleRate,2);
478 #endif
479 }
480 else
481 {
482 #ifdef BUILD_FLOAT
483 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],
484 LVM_VC_MIXER_TIME, pInstance->Params.SampleRate, 2);
485 #else
486 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_Volume.MixerStream[0],LVM_VC_MIXER_TIME,pInstance->Params.SampleRate,2);
487 #endif
488 }
489 }
490
491
492 /************************************************************************************/
493 /* */
494 /* FUNCTION: LVM_SetHeadroom */
495 /* */
496 /* DESCRIPTION: */
497 /* Find suitable headroom based on EQ settings. */
498 /* */
499 /* PARAMETERS: */
500 /* pInstance Pointer to the instance */
501 /* pParams Initialisation parameters */
502 /* */
503 /* RETURNS: */
504 /* void Nothing */
505 /* */
506 /* NOTES: */
507 /* */
508 /************************************************************************************/
LVM_SetHeadroom(LVM_Instance_t * pInstance,LVM_ControlParams_t * pParams)509 void LVM_SetHeadroom(LVM_Instance_t *pInstance,
510 LVM_ControlParams_t *pParams)
511 {
512 LVM_INT16 ii, jj;
513 LVM_INT16 Headroom = 0;
514 LVM_INT16 MaxGain = 0;
515
516
517 if ((pParams->EQNB_OperatingMode == LVEQNB_ON) && (pInstance->HeadroomParams.Headroom_OperatingMode == LVM_HEADROOM_ON))
518 {
519 /* Find typical headroom value */
520 for(jj = 0; jj < pInstance->HeadroomParams.NHeadroomBands; jj++)
521 {
522 MaxGain = 0;
523 for( ii = 0; ii < pParams->EQNB_NBands; ii++)
524 {
525 if((pParams->pEQNB_BandDefinition[ii].Frequency >= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_Low) &&
526 (pParams->pEQNB_BandDefinition[ii].Frequency <= pInstance->HeadroomParams.pHeadroomDefinition[jj].Limit_High))
527 {
528 if(pParams->pEQNB_BandDefinition[ii].Gain > MaxGain)
529 {
530 MaxGain = pParams->pEQNB_BandDefinition[ii].Gain;
531 }
532 }
533 }
534
535 if((MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset) > Headroom){
536 Headroom = (LVM_INT16)(MaxGain - pInstance->HeadroomParams.pHeadroomDefinition[jj].Headroom_Offset);
537 }
538 }
539
540 /* Saturate */
541 if(Headroom < 0)
542 Headroom = 0;
543 }
544 pInstance->Headroom = (LVM_UINT16)Headroom ;
545
546 }
547
548
549 /****************************************************************************************/
550 /* */
551 /* FUNCTION: LVM_ApplyNewSettings */
552 /* */
553 /* DESCRIPTION: */
554 /* Applies changes to parametres. This function makes no assumptions about what */
555 /* each module needs for initialisation and hence passes all parameters to all the */
556 /* the modules in turn. */
557 /* */
558 /* */
559 /* PARAMETERS: */
560 /* hInstance Instance handle */
561 /* */
562 /* RETURNS: */
563 /* LVM_Success Succeeded */
564 /* */
565 /****************************************************************************************/
566
LVM_ApplyNewSettings(LVM_Handle_t hInstance)567 LVM_ReturnStatus_en LVM_ApplyNewSettings(LVM_Handle_t hInstance)
568 {
569 LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
570 LVM_ControlParams_t LocalParams;
571 LVM_INT16 Count = 5;
572
573
574 /*
575 * Copy the new parameters but make sure they didn't change while copying
576 */
577 do
578 {
579 pInstance->ControlPending = LVM_FALSE;
580 LocalParams = pInstance->NewParams;
581 pInstance->HeadroomParams = pInstance->NewHeadroomParams;
582 Count--;
583 } while ((pInstance->ControlPending != LVM_FALSE) &&
584 (Count > 0));
585
586 #ifdef SUPPORT_MC
587 pInstance->NrChannels = LocalParams.NrChannels;
588 pInstance->ChMask = LocalParams.ChMask;
589 #endif
590
591 /* Clear all internal data if format change*/
592 if(LocalParams.SourceFormat != pInstance->Params.SourceFormat)
593 {
594 LVM_ClearAudioBuffers(pInstance);
595 pInstance->ControlPending = LVM_FALSE;
596 }
597
598 /*
599 * Update the treble boost if required
600 */
601 if ((pInstance->Params.SampleRate != LocalParams.SampleRate) ||
602 (pInstance->Params.TE_EffectLevel != LocalParams.TE_EffectLevel) ||
603 (pInstance->Params.TE_OperatingMode != LocalParams.TE_OperatingMode) ||
604 (pInstance->Params.OperatingMode != LocalParams.OperatingMode) ||
605 (pInstance->Params.SpeakerType != LocalParams.SpeakerType))
606 {
607 LVM_SetTrebleBoost(pInstance,
608 &LocalParams);
609 }
610
611 /*
612 * Update the headroom if required
613 */
614 LVM_SetHeadroom(pInstance, /* Instance pointer */
615 &LocalParams); /* New parameters */
616
617 /*
618 * Update the volume if required
619 */
620 {
621 LVM_SetVolume(pInstance, /* Instance pointer */
622 &LocalParams); /* New parameters */
623 }
624 /* Apply balance changes*/
625 if(pInstance->Params.VC_Balance != LocalParams.VC_Balance)
626 {
627 /* Configure Mixer module for gradual changes to volume*/
628 if(LocalParams.VC_Balance < 0)
629 {
630 #ifdef BUILD_FLOAT
631 LVM_FLOAT Target_Float;
632 #else
633 LVM_INT32 Target;
634 #endif
635 /* Drop in right channel volume*/
636 #ifdef BUILD_FLOAT
637 Target_Float = LVM_MAXFLOAT;
638 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
639 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
640 LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
641
642 Target_Float = dB_to_LinFloat((LVM_INT16)(LocalParams.VC_Balance << 4));
643 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
644 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
645 LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
646 #else
647 Target = LVM_MAXINT_16;
648 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
649 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
650
651 Target = dB_to_Lin32((LVM_INT16)(LocalParams.VC_Balance<<4));
652 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
653 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
654 #endif
655 }
656 else if(LocalParams.VC_Balance >0)
657 {
658 #ifdef BUILD_FLOAT
659 LVM_FLOAT Target_Float;
660 #else
661 LVM_INT32 Target;
662 #endif
663 /* Drop in left channel volume*/
664 #ifdef BUILD_FLOAT
665 Target_Float = dB_to_LinFloat((LVM_INT16)((-LocalParams.VC_Balance) << 4));
666 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0], Target_Float);
667 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
668 LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
669
670 Target_Float = LVM_MAXFLOAT;
671 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1], Target_Float);
672 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
673 LVM_VC_MIXER_TIME, LocalParams.SampleRate, 1);
674 #else
675 Target = dB_to_Lin32((LVM_INT16)((-LocalParams.VC_Balance)<<4));
676 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
677 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
678
679 Target = LVM_MAXINT_16;
680 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
681 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
682 #endif
683 }
684 else
685 {
686 #ifdef BUILD_FLOAT
687 LVM_FLOAT Target_Float;
688 #else
689 LVM_INT32 Target;
690 #endif
691 /* No drop*/
692 #ifdef BUILD_FLOAT
693 Target_Float = LVM_MAXFLOAT;
694 #else
695 Target = LVM_MAXINT_16;
696 #endif
697 #ifdef BUILD_FLOAT
698 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target_Float);
699 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],
700 LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
701
702 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target_Float);
703 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],
704 LVM_VC_MIXER_TIME,LocalParams.SampleRate, 1);
705 #else
706 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[0],Target);
707 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[0],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
708
709 LVC_Mixer_SetTarget(&pInstance->VC_BalanceMix.MixerStream[1],Target);
710 LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->VC_BalanceMix.MixerStream[1],LVM_VC_MIXER_TIME,LocalParams.SampleRate,1);
711 #endif
712 }
713 }
714 /*
715 * Update the bass enhancement
716 */
717 {
718 LVDBE_ReturnStatus_en DBE_Status;
719 LVDBE_Params_t DBE_Params;
720 LVDBE_Handle_t *hDBEInstance = pInstance->hDBEInstance;
721
722
723 /*
724 * Set the new parameters
725 */
726 if(LocalParams.OperatingMode == LVM_MODE_OFF)
727 {
728 DBE_Params.OperatingMode = LVDBE_OFF;
729 }
730 else
731 {
732 DBE_Params.OperatingMode = (LVDBE_Mode_en)LocalParams.BE_OperatingMode;
733 }
734 DBE_Params.SampleRate = (LVDBE_Fs_en)LocalParams.SampleRate;
735 DBE_Params.EffectLevel = LocalParams.BE_EffectLevel;
736 DBE_Params.CentreFrequency = (LVDBE_CentreFreq_en)LocalParams.BE_CentreFreq;
737 DBE_Params.HPFSelect = (LVDBE_FilterSelect_en)LocalParams.BE_HPF;
738 DBE_Params.HeadroomdB = 0;
739 DBE_Params.VolumeControl = LVDBE_VOLUME_OFF;
740 DBE_Params.VolumedB = 0;
741 #ifdef SUPPORT_MC
742 DBE_Params.NrChannels = LocalParams.NrChannels;
743 #endif
744
745 /*
746 * Make the changes
747 */
748 DBE_Status = LVDBE_Control(hDBEInstance,
749 &DBE_Params);
750
751
752 /*
753 * Quit if the changes were not accepted
754 */
755 if (DBE_Status != LVDBE_SUCCESS)
756 {
757 return((LVM_ReturnStatus_en)DBE_Status);
758 }
759
760
761 /*
762 * Set the control flag
763 */
764 pInstance->DBE_Active = LVM_TRUE;
765 }
766
767 /*
768 * Update the N-Band Equaliser
769 */
770 {
771 LVEQNB_ReturnStatus_en EQNB_Status;
772 LVEQNB_Params_t EQNB_Params;
773 LVEQNB_Handle_t *hEQNBInstance = pInstance->hEQNBInstance;
774
775
776 /*
777 * Set the new parameters
778 */
779
780 if(LocalParams.OperatingMode == LVM_MODE_OFF)
781 {
782 EQNB_Params.OperatingMode = LVEQNB_BYPASS;
783 }
784 else
785 {
786 EQNB_Params.OperatingMode = (LVEQNB_Mode_en)LocalParams.EQNB_OperatingMode;
787 }
788
789 EQNB_Params.SampleRate = (LVEQNB_Fs_en)LocalParams.SampleRate;
790 EQNB_Params.NBands = LocalParams.EQNB_NBands;
791 EQNB_Params.pBandDefinition = (LVEQNB_BandDef_t *)LocalParams.pEQNB_BandDefinition;
792 if (LocalParams.SourceFormat == LVM_STEREO) /* Mono format not supported */
793 {
794 EQNB_Params.SourceFormat = LVEQNB_STEREO;
795 }
796 #ifdef SUPPORT_MC
797 /* Note: Currently SourceFormat field of EQNB is not been
798 * used by the module.
799 */
800 else if (LocalParams.SourceFormat == LVM_MULTICHANNEL)
801 {
802 EQNB_Params.SourceFormat = LVEQNB_MULTICHANNEL;
803 }
804 #endif
805 else
806 {
807 EQNB_Params.SourceFormat = LVEQNB_MONOINSTEREO; /* Force to Mono-in-Stereo mode */
808 }
809 #ifdef SUPPORT_MC
810 EQNB_Params.NrChannels = LocalParams.NrChannels;
811 #endif
812
813 /*
814 * Set the control flag
815 */
816 if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
817 (LocalParams.EQNB_OperatingMode == LVM_EQNB_ON))
818 {
819 pInstance->EQNB_Active = LVM_TRUE;
820 }
821 else
822 {
823 EQNB_Params.OperatingMode = LVEQNB_BYPASS;
824 }
825
826 /*
827 * Make the changes
828 */
829 EQNB_Status = LVEQNB_Control(hEQNBInstance,
830 &EQNB_Params);
831
832
833 /*
834 * Quit if the changes were not accepted
835 */
836 if (EQNB_Status != LVEQNB_SUCCESS)
837 {
838 return((LVM_ReturnStatus_en)EQNB_Status);
839 }
840
841 }
842
843
844 /*
845 * Update concert sound
846 */
847 {
848 LVCS_ReturnStatus_en CS_Status;
849 LVCS_Params_t CS_Params;
850 LVCS_Handle_t *hCSInstance = pInstance->hCSInstance;
851 LVM_Mode_en CompressorMode=LVM_MODE_ON;
852
853 /*
854 * Set the new parameters
855 */
856 if(LocalParams.VirtualizerOperatingMode == LVM_MODE_ON)
857 {
858 CS_Params.OperatingMode = LVCS_ON;
859 }
860 else
861 {
862 CS_Params.OperatingMode = LVCS_OFF;
863 }
864
865 if((LocalParams.TE_OperatingMode == LVM_TE_ON) && (LocalParams.TE_EffectLevel == LVM_TE_LOW_MIPS))
866 {
867 CS_Params.SpeakerType = LVCS_EX_HEADPHONES;
868 }
869 else
870 {
871 CS_Params.SpeakerType = LVCS_HEADPHONES;
872 }
873
874 #ifdef SUPPORT_MC
875 /* Concert sound module processes only the left and right channels
876 * data. So the Source Format is set to LVCS_STEREO for multichannel
877 * input also.
878 */
879 if (LocalParams.SourceFormat == LVM_STEREO ||
880 LocalParams.SourceFormat == LVM_MULTICHANNEL)
881 #else
882 if (LocalParams.SourceFormat == LVM_STEREO) /* Mono format not supported */
883 #endif
884 {
885 CS_Params.SourceFormat = LVCS_STEREO;
886 }
887 else
888 {
889 CS_Params.SourceFormat = LVCS_MONOINSTEREO; /* Force to Mono-in-Stereo mode */
890 }
891 CS_Params.SampleRate = LocalParams.SampleRate;
892 CS_Params.ReverbLevel = LocalParams.VirtualizerReverbLevel;
893 CS_Params.EffectLevel = LocalParams.CS_EffectLevel;
894 #ifdef SUPPORT_MC
895 CS_Params.NrChannels = LocalParams.NrChannels;
896 #endif
897
898 /*
899 * Set the control flag
900 */
901 if ((LocalParams.OperatingMode == LVM_MODE_ON) &&
902 (LocalParams.VirtualizerOperatingMode != LVCS_OFF))
903 {
904 pInstance->CS_Active = LVM_TRUE;
905 }
906 else
907 {
908 CS_Params.OperatingMode = LVCS_OFF;
909 }
910
911 CS_Params.CompressorMode=CompressorMode;
912
913 /*
914 * Make the changes
915 */
916 CS_Status = LVCS_Control(hCSInstance,
917 &CS_Params);
918
919
920 /*
921 * Quit if the changes were not accepted
922 */
923 if (CS_Status != LVCS_SUCCESS)
924 {
925 return((LVM_ReturnStatus_en)CS_Status);
926 }
927
928 }
929
930 /*
931 * Update the Power Spectrum Analyser
932 */
933 {
934 LVPSA_RETURN PSA_Status;
935 LVPSA_ControlParams_t PSA_Params;
936 pLVPSA_Handle_t *hPSAInstance = pInstance->hPSAInstance;
937
938
939 /*
940 * Set the new parameters
941 */
942 PSA_Params.Fs = LocalParams.SampleRate;
943 PSA_Params.LevelDetectionSpeed = (LVPSA_LevelDetectSpeed_en)LocalParams.PSA_PeakDecayRate;
944
945 /*
946 * Make the changes
947 */
948 if(pInstance->InstParams.PSA_Included==LVM_PSA_ON)
949 {
950 PSA_Status = LVPSA_Control(hPSAInstance,
951 &PSA_Params);
952
953 if (PSA_Status != LVPSA_OK)
954 {
955 return((LVM_ReturnStatus_en)PSA_Status);
956 }
957
958 /*
959 * Apply new settings
960 */
961 PSA_Status = LVPSA_ApplyNewSettings ((LVPSA_InstancePr_t*)hPSAInstance);
962 if(PSA_Status != LVPSA_OK)
963 {
964 return((LVM_ReturnStatus_en)PSA_Status);
965 }
966 }
967 }
968
969 /*
970 * Update the parameters and clear the flag
971 */
972 pInstance->NoSmoothVolume = LVM_FALSE;
973 pInstance->Params = LocalParams;
974
975
976 return(LVM_SUCCESS);
977 }
978
979
980 /****************************************************************************************/
981 /* */
982 /* FUNCTION: LVM_SetHeadroomParams */
983 /* */
984 /* DESCRIPTION: */
985 /* This function is used to set the automatiuc headroom management parameters. */
986 /* */
987 /* PARAMETERS: */
988 /* hInstance Instance Handle */
989 /* pHeadroomParams Pointer to headroom parameter structure */
990 /* */
991 /* RETURNS: */
992 /* LVM_Success Succeeded */
993 /* */
994 /* NOTES: */
995 /* 1. This function may be interrupted by the LVM_Process function */
996 /* */
997 /****************************************************************************************/
998
LVM_SetHeadroomParams(LVM_Handle_t hInstance,LVM_HeadroomParams_t * pHeadroomParams)999 LVM_ReturnStatus_en LVM_SetHeadroomParams(LVM_Handle_t hInstance,
1000 LVM_HeadroomParams_t *pHeadroomParams)
1001 {
1002 LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
1003 LVM_UINT16 ii, NBands;
1004
1005 /* Check for NULL pointers */
1006 if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
1007 {
1008 return (LVM_NULLADDRESS);
1009 }
1010 if ((pHeadroomParams->NHeadroomBands != 0) && (pHeadroomParams->pHeadroomDefinition == LVM_NULL))
1011 {
1012 return (LVM_NULLADDRESS);
1013 }
1014
1015 /* Consider only the LVM_HEADROOM_MAX_NBANDS first bands*/
1016 if (pHeadroomParams->NHeadroomBands > LVM_HEADROOM_MAX_NBANDS)
1017 {
1018 NBands = LVM_HEADROOM_MAX_NBANDS;
1019 }
1020 else
1021 {
1022 NBands = pHeadroomParams->NHeadroomBands;
1023 }
1024 pInstance->NewHeadroomParams.NHeadroomBands = NBands;
1025
1026 /* Copy settings in memory */
1027 for(ii = 0; ii < NBands; ii++)
1028 {
1029 pInstance->pHeadroom_BandDefs[ii] = pHeadroomParams->pHeadroomDefinition[ii];
1030 }
1031
1032 pInstance->NewHeadroomParams.pHeadroomDefinition = pInstance->pHeadroom_BandDefs;
1033 pInstance->NewHeadroomParams.Headroom_OperatingMode = pHeadroomParams->Headroom_OperatingMode;
1034 pInstance->ControlPending = LVM_TRUE;
1035
1036 return(LVM_SUCCESS);
1037 }
1038
1039 /****************************************************************************************/
1040 /* */
1041 /* FUNCTION: LVM_GetHeadroomParams */
1042 /* */
1043 /* DESCRIPTION: */
1044 /* This function is used to get the automatic headroom management parameters. */
1045 /* */
1046 /* PARAMETERS: */
1047 /* hInstance Instance Handle */
1048 /* pHeadroomParams Pointer to headroom parameter structure (output) */
1049 /* */
1050 /* RETURNS: */
1051 /* LVM_SUCCESS Succeeded */
1052 /* LVM_NULLADDRESS When hInstance or pHeadroomParams are NULL */
1053 /* */
1054 /* NOTES: */
1055 /* 1. This function may be interrupted by the LVM_Process function */
1056 /* */
1057 /****************************************************************************************/
1058
LVM_GetHeadroomParams(LVM_Handle_t hInstance,LVM_HeadroomParams_t * pHeadroomParams)1059 LVM_ReturnStatus_en LVM_GetHeadroomParams(LVM_Handle_t hInstance,
1060 LVM_HeadroomParams_t *pHeadroomParams)
1061 {
1062 LVM_Instance_t *pInstance =(LVM_Instance_t *)hInstance;
1063 LVM_UINT16 ii;
1064
1065 /* Check for NULL pointers */
1066 if ((hInstance == LVM_NULL) || (pHeadroomParams == LVM_NULL))
1067 {
1068 return (LVM_NULLADDRESS);
1069 }
1070
1071 pHeadroomParams->NHeadroomBands = pInstance->NewHeadroomParams.NHeadroomBands;
1072
1073
1074 /* Copy settings in memory */
1075 for(ii = 0; ii < pInstance->NewHeadroomParams.NHeadroomBands; ii++)
1076 {
1077 pInstance->pHeadroom_UserDefs[ii] = pInstance->pHeadroom_BandDefs[ii];
1078 }
1079
1080
1081 pHeadroomParams->pHeadroomDefinition = pInstance->pHeadroom_UserDefs;
1082 pHeadroomParams->Headroom_OperatingMode = pInstance->NewHeadroomParams.Headroom_OperatingMode;
1083 return(LVM_SUCCESS);
1084 }
1085
1086 /****************************************************************************************/
1087 /* */
1088 /* FUNCTION: LVM_AlgoCallBack */
1089 /* */
1090 /* DESCRIPTION: */
1091 /* This is the callback function of the algorithm. */
1092 /* */
1093 /* PARAMETERS: */
1094 /* pBundleHandle Pointer to the Instance Handle */
1095 /* pData Pointer to the data */
1096 /* callbackId ID of the callback */
1097 /* */
1098 /* NOTES: */
1099 /* 1. This function may be interrupted by the LVM_Process function */
1100 /* */
1101 /****************************************************************************************/
LVM_AlgoCallBack(void * pBundleHandle,void * pData,LVM_INT16 callbackId)1102 LVM_INT32 LVM_AlgoCallBack( void *pBundleHandle,
1103 void *pData,
1104 LVM_INT16 callbackId)
1105 {
1106 LVM_Instance_t *pInstance =(LVM_Instance_t *)pBundleHandle;
1107
1108 (void) pData;
1109
1110 switch(callbackId & 0xFF00){
1111 case ALGORITHM_CS_ID:
1112 switch(callbackId & 0x00FF)
1113 {
1114 case LVCS_EVENT_ALGOFF:
1115 pInstance->CS_Active = LVM_FALSE;
1116 break;
1117 default:
1118 break;
1119 }
1120 break;
1121 case ALGORITHM_EQNB_ID:
1122 switch(callbackId & 0x00FF)
1123 {
1124 case LVEQNB_EVENT_ALGOFF:
1125 pInstance->EQNB_Active = LVM_FALSE;
1126 break;
1127 default:
1128 break;
1129 }
1130 break;
1131 default:
1132 break;
1133 }
1134
1135 return 0;
1136 }
1137
1138 /****************************************************************************************/
1139 /* */
1140 /* FUNCTION: LVM_VCCallBack */
1141 /* */
1142 /* DESCRIPTION: */
1143 /* This is the callback function of the Volume control. */
1144 /* */
1145 /* PARAMETERS: */
1146 /* pBundleHandle Pointer to the Instance Handle */
1147 /* pGeneralPurpose Pointer to the data */
1148 /* CallBackParam ID of the callback */
1149 /* */
1150 /* NOTES: */
1151 /* 1. This function may be interrupted by the LVM_Process function */
1152 /* */
1153 /****************************************************************************************/
LVM_VCCallBack(void * pBundleHandle,void * pGeneralPurpose,short CallBackParam)1154 LVM_INT32 LVM_VCCallBack(void* pBundleHandle,
1155 void* pGeneralPurpose,
1156 short CallBackParam)
1157 {
1158 LVM_Instance_t *pInstance =(LVM_Instance_t *)pBundleHandle;
1159 #ifdef BUILD_FLOAT
1160 LVM_FLOAT Target;
1161 #else
1162 LVM_INT32 Target;
1163 #endif
1164
1165 (void) pGeneralPurpose;
1166 (void) CallBackParam;
1167
1168 /* When volume mixer has reached 0 dB target then stop it to avoid
1169 unnecessary processing. */
1170 #ifdef BUILD_FLOAT
1171 Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
1172 if(Target == 1.0f)
1173 {
1174 pInstance->VC_Active = LVM_FALSE;
1175 }
1176 #else
1177 Target = LVC_Mixer_GetTarget(&pInstance->VC_Volume.MixerStream[0]);
1178
1179 if(Target == 0x7FFF)
1180 {
1181 pInstance->VC_Active = LVM_FALSE;
1182 }
1183 #endif
1184 return 1;
1185 }
1186