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 "LVEQNB.h"
     25 #include "LVEQNB_Private.h"
     26 #include "VectorArithmetic.h"
     27 #include "BIQUAD.h"
     28 
     29 
     30 /****************************************************************************************/
     31 /*                                                                                      */
     32 /*  Defines                                                                             */
     33 /*                                                                                      */
     34 /****************************************************************************************/
     35 
     36 #define     LOW_FREQ            298             /* 32768/110 for low test frequency */
     37 #define     HIGH_FREQ           386             /* 32768/85 for high test frequency */
     38 
     39 /****************************************************************************************/
     40 /*                                                                                      */
     41 /* FUNCTION:                 LVEQNB_GetParameters                                       */
     42 /*                                                                                      */
     43 /* DESCRIPTION:                                                                         */
     44 /*  Request the N-Band equaliser parameters. The current parameter set is returned via  */
     45 /*  the parameter pointer.                                                              */
     46 /*                                                                                      */
     47 /* PARAMETERS:                                                                          */
     48 /*  hInstance                Instance handle                                            */
     49 /*  pParams                  Pointer to an empty parameter structure                    */
     50 /*                                                                                      */
     51 /* RETURNS:                                                                             */
     52 /*  LVEQNB_SUCCESS          Succeeds                                                    */
     53 /*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
     54 /*                                                                                      */
     55 /* NOTES:                                                                               */
     56 /*  1.  This function may be interrupted by the LVEQNB_Process function                 */
     57 /*                                                                                      */
     58 /****************************************************************************************/
     59 
     60 LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t     hInstance,
     61                                             LVEQNB_Params_t     *pParams)
     62 {
     63 
     64     LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
     65 
     66    /*
     67      * Check for error conditions
     68      */
     69     if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
     70     {
     71         return LVEQNB_NULLADDRESS;
     72     }
     73 
     74     *pParams = pInstance->Params;
     75 
     76     return(LVEQNB_SUCCESS);
     77 }
     78 
     79 
     80 /************************************************************************************/
     81 /*                                                                                  */
     82 /* FUNCTION:                 LVEQNB_GetCapabilities                                 */
     83 /*                                                                                  */
     84 /* DESCRIPTION:                                                                     */
     85 /*  Get the N-Band equaliser capabilities. The current capabilities are returned    */
     86 /*  via the pointer.                                                                */
     87 /*                                                                                  */
     88 /* PARAMETERS:                                                                      */
     89 /*  hInstance                Instance handle                                        */
     90 /*  pCapabilities            Pointer to an empty capability structure               */
     91 /*                                                                                  */
     92 /* RETURNS:                                                                         */
     93 /*  LVEQNB_Success           Succeeds                                               */
     94 /*  LVEQNB_NULLADDRESS       hInstance or pCapabilities is NULL                     */
     95 /*                                                                                  */
     96 /* NOTES:                                                                           */
     97 /*  1.  This function may be interrupted by the LVEQNB_Process function             */
     98 /*                                                                                  */
     99 /************************************************************************************/
    100 
    101 LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t           hInstance,
    102                                               LVEQNB_Capabilities_t     *pCapabilities)
    103 {
    104 
    105     LVEQNB_Instance_t    *pInstance =(LVEQNB_Instance_t  *)hInstance;
    106 
    107     if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL))
    108     {
    109         return LVEQNB_NULLADDRESS;
    110     }
    111 
    112     *pCapabilities = pInstance->Capabilities;
    113 
    114     return(LVEQNB_SUCCESS);
    115 }
    116 
    117 
    118 /************************************************************************************/
    119 /*                                                                                  */
    120 /* FUNCTION:            LVEQNB_SetFilters                                           */
    121 /*                                                                                  */
    122 /* DESCRIPTION:                                                                     */
    123 /*  Sets the filter type based on the definition.                                   */
    124 /*                                                                                  */
    125 /* PARAMETERS:                                                                      */
    126 /*  pInstance           Pointer to the instance                                     */
    127 /*  pParams             Initialisation parameters                                   */
    128 /*                                                                                  */
    129 /* RETURNS:                                                                         */
    130 /*  void                Nothing                                                     */
    131 /*                                                                                  */
    132 /* NOTES:                                                                           */
    133 /*  1. To select the biquad type the follow rules are applied:                      */
    134 /*          Double precision    if (fc <= fs/110)                                   */
    135 /*          Double precision    if (fs/110 < fc < fs/85) & (Q>3)                    */
    136 /*          Single precision    otherwise                                           */
    137 /*                                                                                  */
    138 /************************************************************************************/
    139 
    140 void    LVEQNB_SetFilters(LVEQNB_Instance_t     *pInstance,
    141                           LVEQNB_Params_t       *pParams)
    142 {
    143 #ifdef HIGHER_FS
    144     extern const LVM_UINT32   LVEQNB_SampleRateTab[];           /* Sample rate table */
    145 #else
    146     extern const LVM_UINT16   LVEQNB_SampleRateTab[];           /* Sample rate table */
    147 #endif
    148 
    149     LVM_UINT16          i;                                      /* Filter band index */
    150     LVM_UINT32          fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate];  /* Sample rate */
    151     LVM_UINT32          fc;                                     /* Filter centre frequency */
    152     LVM_INT16           QFactor;                                /* Filter Q factor */
    153 
    154 
    155     pInstance->NBands = pParams->NBands;
    156 
    157     for (i=0; i<pParams->NBands; i++)
    158     {
    159         /*
    160          * Get the filter settings
    161          */
    162         fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency;     /* Get the band centre frequency */
    163         QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor;   /* Get the band Q factor */
    164 
    165 #ifdef BUILD_FLOAT
    166         pInstance->pBiquadType[i] = LVEQNB_SinglePrecision_Float; /* Default to single precision */
    167 #else
    168         /*
    169          * For each filter set the type of biquad required
    170          */
    171         pInstance->pBiquadType[i] = LVEQNB_SinglePrecision;         /* Default to single precision */
    172 #endif
    173 #ifndef BUILD_FLOAT
    174         if ((fc << 15) <= (LOW_FREQ * fs))
    175         {
    176             /*
    177              * fc <= fs/110
    178              */
    179             pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
    180         }
    181         else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300))
    182         {
    183             /*
    184              * (fs/110 < fc < fs/85) & (Q>3)
    185              */
    186             pInstance->pBiquadType[i] = LVEQNB_DoublePrecision;
    187         }
    188 #endif
    189 
    190         /*
    191          * Check for out of range frequencies
    192          */
    193         if (fc > (fs >> 1))
    194         {
    195             pInstance->pBiquadType[i] = LVEQNB_OutOfRange;
    196         }
    197 
    198 
    199         /*
    200          * Copy the filter definition to persistant memory
    201          */
    202         pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i];
    203 
    204     }
    205 }
    206 
    207 
    208 /************************************************************************************/
    209 /*                                                                                  */
    210 /* FUNCTION:            LVEQNB_SetCoefficients                                      */
    211 /*                                                                                  */
    212 /* DESCRIPTION:                                                                     */
    213 /*  Sets the filter coefficients. This uses the type to select single or double     */
    214 /*  precision coefficients.                                                         */
    215 /*                                                                                  */
    216 /* PARAMETERS:                                                                      */
    217 /*  pInstance           Pointer to the instance                                     */
    218 /*  pParams             Initialisation parameters                                   */
    219 /*                                                                                  */
    220 /************************************************************************************/
    221 
    222 void    LVEQNB_SetCoefficients(LVEQNB_Instance_t     *pInstance)
    223 {
    224 
    225     LVM_UINT16              i;                          /* Filter band index */
    226     LVEQNB_BiquadType_en    BiquadType;                 /* Filter biquad type */
    227 
    228 
    229     /*
    230      * Set the coefficients for each band by the init function
    231      */
    232     for (i=0; i<pInstance->Params.NBands; i++)
    233     {
    234 
    235         /*
    236          * Check band type for correct initialisation method and recalculate the coefficients
    237          */
    238         BiquadType = pInstance->pBiquadType[i];
    239         switch  (BiquadType)
    240         {
    241 #ifdef BUILD_FLOAT
    242             case    LVEQNB_SinglePrecision_Float:
    243             {
    244                 PK_FLOAT_Coefs_t      Coefficients;
    245                 /*
    246                  * Calculate the single precision coefficients
    247                  */
    248                 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
    249                                        &pInstance->pBandDefinitions[i],
    250                                        &Coefficients);
    251                 /*
    252                  * Set the coefficients
    253                  */
    254                 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState_Float[i],
    255                                                    &pInstance->pEQNB_Taps_Float[i],
    256                                                    &Coefficients);
    257                 break;
    258             }
    259 #else
    260             case    LVEQNB_DoublePrecision:
    261             {
    262                 PK_C32_Coefs_t      Coefficients;
    263 
    264                 /*
    265                  * Calculate the double precision coefficients
    266                  */
    267                 LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
    268                                        &pInstance->pBandDefinitions[i],
    269                                        &Coefficients);
    270 
    271                 /*
    272                  * Set the coefficients
    273                  */
    274                 PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
    275                                                    &pInstance->pEQNB_Taps[i],
    276                                                    &Coefficients);
    277                 break;
    278             }
    279 
    280             case    LVEQNB_SinglePrecision:
    281             {
    282                 PK_C16_Coefs_t      Coefficients;
    283 
    284                 /*
    285                  * Calculate the single precision coefficients
    286                  */
    287                 LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate,
    288                                        &pInstance->pBandDefinitions[i],
    289                                        &Coefficients);
    290 
    291                 /*
    292                  * Set the coefficients
    293                  */
    294                 PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i],
    295                                                    &pInstance->pEQNB_Taps[i],
    296                                                    &Coefficients);
    297                 break;
    298             }
    299 #endif
    300             default:
    301                 break;
    302         }
    303     }
    304 
    305 }
    306 
    307 
    308 /************************************************************************************/
    309 /*                                                                                  */
    310 /* FUNCTION:            LVEQNB_ClearFilterHistory                                   */
    311 /*                                                                                  */
    312 /* DESCRIPTION:                                                                     */
    313 /*  Clears the filter data history                                                  */
    314 /*                                                                                  */
    315 /* PARAMETERS:                                                                      */
    316 /*  pInstance           Pointer to the instance                                     */
    317 /*                                                                                  */
    318 /************************************************************************************/
    319 #ifndef BUILD_FLOAT
    320 void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
    321 {
    322     LVM_INT16       *pTapAddress;
    323     LVM_INT16       NumTaps;
    324 
    325 
    326     pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps;
    327     NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16));
    328 
    329     if (NumTaps != 0)
    330     {
    331         LoadConst_16(0,                                 /* Clear the history, value 0 */
    332                      pTapAddress,                       /* Destination */
    333                      NumTaps);                          /* Number of words */
    334     }
    335 }
    336 #else
    337 void    LVEQNB_ClearFilterHistory(LVEQNB_Instance_t     *pInstance)
    338 {
    339     LVM_FLOAT       *pTapAddress;
    340     LVM_INT16       NumTaps;
    341 
    342     pTapAddress = (LVM_FLOAT *)pInstance->pEQNB_Taps_Float;
    343     NumTaps     = (LVM_INT16)((pInstance->Capabilities.MaxBands * \
    344                                     sizeof(Biquad_2I_Order2_FLOAT_Taps_t)) / sizeof(LVM_FLOAT));
    345 
    346     if (NumTaps != 0)
    347     {
    348         LoadConst_Float(0,                                 /* Clear the history, value 0 */
    349                         pTapAddress,                       /* Destination */
    350                         NumTaps);                          /* Number of words */
    351     }
    352 }
    353 #endif
    354 /****************************************************************************************/
    355 /*                                                                                      */
    356 /* FUNCTION:                LVEQNB_Control                                              */
    357 /*                                                                                      */
    358 /* DESCRIPTION:                                                                         */
    359 /*  Sets or changes the LifeVibes module parameters.                                    */
    360 /*                                                                                      */
    361 /* PARAMETERS:                                                                          */
    362 /*  hInstance               Instance handle                                             */
    363 /*  pParams                 Pointer to a parameter structure                            */
    364 /*                                                                                      */
    365 /* RETURNS:                                                                             */
    366 /*  LVEQNB_Success          Always succeeds                                             */
    367 /*  LVEQNB_NULLADDRESS      Instance or pParams  is NULL pointer                        */
    368 /*  LVEQNB_NULLADDRESS      NULL address for the equaliser filter definitions and the   */
    369 /*                          number of bands is non-zero                                 */
    370 /*                                                                                      */
    371 /* NOTES:                                                                               */
    372 /*  1.  This function may be interrupted by the LVEQNB_Process function                 */
    373 /*                                                                                      */
    374 /****************************************************************************************/
    375 
    376 LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t        hInstance,
    377                                       LVEQNB_Params_t        *pParams)
    378 {
    379 
    380     LVEQNB_Instance_t    *pInstance = (LVEQNB_Instance_t  *)hInstance;
    381     LVM_INT16            bChange    = LVM_FALSE;
    382     LVM_INT16            i = 0;
    383     LVEQNB_Mode_en       OperatingModeSave ;
    384 
    385     /*
    386      * Check for error conditions
    387      */
    388     if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
    389     {
    390         return LVEQNB_NULLADDRESS;
    391     }
    392 
    393     if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL))
    394     {
    395         return LVEQNB_NULLADDRESS;
    396     }
    397 
    398     OperatingModeSave = pInstance->Params.OperatingMode;
    399 
    400     /* Set the alpha factor of the mixer */
    401     if (pParams->SampleRate != pInstance->Params.SampleRate)
    402     {
    403         LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
    404         LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
    405     }
    406 
    407 
    408     if( (pInstance->Params.NBands            !=  pParams->NBands          ) ||
    409         (pInstance->Params.OperatingMode     !=  pParams->OperatingMode   ) ||
    410         (pInstance->Params.pBandDefinition   !=  pParams->pBandDefinition ) ||
    411         (pInstance->Params.SampleRate        !=  pParams->SampleRate      ) ||
    412         (pInstance->Params.SourceFormat      !=  pParams->SourceFormat    ))
    413     {
    414 
    415         bChange = LVM_TRUE;
    416     }
    417     else
    418     {
    419         for(i = 0; i < pParams->NBands; i++)
    420         {
    421 
    422             if((pInstance->pBandDefinitions[i].Frequency  != pParams->pBandDefinition[i].Frequency )||
    423                 (pInstance->pBandDefinitions[i].Gain       != pParams->pBandDefinition[i].Gain      )||
    424                 (pInstance->pBandDefinitions[i].QFactor    != pParams->pBandDefinition[i].QFactor   ))
    425             {
    426 
    427                 bChange = LVM_TRUE;
    428             }
    429         }
    430     }
    431 
    432 
    433     // During operating mode transition, there is a race condition where the mode
    434     // is still LVEQNB_ON, but the effect is considered disabled in the upper layers.
    435     // modeChange handles this special race condition.
    436     const int /* bool */ modeChange = pParams->OperatingMode != OperatingModeSave
    437             || (OperatingModeSave == LVEQNB_ON
    438                     && pInstance->bInOperatingModeTransition
    439                     && LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0);
    440 
    441     if (bChange || modeChange) {
    442 
    443         /*
    444          * If the sample rate has changed clear the history
    445          */
    446         if (pInstance->Params.SampleRate != pParams->SampleRate)
    447         {
    448             LVEQNB_ClearFilterHistory(pInstance);           /* Clear the history */
    449         }
    450 
    451         /*
    452          * Update the instance parameters
    453          */
    454         pInstance->Params = *pParams;
    455 
    456 
    457         /*
    458          * Reset the filters except if the algo is switched off
    459          */
    460         if(pParams->OperatingMode != LVEQNB_BYPASS){
    461             /*
    462              * Reset the filters as all parameters could have changed
    463              */
    464             LVEQNB_SetFilters(pInstance,                        /* Instance pointer */
    465                               pParams);                         /* New parameters */
    466 
    467             /*
    468              * Update the filters
    469              */
    470             LVEQNB_SetCoefficients(pInstance);                  /* Instance pointer */
    471         }
    472 
    473         if (modeChange) {
    474             if(pParams->OperatingMode == LVEQNB_ON)
    475             {
    476 #ifdef BUILD_FLOAT
    477                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 1.0f);
    478                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 0.0f);
    479 #else
    480                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16);
    481                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0);
    482 #endif
    483                 pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
    484                 pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
    485             }
    486             else
    487             {
    488                 /* Stay on the ON operating mode until the transition is done */
    489                 // This may introduce a state race condition if the effect is enabled again
    490                 // while in transition.  This is fixed in the modeChange logic.
    491                 pInstance->Params.OperatingMode = LVEQNB_ON;
    492 #ifdef BUILD_FLOAT
    493                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0], 0.0f);
    494                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1], 1.0f);
    495 #else
    496                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0);
    497                 LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16);
    498 #endif
    499                 pInstance->BypassMixer.MixerStream[0].CallbackSet        = 1;
    500                 pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
    501             }
    502             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
    503             LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2);
    504             pInstance->bInOperatingModeTransition = LVM_TRUE;
    505         }
    506 
    507     }
    508     return(LVEQNB_SUCCESS);
    509 }
    510 
    511 
    512 /****************************************************************************************/
    513 /*                                                                                      */
    514 /* FUNCTION:                LVEQNB_BypassMixerCallBack                                  */
    515 /*                                                                                      */
    516 /* DESCRIPTION:                                                                         */
    517 /*  CallBack function of the mixer                                                      */
    518 /*  transition                                                                          */
    519 /*                                                                                      */
    520 /****************************************************************************************/
    521 LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance,
    522                                       void *pGeneralPurpose,
    523                                       LVM_INT16 CallbackParam)
    524 {
    525     LVEQNB_Instance_t      *pInstance =(LVEQNB_Instance_t  *)hInstance;
    526     LVM_Callback            CallBack  = pInstance->Capabilities.CallBack;
    527 
    528     (void) pGeneralPurpose;
    529 
    530      /*
    531       * Send an ALGOFF event if the ON->OFF switch transition is finished
    532       */
    533 #ifdef BUILD_FLOAT
    534     if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0) &&
    535        (CallbackParam == 0)){
    536 #else
    537     if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) &&
    538        (CallbackParam == 0)){
    539 #endif
    540         pInstance->Params.OperatingMode = LVEQNB_BYPASS;
    541         if (CallBack != LVM_NULL){
    542             CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF);
    543         }
    544     }
    545 
    546     /*
    547      *  Exit transition state
    548      */
    549     pInstance->bInOperatingModeTransition = LVM_FALSE;
    550 
    551     return 1;
    552 }
    553