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