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 "LVDBE.h"
25 #include "LVDBE_Private.h"
26 #include "VectorArithmetic.h"
27 #include "LVDBE_Coeffs.h"
28 #include "LVDBE_Tables.h"
29 
30 /****************************************************************************************/
31 /*                                                                                      */
32 /* FUNCTION:                  LVDBE_GetParameters                                       */
33 /*                                                                                      */
34 /* DESCRIPTION:                                                                         */
35 /*    Request the Dynamic Bass Enhancement parameters. The current parameter set is     */
36 /*  returned via the parameter pointer.                                                 */
37 /*                                                                                      */
38 /* PARAMETERS:                                                                          */
39 /*  hInstance                   Instance handle                                         */
40 /*  pParams                  Pointer to an empty parameter structure                    */
41 /*                                                                                      */
42 /* RETURNS:                                                                             */
43 /*  LVDBE_SUCCESS            Always succeeds                                            */
44 /*                                                                                      */
45 /* NOTES:                                                                               */
46 /*  1.    This function may be interrupted by the LVDBE_Process function                */
47 /*                                                                                      */
48 /****************************************************************************************/
49 
LVDBE_GetParameters(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)50 LVDBE_ReturnStatus_en LVDBE_GetParameters(LVDBE_Handle_t        hInstance,
51                                             LVDBE_Params_t        *pParams)
52 {
53 
54     LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
55 
56     *pParams = pInstance->Params;
57 
58     return(LVDBE_SUCCESS);
59 }
60 
61 /************************************************************************************/
62 /*                                                                                  */
63 /* FUNCTION:                  LVDBE_GetCapabilities                                 */
64 /*                                                                                  */
65 /* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
66 /* returned via the pointer.                                                        */
67 /*                                                                                  */
68 /* PARAMETERS:                                                                      */
69 /*  hInstance                   Instance handle                                     */
70 /*  pCapabilities              Pointer to an empty capability structure             */
71 /*                                                                                  */
72 /* RETURNS:                                                                         */
73 /*  LVDBE_Success             Always succeeds                                       */
74 /*                                                                                  */
75 /* NOTES:                                                                           */
76 /*  1.    This function may be interrupted by the LVDBE_Process function            */
77 /*                                                                                  */
78 /************************************************************************************/
79 
LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,LVDBE_Capabilities_t * pCapabilities)80 LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
81                                               LVDBE_Capabilities_t    *pCapabilities)
82 {
83 
84     LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
85 
86     *pCapabilities = pInstance->Capabilities;
87 
88     return(LVDBE_SUCCESS);
89 }
90 
91 /************************************************************************************/
92 /*                                                                                  */
93 /* FUNCTION:            LVDBE_SetFilters                                            */
94 /*                                                                                  */
95 /* DESCRIPTION:                                                                     */
96 /*  Sets the filter coefficients and clears the data history                        */
97 /*                                                                                  */
98 /* PARAMETERS:                                                                      */
99 /*  pInstance           Pointer to the instance                                     */
100 /*  pParams             Initialisation parameters                                   */
101 /*                                                                                  */
102 /************************************************************************************/
103 
LVDBE_SetFilters(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)104 void    LVDBE_SetFilters(LVDBE_Instance_t     *pInstance,
105                          LVDBE_Params_t       *pParams)
106 {
107 
108     /*
109      * Calculate the table offsets
110      */
111     LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
112                                     (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_192000)));
113 
114     /*
115      * Setup the high pass filter
116      */
117     LoadConst_Float(0,                                          /* Clear the history, value 0 */
118                    (LVM_FLOAT *)&pInstance->pData->HPFTaps,     /* Destination */
119                     sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
120     BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
121                                     &pInstance->pData->HPFTaps,
122                                     (BQ_FLOAT_Coefs_t *)&LVDBE_HPF_Table[Offset]);
123 
124     /*
125      * Setup the band pass filter
126      */
127     LoadConst_Float(0,                                           /* Clear the history, value 0 */
128                  (LVM_FLOAT *)&pInstance->pData->BPFTaps,        /* Destination */
129                  sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT));   /* Number of words */
130     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,    /* Initialise the filter */
131                                     &pInstance->pData->BPFTaps,
132                                     (BP_FLOAT_Coefs_t *)&LVDBE_BPF_Table[Offset]);
133 }
134 
135 /************************************************************************************/
136 /*                                                                                  */
137 /* FUNCTION:            LVDBE_SetAGC                                                */
138 /*                                                                                  */
139 /* DESCRIPTION:                                                                     */
140 /*  Sets the AGC gain level and attack and decay times constants.                   */
141 /*                                                                                  */
142 /* PARAMETERS:                                                                      */
143 /*  pInstance           Pointer to the instance                                     */
144 /*  pParams             Initialisation parameters                                   */
145 /*                                                                                  */
146 /************************************************************************************/
147 
LVDBE_SetAGC(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)148 void    LVDBE_SetAGC(LVDBE_Instance_t     *pInstance,
149                      LVDBE_Params_t       *pParams)
150 {
151 
152     /*
153      * Get the attack and decay time constants
154      */
155     pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate];  /* Attack multiplier */
156     pInstance->pData->AGCInstance.AGC_Decay  = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate];   /* Decay multipler */
157 
158     /*
159      * Get the boost gain
160      */
161     if (pParams->HPFSelect == LVDBE_HPF_ON)
162     {
163         pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel];  /* High pass filter on */
164     }
165     else
166     {
167         pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel];     /* High pass filter off */
168     }
169     pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
170 
171 }
172 
173 /************************************************************************************/
174 /*                                                                                  */
175 /* FUNCTION:            LVDBE_SetVolume                                             */
176 /*                                                                                  */
177 /* DESCRIPTION:                                                                     */
178 /*  Converts the input volume demand from dBs to linear.                            */
179 /*                                                                                  */
180 /* PARAMETERS:                                                                      */
181 /*  pInstance           Pointer to the instance                                     */
182 /*  pParams             Initialisation parameters                                   */
183 /*                                                                                  */
184 /* NOTES:                                                                           */
185 /*  1. The volume should have the following settings:                               */
186 /*                                                                                  */
187 /*          DBE         Vol Control           Volume setting                        */
188 /*          ===         ===========         ===================                     */
189 /*          Off             Off                 HeadroomdB                          */
190 /*          Off             On              VolumedB+HeadroomdB                     */
191 /*          On              Off                 HeadroomdB                          */
192 /*          On              On              VolumedB+HeadroomdB                     */
193 /*                                                                                  */
194 /************************************************************************************/
195 
LVDBE_SetVolume(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)196 void    LVDBE_SetVolume(LVDBE_Instance_t     *pInstance,
197                         LVDBE_Params_t       *pParams)
198 {
199 
200     LVM_UINT16      dBShifts;                                   /* 6dB shifts */
201     LVM_UINT16      dBOffset;                                   /* Table offset */
202     LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
203 
204     LVM_FLOAT        dBShifts_fac;
205     /*
206      * Apply the volume if enabled
207      */
208     if (pParams->VolumeControl == LVDBE_VOLUME_ON)
209     {
210         /*
211          * Limit the gain to the maximum allowed
212          */
213         if  (pParams->VolumedB > VOLUME_MAX)
214         {
215             Volume = VOLUME_MAX;
216         }
217         else
218         {
219             Volume = pParams->VolumedB;
220         }
221     }
222 
223     /*
224      * Calculate the required gain and shifts
225      */
226     dBOffset = (LVM_UINT16)(6 + Volume % 6);                    /* Get the dBs 0-5 */
227     dBShifts = (LVM_UINT16)(Volume / -6);                       /* Get the 6dB shifts */
228 
229     dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
230     /*
231      * When DBE is enabled use AGC volume
232      */
233     pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
234     pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
235     pInstance->pData->AGCInstance.VolumeTC    = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate];   /* Volume update time constant */
236 
237     /*
238      * When DBE is disabled use the bypass volume control
239      */
240     if(dBShifts > 0)
241     {
242         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
243                             LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
244     }
245     else
246     {
247         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
248                             LVDBE_VolumeTable[dBOffset]);
249     }
250 
251     pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
252     LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
253                                 LVDBE_MIXER_TC,
254                                 (LVM_Fs_en)pInstance->Params.SampleRate,
255                                 2);
256 }
257 
258 /****************************************************************************************/
259 /*                                                                                      */
260 /* FUNCTION:                LVDBE_Control                                               */
261 /*                                                                                      */
262 /* DESCRIPTION:                                                                         */
263 /*  Sets or changes the Bass Enhancement parameters. Changing the parameters while the  */
264 /*  module is processing signals may have the following side effects:                   */
265 /*                                                                                      */
266 /*  General parameters:                                                                 */
267 /*  ===================                                                                 */
268 /*  OperatingMode:      Changing the mode of operation may cause a change in volume     */
269 /*                      level or cause pops and clicks.                                 */
270 /*                                                                                      */
271 /*  SampleRate:         Changing the sample rate may cause pops and clicks.             */
272 /*                                                                                      */
273 /*  EffectLevel:        Changing the effect level may cause pops and clicks             */
274 /*                                                                                      */
275 /*  CentreFrequency:    Changing the centre frequency may cause pops and clicks         */
276 /*                                                                                      */
277 /*  HPFSelect:          Selecting/de-selecting the high pass filter may cause pops and  */
278 /*                      clicks                                                          */
279 /*                                                                                      */
280 /*  VolumedB            Changing the volume setting will have no side effects           */
281 /*                                                                                      */
282 /*                                                                                      */
283 /* PARAMETERS:                                                                          */
284 /*  hInstance               Instance handle                                             */
285 /*  pParams                 Pointer to a parameter structure                            */
286 /*                                                                                      */
287 /* RETURNS:                                                                             */
288 /*  LVDBE_SUCCESS           Always succeeds                                             */
289 /*                                                                                      */
290 /* NOTES:                                                                               */
291 /*  1.  This function must not be interrupted by the LVDBE_Process function             */
292 /*                                                                                      */
293 /****************************************************************************************/
294 
LVDBE_Control(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)295 LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t         hInstance,
296                                       LVDBE_Params_t         *pParams)
297 {
298 
299     LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
300     LVMixer3_2St_FLOAT_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
301 
302     /*
303      * Update the filters
304      */
305     if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
306         (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
307     {
308         LVDBE_SetFilters(pInstance,                     /* Instance pointer */
309                          pParams);                      /* New parameters */
310     }
311 
312     /*
313      * Update the AGC is the effect level has changed
314      */
315     if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
316         (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
317         (pInstance->Params.HPFSelect != pParams->HPFSelect))
318     {
319         LVDBE_SetAGC(pInstance,                         /* Instance pointer */
320                      pParams);                          /* New parameters */
321         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
322             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
323 
324         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
325             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
326 
327     }
328 
329     /*
330      * Update the Volume if the volume demand has changed
331      */
332     if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
333         (pInstance->Params.SampleRate != pParams->SampleRate) ||
334         (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
335         (pInstance->Params.VolumeControl != pParams->VolumeControl))
336     {
337         LVDBE_SetVolume(pInstance,                      /* Instance pointer */
338                        pParams);                        /* New parameters */
339     }
340 
341     if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
342     {
343         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
344         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
345     }
346     if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
347     {
348         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
349         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
350     }
351 
352     /*
353      * Update the instance parameters
354      */
355     pInstance->Params = *pParams;
356 
357     return(LVDBE_SUCCESS);
358 }
359