summaryrefslogtreecommitdiffstats
path: root/media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c')
-rwxr-xr-xmedia/libeffects/lvm/lib/Eq/src/LVEQNB_Control.c501
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;
+}
+
+
+
+
+
+