Home | History | Annotate | Download | only in src
      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 
     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 
     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 
    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 
    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 
    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 
    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