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
50LVDBE_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
81LVDBE_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
106void    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
189void    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
242void    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
370LVDBE_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