blob: 35e5bc82aca5bbdfae70e91d5005f4f8c2fe89c5 [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 "LVDBE.h"
#include "LVDBE_Private.h"
/****************************************************************************************/
/* */
/* FUNCTION: LVDBE_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: */
/* LVDBE_SUCCESS Succeeded */
/* */
/* NOTES: */
/* 1. This function may be interrupted by the LVDBE_Process function */
/* */
/****************************************************************************************/
LVDBE_ReturnStatus_en LVDBE_Memory(LVDBE_Handle_t hInstance,
LVDBE_MemTab_t *pMemoryTable,
LVDBE_Capabilities_t *pCapabilities)
{
LVM_UINT32 ScratchSize;
LVDBE_Instance_t *pInstance = (LVDBE_Instance_t *)hInstance;
/*
* Fill in the memory table
*/
if (hInstance == LVM_NULL)
{
/*
* Instance memory
*/
pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Size = sizeof(LVDBE_Instance_t);
pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Alignment = LVDBE_INSTANCE_ALIGN;
pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].Type = LVDBE_PERSISTENT;
pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
/*
* Data memory
*/
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Size = sizeof(LVDBE_Data_t);
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Alignment = LVDBE_PERSISTENT_DATA_ALIGN;
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].Type = LVDBE_PERSISTENT_DATA;
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
/*
* Coef memory
*/
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Size = sizeof(LVDBE_Coef_t);
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Alignment = LVDBE_PERSISTENT_COEF_ALIGN;
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].Type = LVDBE_PERSISTENT_COEF;
pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
/*
* Scratch memory
*/
ScratchSize = (LVM_UINT32)(LVDBE_SCRATCHBUFFERS_INPLACE*sizeof(LVM_INT16)*pCapabilities->MaxBlockSize);
pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Size = ScratchSize;
pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Alignment = LVDBE_SCRATCH_ALIGN;
pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].Type = LVDBE_SCRATCH;
pMemoryTable->Region[LVDBE_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
}
else
{
/* Read back memory allocation table */
*pMemoryTable = pInstance->MemoryTable;
}
return(LVDBE_SUCCESS);
}
/****************************************************************************************/
/* */
/* FUNCTION: LVDBE_Init */
/* */
/* DESCRIPTION: */
/* Create and initialisation function for the Dynamic Bass Enhancement 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: */
/* LVDBE_SUCCESS Initialisation succeeded */
/* LVDBE_ALIGNMENTERROR Instance or scratch memory on incorrect alignment */
/* LVDBE_NULLADDRESS Instance or scratch memory has a NULL pointer */
/* */
/* 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 LVDBE_Process function */
/* */
/****************************************************************************************/
LVDBE_ReturnStatus_en LVDBE_Init(LVDBE_Handle_t *phInstance,
LVDBE_MemTab_t *pMemoryTable,
LVDBE_Capabilities_t *pCapabilities)
{
LVDBE_Instance_t *pInstance;
LVMixer3_1St_st *pMixer_Instance;
LVMixer3_2St_st *pBypassMixer_Instance;
LVM_INT16 i;
LVM_INT32 MixGain;
/*
* Set the instance handle if not already initialised
*/
if (*phInstance == LVM_NULL)
{
*phInstance = (LVDBE_Handle_t)pMemoryTable->Region[LVDBE_MEMREGION_INSTANCE].pBaseAddress;
}
pInstance =(LVDBE_Instance_t *)*phInstance;
/*
* Check the memory table for NULL pointers and incorrectly aligned data
*/
for (i=0; i<LVDBE_NR_MEMORY_REGIONS; i++)
{
if (pMemoryTable->Region[i].Size!=0)
{
if (pMemoryTable->Region[i].pBaseAddress==LVM_NULL)
{
return(LVDBE_NULLADDRESS);
}
if (((uintptr_t)pMemoryTable->Region[i].pBaseAddress % pMemoryTable->Region[i].Alignment)!=0){
return(LVDBE_ALIGNMENTERROR);
}
}
}
/*
* Save the memory table in the instance structure
*/
pInstance->Capabilities = *pCapabilities;
/*
* Save the memory table in the instance structure
*/
pInstance->MemoryTable = *pMemoryTable;
/*
* Set the default instance parameters
*/
pInstance->Params.CentreFrequency = LVDBE_CENTRE_55HZ;
pInstance->Params.EffectLevel = 0;
pInstance->Params.HeadroomdB = 0;
pInstance->Params.HPFSelect = LVDBE_HPF_OFF;
pInstance->Params.OperatingMode = LVDBE_OFF;
pInstance->Params.SampleRate = LVDBE_FS_8000;
pInstance->Params.VolumeControl = LVDBE_VOLUME_OFF;
pInstance->Params.VolumedB = 0;
/*
* Set pointer to data and coef memory
*/
pInstance->pData = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_DATA].pBaseAddress;
pInstance->pCoef = pMemoryTable->Region[LVDBE_MEMREGION_PERSISTENT_COEF].pBaseAddress;
/*
* Initialise the filters
*/
LVDBE_SetFilters(pInstance, /* Set the filter taps and coefficients */
&pInstance->Params);
/*
* Initialise the AGC
*/
LVDBE_SetAGC(pInstance, /* Set the AGC gain */
&pInstance->Params);
pInstance->pData->AGCInstance.AGC_Gain = pInstance->pData->AGCInstance.AGC_MaxGain;
/* Default to the bass boost setting */
// initialize the mixer with some fixes values since otherwise LVDBE_SetVolume ends up
// reading uninitialized data
pMixer_Instance = &pInstance->pData->BypassVolume;
LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],0x00007FFF,0x00007FFF);
/*
* Initialise the volume
*/
LVDBE_SetVolume(pInstance, /* Set the Volume */
&pInstance->Params);
pInstance->pData->AGCInstance.Volume = pInstance->pData->AGCInstance.Target;
/* Initialise as the target */
MixGain = LVC_Mixer_GetTarget(&pMixer_Instance->MixerStream[0]);
LVC_Mixer_Init(&pMixer_Instance->MixerStream[0],MixGain,MixGain);
/* Configure the mixer process path */
pMixer_Instance->MixerStream[0].CallbackParam = 0;
pMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
pMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
pMixer_Instance->MixerStream[0].CallbackSet = 0;
/*
* Initialise the clicks minimisation BypassMixer
*/
pBypassMixer_Instance = &pInstance->pData->BypassMixer;
/*
* Setup the mixer gain for the processed path
*/
pBypassMixer_Instance->MixerStream[0].CallbackParam = 0;
pBypassMixer_Instance->MixerStream[0].pCallbackHandle = LVM_NULL;
pBypassMixer_Instance->MixerStream[0].pCallBack = LVM_NULL;
pBypassMixer_Instance->MixerStream[0].CallbackSet=0;
LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[0],0,0);
LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[0],
LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
/*
* Setup the mixer gain for the unprocessed path
*/
pBypassMixer_Instance->MixerStream[1].CallbackParam = 0;
pBypassMixer_Instance->MixerStream[1].pCallbackHandle = LVM_NULL;
pBypassMixer_Instance->MixerStream[1].pCallBack = LVM_NULL;
pBypassMixer_Instance->MixerStream[1].CallbackSet=0;
LVC_Mixer_Init(&pBypassMixer_Instance->MixerStream[1],0x00007FFF,0x00007FFF);
LVC_Mixer_SetTimeConstant(&pBypassMixer_Instance->MixerStream[1],
LVDBE_BYPASS_MIXER_TC,pInstance->Params.SampleRate,2);
return(LVDBE_SUCCESS);
}