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