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