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 /*                                                                                  */
64 /* FUNCTION:                  LVDBE_GetCapabilities                                 */
65 /*                                                                                  */
66 /* DESCRIPTION: Dynamic Bass Enhnacement capabilities. The current capabilities are */
67 /* returned via the pointer.                                                        */
68 /*                                                                                  */
69 /* PARAMETERS:                                                                      */
70 /*  hInstance                   Instance handle                                     */
71 /*  pCapabilities              Pointer to an empty capability structure             */
72 /*                                                                                  */
73 /* RETURNS:                                                                         */
74 /*  LVDBE_Success             Always succeeds                                       */
75 /*                                                                                  */
76 /* NOTES:                                                                           */
77 /*  1.    This function may be interrupted by the LVDBE_Process function            */
78 /*                                                                                  */
79 /************************************************************************************/
80 
LVDBE_GetCapabilities(LVDBE_Handle_t hInstance,LVDBE_Capabilities_t * pCapabilities)81 LVDBE_ReturnStatus_en LVDBE_GetCapabilities(LVDBE_Handle_t            hInstance,
82                                               LVDBE_Capabilities_t    *pCapabilities)
83 {
84 
85     LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
86 
87     *pCapabilities = pInstance->Capabilities;
88 
89     return(LVDBE_SUCCESS);
90 }
91 
92 
93 /************************************************************************************/
94 /*                                                                                  */
95 /* FUNCTION:            LVDBE_SetFilters                                            */
96 /*                                                                                  */
97 /* DESCRIPTION:                                                                     */
98 /*  Sets the filter coefficients and clears the data history                        */
99 /*                                                                                  */
100 /* PARAMETERS:                                                                      */
101 /*  pInstance           Pointer to the instance                                     */
102 /*  pParams             Initialisation parameters                                   */
103 /*                                                                                  */
104 /************************************************************************************/
105 
LVDBE_SetFilters(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)106 void    LVDBE_SetFilters(LVDBE_Instance_t     *pInstance,
107                          LVDBE_Params_t       *pParams)
108 {
109 
110 #if defined(BUILD_FLOAT) && defined(HIGHER_FS)
111     /*
112      * Calculate the table offsets
113      */
114     LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
115                                     (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_192000)));
116 #else
117     /*
118      * Calculate the table offsets
119      */
120     LVM_UINT16 Offset = (LVM_UINT16)((LVM_UINT16)pParams->SampleRate + \
121                                     (LVM_UINT16)(pParams->CentreFrequency * (1+LVDBE_FS_48000)));
122 #endif
123 
124     /*
125      * Setup the high pass filter
126      */
127 #ifndef BUILD_FLOAT
128     LoadConst_16(0,                                              /* Clear the history, value 0 */
129                  (void *)&pInstance->pData->HPFTaps,             /* Destination Cast to void: \
130                                                                     no dereferencing in function*/
131                  sizeof(pInstance->pData->HPFTaps)/sizeof(LVM_INT16));   /* Number of words */
132 #else
133     LoadConst_Float(0,                                          /* Clear the history, value 0 */
134                    (void *)&pInstance->pData->HPFTaps,          /* Destination Cast to void: \
135                                                                   no dereferencing in function*/
136                     sizeof(pInstance->pData->HPFTaps) / sizeof(LVM_FLOAT)); /* Number of words */
137 #endif
138 #ifndef BUILD_FLOAT
139     BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
140                                     &pInstance->pData->HPFTaps,
141                                     (BQ_C32_Coefs_t *)&LVDBE_HPF_Table[Offset]);
142 #else
143     BQ_2I_D32F32Cll_TRC_WRA_01_Init(&pInstance->pCoef->HPFInstance,    /* Initialise the filter */
144                                     &pInstance->pData->HPFTaps,
145                                     (BQ_FLOAT_Coefs_t *)&LVDBE_HPF_Table[Offset]);
146 #endif
147 
148 
149     /*
150      * Setup the band pass filter
151      */
152 #ifndef BUILD_FLOAT
153     LoadConst_16(0,                                                 /* Clear the history, value 0 */
154                  (void *)&pInstance->pData->BPFTaps,                /* Destination Cast to void: \
155                                                                      no dereferencing in function*/
156                  sizeof(pInstance->pData->BPFTaps)/sizeof(LVM_INT16));   /* Number of words */
157 #else
158     LoadConst_Float(0,                                           /* Clear the history, value 0 */
159                  (void *)&pInstance->pData->BPFTaps,             /* Destination Cast to void: \
160                                                                     no dereferencing in function*/
161                  sizeof(pInstance->pData->BPFTaps) / sizeof(LVM_FLOAT));   /* Number of words */
162 #endif
163 #ifndef BUILD_FLOAT
164     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,         /* Initialise the filter */
165                                     &pInstance->pData->BPFTaps,
166                                     (BP_C32_Coefs_t *)&LVDBE_BPF_Table[Offset]);
167 #else
168     BP_1I_D32F32Cll_TRC_WRA_02_Init(&pInstance->pCoef->BPFInstance,    /* Initialise the filter */
169                                     &pInstance->pData->BPFTaps,
170                                     (BP_FLOAT_Coefs_t *)&LVDBE_BPF_Table[Offset]);
171 #endif
172 }
173 
174 
175 
176 /************************************************************************************/
177 /*                                                                                  */
178 /* FUNCTION:            LVDBE_SetAGC                                                */
179 /*                                                                                  */
180 /* DESCRIPTION:                                                                     */
181 /*  Sets the AGC gain level and attack and decay times constants.                   */
182 /*                                                                                  */
183 /* PARAMETERS:                                                                      */
184 /*  pInstance           Pointer to the instance                                     */
185 /*  pParams             Initialisation parameters                                   */
186 /*                                                                                  */
187 /************************************************************************************/
188 
LVDBE_SetAGC(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)189 void    LVDBE_SetAGC(LVDBE_Instance_t     *pInstance,
190                      LVDBE_Params_t       *pParams)
191 {
192 
193     /*
194      * Get the attack and decay time constants
195      */
196     pInstance->pData->AGCInstance.AGC_Attack = LVDBE_AGC_ATTACK_Table[(LVM_UINT16)pParams->SampleRate];  /* Attack multiplier */
197     pInstance->pData->AGCInstance.AGC_Decay  = LVDBE_AGC_DECAY_Table[(LVM_UINT16)pParams->SampleRate];   /* Decay multipler */
198 
199 
200     /*
201      * Get the boost gain
202      */
203     if (pParams->HPFSelect == LVDBE_HPF_ON)
204     {
205         pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_HPFGAIN_Table[(LVM_UINT16)pParams->EffectLevel];  /* High pass filter on */
206     }
207     else
208     {
209         pInstance->pData->AGCInstance.AGC_MaxGain   = LVDBE_AGC_GAIN_Table[(LVM_UINT16)pParams->EffectLevel];     /* High pass filter off */
210     }
211 #ifndef BUILD_FLOAT
212     pInstance->pData->AGCInstance.AGC_GainShift = AGC_GAIN_SHIFT;
213 #endif
214     pInstance->pData->AGCInstance.AGC_Target = AGC_TARGETLEVEL;
215 
216 }
217 
218 
219 /************************************************************************************/
220 /*                                                                                  */
221 /* FUNCTION:            LVDBE_SetVolume                                             */
222 /*                                                                                  */
223 /* DESCRIPTION:                                                                     */
224 /*  Converts the input volume demand from dBs to linear.                            */
225 /*                                                                                  */
226 /* PARAMETERS:                                                                      */
227 /*  pInstance           Pointer to the instance                                     */
228 /*  pParams             Initialisation parameters                                   */
229 /*                                                                                  */
230 /* NOTES:                                                                           */
231 /*  1. The volume should have the following settings:                               */
232 /*                                                                                  */
233 /*          DBE         Vol Control           Volume setting                        */
234 /*          ===         ===========         ===================                     */
235 /*          Off             Off                 HeadroomdB                          */
236 /*          Off             On              VolumedB+HeadroomdB                     */
237 /*          On              Off                 HeadroomdB                          */
238 /*          On              On              VolumedB+HeadroomdB                     */
239 /*                                                                                  */
240 /************************************************************************************/
241 
LVDBE_SetVolume(LVDBE_Instance_t * pInstance,LVDBE_Params_t * pParams)242 void    LVDBE_SetVolume(LVDBE_Instance_t     *pInstance,
243                         LVDBE_Params_t       *pParams)
244 {
245 
246     LVM_UINT16      dBShifts;                                   /* 6dB shifts */
247     LVM_UINT16      dBOffset;                                   /* Table offset */
248     LVM_INT16       Volume = 0;                                 /* Required volume in dBs */
249 
250 #ifdef BUILD_FLOAT
251     LVM_FLOAT        dBShifts_fac;
252 #endif
253     /*
254      * Apply the volume if enabled
255      */
256     if (pParams->VolumeControl == LVDBE_VOLUME_ON)
257     {
258         /*
259          * Limit the gain to the maximum allowed
260          */
261         if  (pParams->VolumedB > VOLUME_MAX)
262         {
263             Volume = VOLUME_MAX;
264         }
265         else
266         {
267             Volume = pParams->VolumedB;
268         }
269     }
270 
271 
272     /*
273      * Calculate the required gain and shifts
274      */
275     dBOffset = (LVM_UINT16)(6 + Volume % 6);                    /* Get the dBs 0-5 */
276     dBShifts = (LVM_UINT16)(Volume / -6);                       /* Get the 6dB shifts */
277 
278 #ifdef BUILD_FLOAT
279     dBShifts_fac = (LVM_FLOAT)(1 << dBShifts);
280 #endif
281     /*
282      * When DBE is enabled use AGC volume
283      */
284 #ifndef BUILD_FLOAT
285     pInstance->pData->AGCInstance.Target = ((LVM_INT32)LVDBE_VolumeTable[dBOffset] << 16);
286     pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target >> dBShifts;
287 #else
288     pInstance->pData->AGCInstance.Target = (LVDBE_VolumeTable[dBOffset]);
289     pInstance->pData->AGCInstance.Target = pInstance->pData->AGCInstance.Target / dBShifts_fac;
290 #endif
291     pInstance->pData->AGCInstance.VolumeTC    = LVDBE_VolumeTCTable[(LVM_UINT16)pParams->SampleRate];   /* Volume update time constant */
292 #ifndef BUILD_FLOAT
293     pInstance->pData->AGCInstance.VolumeShift = VOLUME_SHIFT+1;
294 #endif
295 
296     /*
297      * When DBE is disabled use the bypass volume control
298      */
299     if(dBShifts > 0)
300     {
301 #ifndef BUILD_FLOAT
302         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(((LVM_INT32)LVDBE_VolumeTable[dBOffset]) >> dBShifts));
303 #else
304         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
305                             LVDBE_VolumeTable[dBOffset] / dBShifts_fac);
306 #endif
307     }
308     else
309     {
310 #ifndef BUILD_FLOAT
311         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],(LVM_INT32)LVDBE_VolumeTable[dBOffset]);
312 #else
313         LVC_Mixer_SetTarget(&pInstance->pData->BypassVolume.MixerStream[0],
314                             LVDBE_VolumeTable[dBOffset]);
315 #endif
316     }
317 
318     pInstance->pData->BypassVolume.MixerStream[0].CallbackSet = 1;
319 #ifndef BUILD_FLOAT
320     LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
321                                 LVDBE_MIXER_TC,
322                                 (LVM_Fs_en)pInstance->Params.SampleRate,
323                                 2);
324 #else
325     LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->pData->BypassVolume.MixerStream[0],
326                                 LVDBE_MIXER_TC,
327                                 (LVM_Fs_en)pInstance->Params.SampleRate,
328                                 2);
329 #endif
330 }
331 
332 
333 /****************************************************************************************/
334 /*                                                                                      */
335 /* FUNCTION:                LVDBE_Control                                               */
336 /*                                                                                      */
337 /* DESCRIPTION:                                                                         */
338 /*  Sets or changes the Bass Enhancement parameters. Changing the parameters while the  */
339 /*  module is processing signals may have the following side effects:                   */
340 /*                                                                                      */
341 /*  General parameters:                                                                 */
342 /*  ===================                                                                 */
343 /*  OperatingMode:      Changing the mode of operation may cause a change in volume     */
344 /*                      level or cause pops and clicks.                                 */
345 /*                                                                                      */
346 /*  SampleRate:         Changing the sample rate may cause pops and clicks.             */
347 /*                                                                                      */
348 /*  EffectLevel:        Changing the effect level may cause pops and clicks             */
349 /*                                                                                      */
350 /*  CentreFrequency:    Changing the centre frequency may cause pops and clicks         */
351 /*                                                                                      */
352 /*  HPFSelect:          Selecting/de-selecting the high pass filter may cause pops and  */
353 /*                      clicks                                                          */
354 /*                                                                                      */
355 /*  VolumedB            Changing the volume setting will have no side effects           */
356 /*                                                                                      */
357 /*                                                                                      */
358 /* PARAMETERS:                                                                          */
359 /*  hInstance               Instance handle                                             */
360 /*  pParams                 Pointer to a parameter structure                            */
361 /*                                                                                      */
362 /* RETURNS:                                                                             */
363 /*  LVDBE_SUCCESS           Always succeeds                                             */
364 /*                                                                                      */
365 /* NOTES:                                                                               */
366 /*  1.  This function must not be interrupted by the LVDBE_Process function             */
367 /*                                                                                      */
368 /****************************************************************************************/
369 
LVDBE_Control(LVDBE_Handle_t hInstance,LVDBE_Params_t * pParams)370 LVDBE_ReturnStatus_en LVDBE_Control(LVDBE_Handle_t         hInstance,
371                                       LVDBE_Params_t         *pParams)
372 {
373 
374     LVDBE_Instance_t    *pInstance =(LVDBE_Instance_t  *)hInstance;
375 #ifndef BUILD_FLOAT
376     LVMixer3_2St_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
377 #else
378     LVMixer3_2St_FLOAT_st     *pBypassMixer_Instance = &pInstance->pData->BypassMixer;
379 #endif
380 
381 
382     /*
383      * Update the filters
384      */
385     if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
386         (pInstance->Params.CentreFrequency != pParams->CentreFrequency))
387     {
388         LVDBE_SetFilters(pInstance,                     /* Instance pointer */
389                          pParams);                      /* New parameters */
390     }
391 
392 
393     /*
394      * Update the AGC is the effect level has changed
395      */
396     if ((pInstance->Params.SampleRate != pParams->SampleRate) ||
397         (pInstance->Params.EffectLevel != pParams->EffectLevel) ||
398         (pInstance->Params.HPFSelect != pParams->HPFSelect))
399     {
400         LVDBE_SetAGC(pInstance,                         /* Instance pointer */
401                      pParams);                          /* New parameters */
402 #ifndef BUILD_FLOAT
403         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
404             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
405 
406         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
407             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
408 #else
409         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
410             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
411 
412         LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
413             LVDBE_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate, 2);
414 #endif
415 
416 
417     }
418 
419 
420     /*
421      * Update the Volume if the volume demand has changed
422      */
423     if ((pInstance->Params.VolumedB != pParams->VolumedB) ||
424         (pInstance->Params.SampleRate != pParams->SampleRate) ||
425         (pInstance->Params.HeadroomdB != pParams->HeadroomdB) ||
426         (pInstance->Params.VolumeControl != pParams->VolumeControl))
427     {
428         LVDBE_SetVolume(pInstance,                      /* Instance pointer */
429                        pParams);                        /* New parameters */
430     }
431 
432     if (pInstance->Params.OperatingMode==LVDBE_ON && pParams->OperatingMode==LVDBE_OFF)
433     {
434 #ifndef BUILD_FLOAT
435         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0);
436         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0x00007FFF);
437 #else
438         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 0);
439         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 1.0f);
440 #endif
441     }
442     if (pInstance->Params.OperatingMode==LVDBE_OFF && pParams->OperatingMode==LVDBE_ON)
443     {
444 #ifndef BUILD_FLOAT
445         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0],0x00007FFF);
446         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1],0);
447 #else
448         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[0], 1.0f);
449         LVC_Mixer_SetTarget(&pInstance->pData->BypassMixer.MixerStream[1], 0);
450 #endif
451     }
452 
453     /*
454      * Update the instance parameters
455      */
456     pInstance->Params = *pParams;
457 
458 
459     return(LVDBE_SUCCESS);
460 }
461