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 /*                                                                                      */
     21 /*  Includes                                                                            */
     22 /*                                                                                      */
     23 /****************************************************************************************/
     24 
     25 #include "LVEQNB.h"
     26 #include "LVEQNB_Private.h"
     27 #include "InstAlloc.h"
     28 #include <string.h> /* For memset */
     29 
     30 /****************************************************************************************/
     31 /*                                                                                      */
     32 /* FUNCTION:                LVEQNB_Memory                                               */
     33 /*                                                                                      */
     34 /* DESCRIPTION:                                                                         */
     35 /*  This function is used for memory allocation and free. It can be called in           */
     36 /*  two ways:                                                                           */
     37 /*                                                                                      */
     38 /*      hInstance = NULL                Returns the memory requirements                 */
     39 /*      hInstance = Instance handle     Returns the memory requirements and             */
     40 /*                                      allocated base addresses for the instance       */
     41 /*                                                                                      */
     42 /*  When this function is called for memory allocation (hInstance=NULL) the memory      */
     43 /*  base address pointers are NULL on return.                                           */
     44 /*                                                                                      */
     45 /*  When the function is called for free (hInstance = Instance Handle) the memory       */
     46 /*  table returns the allocated memory and base addresses used during initialisation.   */
     47 /*                                                                                      */
     48 /* PARAMETERS:                                                                          */
     49 /*  hInstance               Instance Handle                                             */
     50 /*  pMemoryTable            Pointer to an empty memory definition table                 */
     51 /*  pCapabilities           Pointer to the instance capabilities                        */
     52 /*                                                                                      */
     53 /* RETURNS:                                                                             */
     54 /*  LVEQNB_SUCCESS          Succeeded                                                   */
     55 /*  LVEQNB_NULLADDRESS      When any of pMemoryTable and pCapabilities is NULL address  */
     56 /*                                                                                      */
     57 /* NOTES:                                                                               */
     58 /*  1.  This function may be interrupted by the LVEQNB_Process function                 */
     59 /*                                                                                      */
     60 /****************************************************************************************/
     61 
     62 LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t            hInstance,
     63                                      LVEQNB_MemTab_t            *pMemoryTable,
     64                                      LVEQNB_Capabilities_t      *pCapabilities)
     65 {
     66 
     67     INST_ALLOC          AllocMem;
     68     LVEQNB_Instance_t   *pInstance = (LVEQNB_Instance_t *)hInstance;
     69 
     70 
     71     if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL))
     72     {
     73         return LVEQNB_NULLADDRESS;
     74     }
     75 
     76 
     77     /*
     78      * Fill in the memory table
     79      */
     80     if (hInstance == LVM_NULL)
     81     {
     82         /*
     83          * Instance memory
     84          */
     85         InstAlloc_Init(&AllocMem,
     86                        LVM_NULL);
     87         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
     88                             sizeof(LVEQNB_Instance_t));
     89         pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size         = InstAlloc_GetTotal(&AllocMem);
     90         pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment    = LVEQNB_INSTANCE_ALIGN;
     91         pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type         = LVEQNB_PERSISTENT;
     92         pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
     93 
     94 
     95         /*
     96          * Persistant data memory
     97          */
     98         InstAlloc_Init(&AllocMem,
     99                        LVM_NULL);
    100         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
    101                             sizeof(Biquad_2I_Order2_Taps_t));
    102         InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
    103                             sizeof(Biquad_2I_Order2_Taps_t));
    104         InstAlloc_AddMember(&AllocMem,
    105                             (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */
    106         InstAlloc_AddMember(&AllocMem,
    107                             (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)));        /* Filter definitions */
    108         InstAlloc_AddMember(&AllocMem,
    109                             (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)));    /* Biquad types */
    110         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size         = InstAlloc_GetTotal(&AllocMem);
    111         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment    = LVEQNB_DATA_ALIGN;
    112         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type         = LVEQNB_PERSISTENT_DATA;
    113         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
    114 
    115         /*
    116          * Persistant coefficient memory
    117          */
    118         InstAlloc_Init(&AllocMem,
    119                        LVM_NULL);
    120         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
    121                             sizeof(Biquad_Instance_t));
    122         InstAlloc_AddMember(&AllocMem,                              /* High pass filter */
    123                             sizeof(Biquad_Instance_t));
    124         InstAlloc_AddMember(&AllocMem,
    125                             pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
    126         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size         = InstAlloc_GetTotal(&AllocMem);
    127         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment    = LVEQNB_COEF_ALIGN;
    128         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type         = LVEQNB_PERSISTENT_COEF;
    129         pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
    130 
    131         /*
    132          * Scratch memory
    133          */
    134         InstAlloc_Init(&AllocMem,
    135                        LVM_NULL);
    136         InstAlloc_AddMember(&AllocMem,                              /* Low pass filter */
    137                             LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
    138         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size              = InstAlloc_GetTotal(&AllocMem);
    139         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment         = LVEQNB_SCRATCH_ALIGN;
    140         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type              = LVEQNB_SCRATCH;
    141         pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress      = LVM_NULL;
    142     }
    143     else
    144     {
    145         /* Read back memory allocation table */
    146         *pMemoryTable = pInstance->MemoryTable;
    147     }
    148 
    149     return(LVEQNB_SUCCESS);
    150 }
    151 
    152 
    153 /****************************************************************************************/
    154 /*                                                                                      */
    155 /* FUNCTION:                LVEQNB_Init                                                 */
    156 /*                                                                                      */
    157 /* DESCRIPTION:                                                                         */
    158 /*  Create and initialisation function for the N-Band equaliser module                  */
    159 /*                                                                                      */
    160 /*  This function can be used to create an algorithm instance by calling with           */
    161 /*  hInstance set to NULL. In this case the algorithm returns the new instance          */
    162 /*  handle.                                                                             */
    163 /*                                                                                      */
    164 /*  This function can be used to force a full re-initialisation of the algorithm        */
    165 /*  by calling with hInstance = Instance Handle. In this case the memory table          */
    166 /*  should be correct for the instance, this can be ensured by calling the function     */
    167 /*  DBE_Memory before calling this function.                                            */
    168 /*                                                                                      */
    169 /* PARAMETERS:                                                                          */
    170 /*  hInstance               Instance handle                                             */
    171 /*  pMemoryTable            Pointer to the memory definition table                      */
    172 /*  pCapabilities           Pointer to the instance capabilities                        */
    173 /*                                                                                      */
    174 /* RETURNS:                                                                             */
    175 /*  LVEQNB_SUCCESS          Initialisation succeeded                                    */
    176 /*  LVEQNB_NULLADDRESS        When pCapabilities or pMemoryTableis or phInstance are NULL */
    177 /*  LVEQNB_NULLADDRESS        One or more of the memory regions has a NULL base address   */
    178 /*                          pointer for a memory region with a non-zero size.           */
    179 /*                                                                                      */
    180 /* NOTES:                                                                               */
    181 /*  1.  The instance handle is the pointer to the base address of the first memory      */
    182 /*      region.                                                                         */
    183 /*  2.  This function must not be interrupted by the LVEQNB_Process function            */
    184 /*                                                                                      */
    185 /****************************************************************************************/
    186 
    187 LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t          *phInstance,
    188                                    LVEQNB_MemTab_t          *pMemoryTable,
    189                                    LVEQNB_Capabilities_t    *pCapabilities)
    190 {
    191 
    192     LVEQNB_Instance_t   *pInstance;
    193     LVM_UINT32          MemSize;
    194     INST_ALLOC          AllocMem;
    195     LVM_INT32           i;
    196 
    197     /*
    198      * Check for NULL pointers
    199      */
    200     if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL))
    201     {
    202         return LVEQNB_NULLADDRESS;
    203     }
    204 
    205     /*
    206      * Check the memory table for NULL pointers
    207      */
    208     for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++)
    209     {
    210         if (pMemoryTable->Region[i].Size!=0)
    211         {
    212             if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
    213             {
    214                 return(LVEQNB_NULLADDRESS);
    215             }
    216         }
    217     }
    218 
    219     /*
    220      * Set the instance handle if not already initialised
    221      */
    222 
    223     InstAlloc_Init(&AllocMem,  pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress);
    224 
    225     if (*phInstance == LVM_NULL)
    226     {
    227         *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t));
    228     }
    229     pInstance =(LVEQNB_Instance_t  *)*phInstance;
    230 
    231 
    232 
    233     /*
    234      * Save the memory table in the instance structure
    235      */
    236     pInstance->Capabilities = *pCapabilities;
    237 
    238 
    239     /*
    240      * Save the memory table in the instance structure and
    241      * set the structure pointers
    242      */
    243     pInstance->MemoryTable       = *pMemoryTable;
    244 
    245     /*
    246      * Allocate coefficient memory
    247      */
    248     InstAlloc_Init(&AllocMem,
    249                    pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress);
    250 
    251     pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
    252                                                        pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
    253 
    254 
    255 
    256     /*
    257      * Allocate data memory
    258      */
    259     InstAlloc_Init(&AllocMem,
    260                    pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
    261 
    262     MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
    263     pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
    264                                                                            MemSize);
    265     MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t));
    266     pInstance->pBandDefinitions  = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem,
    267                                                                            MemSize);
    268     // clear all the bands, setting their gain to 0, otherwise when applying new params,
    269     // it will compare against uninitialized values
    270     memset(pInstance->pBandDefinitions, 0, MemSize);
    271     MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en));
    272     pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem,
    273                                                                          MemSize);
    274 
    275 
    276     /*
    277      * Internally map, structure and allign scratch memory
    278      */
    279     InstAlloc_Init(&AllocMem,
    280                    pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress);
    281 
    282     pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
    283                                                                  sizeof(LVM_INT16));
    284 
    285     /*
    286      * Update the instance parameters
    287      */
    288     pInstance->Params.NBands          = 0;
    289     pInstance->Params.OperatingMode   = LVEQNB_BYPASS;
    290     pInstance->Params.pBandDefinition = LVM_NULL;
    291     pInstance->Params.SampleRate      = LVEQNB_FS_8000;
    292     pInstance->Params.SourceFormat    = LVEQNB_STEREO;
    293 
    294     /*
    295      * Initialise the filters
    296      */
    297     LVEQNB_SetFilters(pInstance,                        /* Set the filter types */
    298                       &pInstance->Params);
    299 
    300     LVEQNB_SetCoefficients(pInstance);                  /* Set the filter coefficients */
    301 
    302     LVEQNB_ClearFilterHistory(pInstance);               /* Clear the filter history */
    303 
    304     /*
    305      * Initialise the bypass variables
    306      */
    307     pInstance->BypassMixer.MixerStream[0].CallbackSet        = 0;
    308     pInstance->BypassMixer.MixerStream[0].CallbackParam      = 0;
    309     pInstance->BypassMixer.MixerStream[0].pCallbackHandle    = (void*)pInstance;
    310     pInstance->BypassMixer.MixerStream[0].pCallBack          = LVEQNB_BypassMixerCallBack;
    311     LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0);
    312     LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2);
    313 
    314     pInstance->BypassMixer.MixerStream[1].CallbackSet        = 1;
    315     pInstance->BypassMixer.MixerStream[1].CallbackParam      = 0;
    316     pInstance->BypassMixer.MixerStream[1].pCallbackHandle    = LVM_NULL;
    317     pInstance->BypassMixer.MixerStream[1].pCallBack          = LVM_NULL;
    318     LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
    319     LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
    320 
    321     pInstance->bInOperatingModeTransition      = LVM_FALSE;
    322 
    323     return(LVEQNB_SUCCESS);
    324 }
    325 
    326