blob: e01c1c58b19ac91bdd024f24d3371e3320a75f5f [file] [log] [blame]
/*
* 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);
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 */
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);
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 */
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);
InstAlloc_AddMember(&AllocMem, /* Low pass filter */
LVEQNB_SCRATCHBUFFERS*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
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);
pInstance->pEQNB_FilterState = InstAlloc_AddMember(&AllocMem,
pCapabilities->MaxBands * sizeof(Biquad_Instance_t)); /* Equaliser Biquad Instance */
/*
* Allocate data memory
*/
InstAlloc_Init(&AllocMem,
pMemoryTable->Region[LVEQNB_MEMREGION_PERSISTENT_DATA].pBaseAddress);
MemSize = (pCapabilities->MaxBands * sizeof(Biquad_2I_Order2_Taps_t));
pInstance->pEQNB_Taps = (Biquad_2I_Order2_Taps_t *)InstAlloc_AddMember(&AllocMem,
MemSize);
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);
pInstance->pFastTemporary = (LVM_INT16 *)InstAlloc_AddMember(&AllocMem,
sizeof(LVM_INT16));
/*
* 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;
LVC_Mixer_Init(&pInstance->BypassMixer.MixerStream[1],0,LVM_MAXINT_16);
LVC_Mixer_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],0,LVM_FS_8000,2);
pInstance->bInOperatingModeTransition = LVM_FALSE;
return(LVEQNB_SUCCESS);
}