diff options
Diffstat (limited to 'media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c')
-rwxr-xr-x | media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c | 501 |
1 files changed, 501 insertions, 0 deletions
diff --git a/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c new file mode 100755 index 0000000..88f6fb0 --- /dev/null +++ b/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c @@ -0,0 +1,501 @@ +/* + * 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. + */ + +/********************************************************************************** + + $Author: nxp007753 $ + $Revision: 1223 $ + $Date: 2010-07-15 14:27:01 +0200 (Thu, 15 Jul 2010) $ + +***********************************************************************************/ + +/****************************************************************************************/ +/* */ +/* Includes */ +/* */ +/****************************************************************************************/ + +#include "LVEQNB.h" +#include "LVEQNB_Private.h" +#include "VectorArithmetic.h" +#include "BIQUAD.h" + + +/****************************************************************************************/ +/* */ +/* Defines */ +/* */ +/****************************************************************************************/ + +#define LOW_FREQ 298 /* 32768/110 for low test frequency */ +#define HIGH_FREQ 386 /* 32768/85 for high test frequency */ + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_GetParameters */ +/* */ +/* DESCRIPTION: */ +/* Request the N-Band equaliser parameters. The current parameter set is returned via */ +/* the parameter pointer. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to an empty parameter structure */ +/* */ +/* RETURNS: */ +/* LVEQNB_SUCCESS Succeeds */ +/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_GetParameters(LVEQNB_Handle_t hInstance, + LVEQNB_Params_t *pParams) +{ + + LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; + + /* + * Check for error conditions + */ + if((hInstance == LVM_NULL) || (pParams == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + *pParams = pInstance->Params; + + return(LVEQNB_SUCCESS); +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_GetCapabilities */ +/* */ +/* DESCRIPTION: */ +/* Get the N-Band equaliser capabilities. The current capabilities are returned */ +/* via the pointer. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pCapabilities Pointer to an empty capability structure */ +/* */ +/* RETURNS: */ +/* LVEQNB_Success Succeeds */ +/* LVEQNB_NULLADDRESS hInstance or pCapabilities is NULL */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_GetCapabilities(LVEQNB_Handle_t hInstance, + LVEQNB_Capabilities_t *pCapabilities) +{ + + LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; + + if((hInstance == LVM_NULL) || (pCapabilities == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + *pCapabilities = pInstance->Capabilities; + + return(LVEQNB_SUCCESS); +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_SetFilters */ +/* */ +/* DESCRIPTION: */ +/* Sets the filter type based on the definition. */ +/* */ +/* PARAMETERS: */ +/* pInstance Pointer to the instance */ +/* pParams Initialisation parameters */ +/* */ +/* RETURNS: */ +/* void Nothing */ +/* */ +/* NOTES: */ +/* 1. To select the biquad type the follow rules are applied: */ +/* Double precision if (fc <= fs/110) */ +/* Double precision if (fs/110 < fc < fs/85) & (Q>3) */ +/* Single precision otherwise */ +/* */ +/************************************************************************************/ + +void LVEQNB_SetFilters(LVEQNB_Instance_t *pInstance, + LVEQNB_Params_t *pParams) +{ + + extern const LVM_UINT16 LVEQNB_SampleRateTab[]; /* Sample rate table */ + LVM_UINT16 i; /* Filter band index */ + LVM_UINT32 fs = (LVM_UINT32)LVEQNB_SampleRateTab[(LVM_UINT16)pParams->SampleRate]; /* Sample rate */ + LVM_UINT32 fc; /* Filter centre frequency */ + LVM_INT16 QFactor; /* Filter Q factor */ + + + pInstance->NBands = pParams->NBands; + + for (i=0; i<pParams->NBands; i++) + { + /* + * Get the filter settings + */ + fc = (LVM_UINT32)pParams->pBandDefinition[i].Frequency; /* Get the band centre frequency */ + QFactor = (LVM_INT16)pParams->pBandDefinition[i].QFactor; /* Get the band Q factor */ + + + /* + * For each filter set the type of biquad required + */ + pInstance->pBiquadType[i] = LVEQNB_SinglePrecision; /* Default to single precision */ + if ((fc << 15) <= (LOW_FREQ * fs)) + { + /* + * fc <= fs/110 + */ + pInstance->pBiquadType[i] = LVEQNB_DoublePrecision; + } + else if (((fc << 15) <= (HIGH_FREQ * fs)) && (QFactor > 300)) + { + /* + * (fs/110 < fc < fs/85) & (Q>3) + */ + pInstance->pBiquadType[i] = LVEQNB_DoublePrecision; + } + + + /* + * Check for out of range frequencies + */ + if (fc > (fs >> 1)) + { + pInstance->pBiquadType[i] = LVEQNB_OutOfRange; + } + + + /* + * Copy the filter definition to persistant memory + */ + pInstance->pBandDefinitions[i] = pParams->pBandDefinition[i]; + + } +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_SetCoefficients */ +/* */ +/* DESCRIPTION: */ +/* Sets the filter coefficients. This uses the type to select single or double */ +/* precision coefficients. */ +/* */ +/* PARAMETERS: */ +/* pInstance Pointer to the instance */ +/* pParams Initialisation parameters */ +/* */ +/************************************************************************************/ + +void LVEQNB_SetCoefficients(LVEQNB_Instance_t *pInstance) +{ + + LVM_UINT16 i; /* Filter band index */ + LVEQNB_BiquadType_en BiquadType; /* Filter biquad type */ + + + /* + * Set the coefficients for each band by the init function + */ + for (i=0; i<pInstance->Params.NBands; i++) + { + + /* + * Check band type for correct initialisation method and recalculate the coefficients + */ + BiquadType = pInstance->pBiquadType[i]; + switch (BiquadType) + { + case LVEQNB_DoublePrecision: + { + PK_C32_Coefs_t Coefficients; + + /* + * Calculate the double precision coefficients + */ + LVEQNB_DoublePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate, + &pInstance->pBandDefinitions[i], + &Coefficients); + + /* + * Set the coefficients + */ + PK_2I_D32F32CllGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i], + &pInstance->pEQNB_Taps[i], + &Coefficients); + break; + } + + case LVEQNB_SinglePrecision: + { + PK_C16_Coefs_t Coefficients; + + /* + * Calculate the single precision coefficients + */ + LVEQNB_SinglePrecCoefs((LVM_UINT16)pInstance->Params.SampleRate, + &pInstance->pBandDefinitions[i], + &Coefficients); + + /* + * Set the coefficients + */ + PK_2I_D32F32CssGss_TRC_WRA_01_Init(&pInstance->pEQNB_FilterState[i], + &pInstance->pEQNB_Taps[i], + &Coefficients); + break; + } + default: + break; + } + } + +} + + +/************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_ClearFilterHistory */ +/* */ +/* DESCRIPTION: */ +/* Clears the filter data history */ +/* */ +/* PARAMETERS: */ +/* pInstance Pointer to the instance */ +/* */ +/************************************************************************************/ + +void LVEQNB_ClearFilterHistory(LVEQNB_Instance_t *pInstance) +{ + LVM_INT16 *pTapAddress; + LVM_INT16 NumTaps; + + + pTapAddress = (LVM_INT16 *)pInstance->pEQNB_Taps; + NumTaps = (LVM_INT16)((pInstance->Capabilities.MaxBands * sizeof(Biquad_2I_Order2_Taps_t))/sizeof(LVM_INT16)); + + if (NumTaps != 0) + { + LoadConst_16(0, /* Clear the history, value 0 */ + pTapAddress, /* Destination */ + NumTaps); /* Number of words */ + } +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_Control */ +/* */ +/* DESCRIPTION: */ +/* Sets or changes the LifeVibes module parameters. */ +/* */ +/* PARAMETERS: */ +/* hInstance Instance handle */ +/* pParams Pointer to a parameter structure */ +/* */ +/* RETURNS: */ +/* LVEQNB_Success Always succeeds */ +/* LVEQNB_NULLADDRESS Instance or pParams is NULL pointer */ +/* LVEQNB_NULLADDRESS NULL address for the equaliser filter definitions and the */ +/* number of bands is non-zero */ +/* */ +/* NOTES: */ +/* 1. This function may be interrupted by the LVEQNB_Process function */ +/* */ +/****************************************************************************************/ + +LVEQNB_ReturnStatus_en LVEQNB_Control(LVEQNB_Handle_t hInstance, + LVEQNB_Params_t *pParams) +{ + + LVEQNB_Instance_t *pInstance = (LVEQNB_Instance_t *)hInstance; + LVM_INT16 bChange = LVM_FALSE; + LVM_INT16 i = 0; + LVEQNB_Mode_en OperatingModeSave ; + + /* + * Check for error conditions + */ + if((hInstance == LVM_NULL) || (pParams == LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + if((pParams->NBands !=0) && (pParams->pBandDefinition==LVM_NULL)) + { + return LVEQNB_NULLADDRESS; + } + + OperatingModeSave = pInstance->Params.OperatingMode; + + /* Set the alpha factor of the mixer */ + if (pParams->SampleRate != pInstance->Params.SampleRate) + { + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + } + + + if( (pInstance->Params.NBands != pParams->NBands ) || + (pInstance->Params.OperatingMode != pParams->OperatingMode ) || + (pInstance->Params.pBandDefinition != pParams->pBandDefinition ) || + (pInstance->Params.SampleRate != pParams->SampleRate ) || + (pInstance->Params.SourceFormat != pParams->SourceFormat )) + { + + bChange = LVM_TRUE; + } + else + { + for(i = 0; i < pParams->NBands; i++) + { + + if((pInstance->pBandDefinitions[i].Frequency != pParams->pBandDefinition[i].Frequency )|| + (pInstance->pBandDefinitions[i].Gain != pParams->pBandDefinition[i].Gain )|| + (pInstance->pBandDefinitions[i].QFactor != pParams->pBandDefinition[i].QFactor )) + { + + bChange = LVM_TRUE; + } + } + } + + + if(bChange){ + + /* + * If the sample rate has changed clear the history + */ + if (pInstance->Params.SampleRate != pParams->SampleRate) + { + LVEQNB_ClearFilterHistory(pInstance); /* Clear the history */ + } + + /* + * Update the instance parameters + */ + pInstance->Params = *pParams; + + + /* + * Reset the filters except if the algo is switched off + */ + if(pParams->OperatingMode != LVEQNB_BYPASS){ + /* + * Reset the filters as all parameters could have changed + */ + LVEQNB_SetFilters(pInstance, /* Instance pointer */ + pParams); /* New parameters */ + + /* + * Update the filters + */ + LVEQNB_SetCoefficients(pInstance); /* Instance pointer */ + } + + if(pParams->OperatingMode != OperatingModeSave) + { + if(pParams->OperatingMode == LVEQNB_ON) + { + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],LVM_MAXINT_16); + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],0); + + pInstance->BypassMixer.MixerStream[0].CallbackSet = 1; + pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; + } + else + { + /* Stay on the ON operating mode until the transition is done */ + pInstance->Params.OperatingMode = LVEQNB_ON; + + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[0],0); + LVC_Mixer_SetTarget(&pInstance->BypassMixer.MixerStream[1],LVM_MAXINT_16); + pInstance->BypassMixer.MixerStream[0].CallbackSet = 1; + pInstance->BypassMixer.MixerStream[1].CallbackSet = 1; + } + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[0],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + LVC_Mixer_VarSlope_SetTimeConstant(&pInstance->BypassMixer.MixerStream[1],LVEQNB_BYPASS_MIXER_TC,(LVM_Fs_en)pParams->SampleRate,2); + + pInstance->bInOperatingModeTransition = LVM_TRUE; + } + + } + return(LVEQNB_SUCCESS); +} + + +/****************************************************************************************/ +/* */ +/* FUNCTION: LVEQNB_BypassMixerCallBack */ +/* */ +/* DESCRIPTION: */ +/* CallBack function of the mixer */ +/* transition */ +/* */ +/****************************************************************************************/ +LVM_INT32 LVEQNB_BypassMixerCallBack (void* hInstance, + void *pGeneralPurpose, + LVM_INT16 CallbackParam) +{ + LVEQNB_Instance_t *pInstance =(LVEQNB_Instance_t *)hInstance; + LVM_Callback CallBack = pInstance->Capabilities.CallBack; + + (void) pGeneralPurpose; + + /* + * Send an ALGOFF event if the ON->OFF switch transition is finished + */ + if((LVC_Mixer_GetTarget(&pInstance->BypassMixer.MixerStream[0]) == 0x00000000) && + (CallbackParam == 0)){ + pInstance->Params.OperatingMode = LVEQNB_BYPASS; + if (CallBack != LVM_NULL){ + CallBack(pInstance->Capabilities.pBundleInstance, LVM_NULL, ALGORITHM_EQNB_ID|LVEQNB_EVENT_ALGOFF); + } + } + + /* + * Exit transition state + */ + pInstance->bInOperatingModeTransition = LVM_FALSE; + + return 1; +} + + + + + + |