| /* |
| * Copyright (C) 2004-2010 NXP Software |
| * Copyright (C) 2010 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| |
| /****************************************************************************************/ |
| /* */ |
| /* Includes */ |
| /* */ |
| /****************************************************************************************/ |
| |
| #include "LVEQNB.h" |
| #include "LVEQNB_Private.h" |
| #include "InstAlloc.h" |
| #include <string.h> /* For memset */ |
| |
| /****************************************************************************************/ |
| /* */ |
| /* FUNCTION: LVEQNB_Memory */ |
| /* */ |
| /* DESCRIPTION: */ |
| /* This function is used for memory allocation and free. It can be called in */ |
| /* two ways: */ |
| /* */ |
| /* hInstance = NULL Returns the memory requirements */ |
| /* hInstance = Instance handle Returns the memory requirements and */ |
| /* allocated base addresses for the instance */ |
| /* */ |
| /* When this function is called for memory allocation (hInstance=NULL) the memory */ |
| /* base address pointers are NULL on return. */ |
| /* */ |
| /* When the function is called for free (hInstance = Instance Handle) the memory */ |
| /* table returns the allocated memory and base addresses used during initialisation. */ |
| /* */ |
| /* PARAMETERS: */ |
| /* hInstance Instance Handle */ |
| /* pMemoryTable Pointer to an empty memory definition table */ |
| /* pCapabilities Pointer to the instance capabilities */ |
| /* */ |
| /* RETURNS: */ |
| /* LVEQNB_SUCCESS Succeeded */ |
| /* LVEQNB_NULLADDRESS When any of pMemoryTable and pCapabilities is NULL address */ |
| /* */ |
| /* NOTES: */ |
| /* 1. This function may be interrupted by the LVEQNB_Process function */ |
| /* */ |
| /****************************************************************************************/ |
| |
| LVEQNB_ReturnStatus_en LVEQNB_Memory(LVEQNB_Handle_t hInstance, |
| LVEQNB_MemTab_t *pMemoryTable, |
| LVEQNB_Capabilities_t *pCapabilities) |
| { |
| |
| INST_ALLOC AllocMem; |
| LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; |
| |
| |
| if((pMemoryTable == LVM_NULL)|| (pCapabilities == LVM_NULL)) |
| { |
| return LVEQNB_NULLADDRESS; |
| } |
| |
| |
| /* |
| * Fill in the memory table |
| */ |
| if (hInstance == LVM_NULL) |
| { |
| /* |
| * Instance memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| LVM_NULL); |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| sizeof(LVEQNB_Instance_t)); |
| pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Size = InstAlloc_GetTotal(&AllocMem); |
| pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Alignment = LVEQNB_INSTANCE_ALIGN; |
| pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].Type = LVEQNB_PERSISTENT; |
| pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL; |
| |
| |
| /* |
| * Persistant data memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| LVM_NULL); |
| #ifdef BUILD_FLOAT |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| sizeof(Biquad_2I_Order2_FLOAT_Taps_t)); |
| InstAlloc_AddMember(&AllocMem, /* High pass filter */ |
| sizeof(Biquad_2I_Order2_FLOAT_Taps_t)); |
| /* Equaliser Biquad Taps */ |
| InstAlloc_AddMember(&AllocMem, |
| (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t))); |
| /* Filter definitions */ |
| InstAlloc_AddMember(&AllocMem, |
| (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t))); |
| /* Biquad types */ |
| InstAlloc_AddMember(&AllocMem, |
| (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en))); |
| #else |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| sizeof(Biquad_2I_Order2_Taps_t)); |
| InstAlloc_AddMember(&AllocMem, /* High pass filter */ |
| sizeof(Biquad_2I_Order2_Taps_t)); |
| InstAlloc_AddMember(&AllocMem, |
| (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t))); /* Equaliser Biquad Taps */ |
| InstAlloc_AddMember(&AllocMem, |
| (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t))); /* Filter definitions */ |
| InstAlloc_AddMember(&AllocMem, |
| (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en))); /* Biquad types */ |
| #endif |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Size = InstAlloc_GetTotal(&AllocMem); |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Alignment = LVEQNB_DATA_ALIGN; |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].Type = LVEQNB_PERSISTENT_DATA; |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL; |
| |
| /* |
| * Persistant coefficient memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| LVM_NULL); |
| #ifdef BUILD_FLOAT |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| sizeof(Biquad_FLOAT_Instance_t)); |
| InstAlloc_AddMember(&AllocMem, /* High pass filter */ |
| sizeof(Biquad_FLOAT_Instance_t)); |
| /* Equaliser Biquad Instance */ |
| InstAlloc_AddMember(&AllocMem, |
| pCapabilities->MaxBands * sizeof(Biquad_FLOAT_Instance_t)); |
| #else |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| sizeof(Biquad_Instance_t)); |
| InstAlloc_AddMember(&AllocMem, /* High pass filter */ |
| sizeof(Biquad_Instance_t)); |
| InstAlloc_AddMember(&AllocMem, |
| pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */ |
| #endif |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Size = InstAlloc_GetTotal(&AllocMem); |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Alignment = LVEQNB_COEF_ALIGN; |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].Type = LVEQNB_PERSISTENT_COEF; |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL; |
| |
| /* |
| * Scratch memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| LVM_NULL); |
| #ifdef BUILD_FLOAT |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| LVEQNB_SCRATCHBUFFERS * sizeof(LVM_FLOAT) * \ |
| pCapabilities->MaxBlockSize); |
| #else |
| InstAlloc_AddMember(&AllocMem, /* Low pass filter */ |
| LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize); |
| #endif |
| pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Size = InstAlloc_GetTotal(&AllocMem); |
| pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Alignment = LVEQNB_SCRATCH_ALIGN; |
| pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].Type = LVEQNB_SCRATCH; |
| pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL; |
| } |
| else |
| { |
| /* Read back memory allocation table */ |
| *pMemoryTable = pInstance->MemoryTable; |
| } |
| |
| return(LVEQNB_SUCCESS); |
| } |
| |
| |
| /****************************************************************************************/ |
| /* */ |
| /* FUNCTION: LVEQNB_Init */ |
| /* */ |
| /* DESCRIPTION: */ |
| /* Create and initialisation function for the N-Band equaliser module */ |
| /* */ |
| /* This function can be used to create an algorithm instance by calling with */ |
| /* hInstance set to NULL. In this case the algorithm returns the new instance */ |
| /* handle. */ |
| /* */ |
| /* This function can be used to force a full re-initialisation of the algorithm */ |
| /* by calling with hInstance = Instance Handle. In this case the memory table */ |
| /* should be correct for the instance, this can be ensured by calling the function */ |
| /* DBE_Memory before calling this function. */ |
| /* */ |
| /* PARAMETERS: */ |
| /* hInstance Instance handle */ |
| /* pMemoryTable Pointer to the memory definition table */ |
| /* pCapabilities Pointer to the instance capabilities */ |
| /* */ |
| /* RETURNS: */ |
| /* LVEQNB_SUCCESS Initialisation succeeded */ |
| /* LVEQNB_NULLADDRESS When pCapabilities or pMemoryTableis or phInstance are NULL */ |
| /* LVEQNB_NULLADDRESS One or more of the memory regions has a NULL base address */ |
| /* pointer for a memory region with a non-zero size. */ |
| /* */ |
| /* NOTES: */ |
| /* 1. The instance handle is the pointer to the base address of the first memory */ |
| /* region. */ |
| /* 2. This function must not be interrupted by the LVEQNB_Process function */ |
| /* */ |
| /****************************************************************************************/ |
| |
| LVEQNB_ReturnStatus_en LVEQNB_Init(LVEQNB_Handle_t *phInstance, |
| LVEQNB_MemTab_t *pMemoryTable, |
| LVEQNB_Capabilities_t *pCapabilities) |
| { |
| |
| LVEQNB_Instance_t *pInstance; |
| LVM_UINT32 MemSize; |
| INST_ALLOC AllocMem; |
| LVM_INT32 i; |
| |
| /* |
| * Check for NULL pointers |
| */ |
| if((phInstance == LVM_NULL) || (pMemoryTable == LVM_NULL) || (pCapabilities == LVM_NULL)) |
| { |
| return LVEQNB_NULLADDRESS; |
| } |
| |
| /* |
| * Check the memory table for NULL pointers |
| */ |
| for (i = 0; i < LVEQNB_NR_MEMORY_REGIONS; i++) |
| { |
| if (pMemoryTable->Region[i].Size!=0) |
| { |
| if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL) |
| { |
| return(LVEQNB_NULLADDRESS); |
| } |
| } |
| } |
| |
| /* |
| * Set the instance handle if not already initialised |
| */ |
| |
| InstAlloc_Init(&AllocMem, pMemoryTable->Region[LVEQNB_MEMREGION_INSTANCE].pBaseAddress); |
| |
| if (*phInstance == LVM_NULL) |
| { |
| *phInstance = InstAlloc_AddMember(&AllocMem, sizeof(LVEQNB_Instance_t)); |
| } |
| pInstance =(LVEQNB_Instance_t *)*phInstance; |
| |
| |
| |
| /* |
| * Save the memory table in the instance structure |
| */ |
| pInstance->Capabilities = *pCapabilities; |
| |
| |
| /* |
| * Save the memory table in the instance structure and |
| * set the structure pointers |
| */ |
| pInstance->MemoryTable = *pMemoryTable; |
| |
| /* |
| * Allocate coefficient memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_COEF].pBaseAddress); |
| |
| #ifdef BUILD_FLOAT |
| /* Equaliser Biquad Instance */ |
| pInstance->pEQNB_FilterState_Float = InstAlloc_AddMember(&AllocMem, |
| pCapabilities->MaxBands * \ |
| sizeof(Biquad_FLOAT_Instance_t)); |
| #else |
| pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem, |
| pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */ |
| #endif |
| |
| |
| |
| /* |
| * Allocate data memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress); |
| |
| #ifdef BUILD_FLOAT |
| MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_FLOAT_Taps_t)); |
| pInstance->pEQNB_Taps_Float = (Biquad_2I_Order2_FLOAT_Taps_t *)InstAlloc_AddMember(&AllocMem, |
| MemSize); |
| #else |
| MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t)); |
| pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem, |
| MemSize); |
| #endif |
| MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BandDef_t)); |
| pInstance->pBandDefinitions = (LVEQNB_BandDef_t *)InstAlloc_AddMember(&AllocMem, |
| MemSize); |
| // clear all the bands, setting their gain to 0, otherwise when applying new params, |
| // it will compare against uninitialized values |
| memset(pInstance->pBandDefinitions, 0, MemSize); |
| MemSize = (pCapabilities->MaxBands * sizeof(LVEQNB_BiquadType_en)); |
| pInstance->pBiquadType = (LVEQNB_BiquadType_en *)InstAlloc_AddMember(&AllocMem, |
| MemSize); |
| |
| |
| /* |
| * Internally map, structure and allign scratch memory |
| */ |
| InstAlloc_Init(&AllocMem, |
| pMemoryTable->Region[LVEQNB_MEMREGION_SCRATCH].pBaseAddress); |
| |
| #ifdef BUILD_FLOAT |
| pInstance->pFastTemporary = (LVM_FLOAT *)InstAlloc_AddMember(&AllocMem, |
| sizeof(LVM_FLOAT)); |
| #else |
| pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem, |
| sizeof(LVM_INT16)); |
| #endif |
| |
| /* |
| * Update the instance parameters |
| */ |
| pInstance->Params.NBands = 0; |
| pInstance->Params.OperatingMode = LVEQNB_BYPASS; |
| pInstance->Params.pBandDefinition = LVM_NULL; |
| pInstance->Params.SampleRate = LVEQNB_FS_8000; |
| pInstance->Params.SourceFormat = LVEQNB_STEREO; |
| |
| /* |
| * Initialise the filters |
| */ |
| LVEQNB_SetFilters(pInstance, /* Set the filter types */ |
| &pInstance->Params); |
| |
| LVEQNB_SetCoefficients(pInstance); /* Set the filter coefficients */ |
| |
| LVEQNB_ClearFilterHistory(pInstance); /* Clear the filter history */ |
| |
| /* |
| * Initialise the bypass variables |
| */ |
| pInstance->BypassMixer.MixerStream[0].CallbackSet = 0; |
| pInstance->BypassMixer.MixerStream[0].CallbackParam = 0; |
| pInstance->BypassMixer.MixerStream[0].pCallbackHandle = (void*)pInstance; |
| pInstance->BypassMixer.MixerStream[0].pCallBack = LVEQNB_BypassMixerCallBack; |
| |
| LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[0],0,0); |
| LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],0,LVM_FS_8000,2); |
| |
| |
| pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; |
| pInstance->BypassMixer.MixerStream[1].CallbackParam = 0; |
| pInstance->BypassMixer.MixerStream[1].pCallbackHandle = LVM_NULL; |
| pInstance->BypassMixer.MixerStream[1].pCallBack = LVM_NULL; |
| #ifdef BUILD_FLOAT |
| LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1], 0, 1.0f); |
| LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1], 0, LVM_FS_8000, 2); |
| #else |
| LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16); |
| LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2); |
| #endif |
| |
| pInstance->bInOperatingModeTransition = LVM_FALSE; |
| |
| return(LVEQNB_SUCCESS); |
| } |
| |