• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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