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