summaryrefslogtreecommitdiffstats
path: root/media/libeffects/lvm/lib/SpectrumAnalyzer/src
diff options
context:
space:
mode:
Diffstat (limited to 'media/libeffects/lvm/lib/SpectrumAnalyzer/src')
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c715
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c197
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c177
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h159
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c260
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h98
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c50
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c220
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c250
9 files changed, 2126 insertions, 0 deletions
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
new file mode 100755
index 0000000..1be8ff0
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Control.c
@@ -0,0 +1,715 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "VectorArithmetic.h"
+
+#define LOW_FREQ 298 /* 32768/110 for low test frequency */
+#define HIGH_FREQ 386 /* 32768/85 for high test frequency */
+
+LVPSA_RETURN LVPSA_SetBPFiltersType ( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams );
+
+LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams );
+
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C16_Coefs_t *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C32_Coefs_t *pCoefficients);
+
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C32_Coefs_t *pCoefficients);
+
+LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams );
+
+LVPSA_RETURN LVPSA_ClearFilterHistory( LVPSA_InstancePr_t *pInst);
+
+
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Control */
+/* */
+/* DESCRIPTION: */
+/* Give some new control parameters to the module. */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* NewParams Structure that contains the new parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Control ( pLVPSA_Handle_t hInstance,
+ LVPSA_ControlParams_t *pNewParams )
+{
+
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+ if((hInstance == LVM_NULL) || (pNewParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ if(pNewParams->Fs >= LVPSA_NR_SUPPORTED_RATE)
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ if(pNewParams->LevelDetectionSpeed >= LVPSA_NR_SUPPORTED_SPEED)
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+
+ pLVPSA_Inst->NewParams = *pNewParams;
+ pLVPSA_Inst->bControlPending = LVM_TRUE;
+
+ return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetControlParams */
+/* */
+/* DESCRIPTION: */
+/* Get the current control parameters of the module */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* pParams Pointer to an empty control structure */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetControlParams ( pLVPSA_Handle_t hInstance,
+ LVPSA_ControlParams_t *pParams )
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+ if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+ pParams->Fs = pLVPSA_Inst->CurrentParams.Fs;
+ pParams->LevelDetectionSpeed = pLVPSA_Inst->CurrentParams.LevelDetectionSpeed;
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetInitParams */
+/* */
+/* DESCRIPTION: */
+/* Get the initialization parameters of the module */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* pParams Pointer to an empty control structure */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetInitParams ( pLVPSA_Handle_t hInstance,
+ LVPSA_InitParams_t *pParams )
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+ if((hInstance == LVM_NULL) || (pParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+ pParams->SpectralDataBufferDuration = pLVPSA_Inst->SpectralDataBufferDuration;
+ pParams->MaxInputBlockSize = pLVPSA_Inst->MaxInputBlockSize;
+ pParams->nBands = pLVPSA_Inst->nBands;
+ pParams->pFiltersParams = pLVPSA_Inst->pFiltersParams;
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Reinitialize some parameters and changes filters' coefficients if */
+/* some control parameters have changed. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t *pInst)
+{
+ LVM_UINT16 ii;
+ LVM_UINT16 Freq;
+ LVPSA_ControlParams_t Params;
+ extern LVM_INT16 LVPSA_nSamplesBufferUpdate[];
+ extern LVM_UINT16 LVPSA_SampleRateTab[];
+ extern LVM_UINT16 LVPSA_DownSamplingFactor[];
+
+
+ if(pInst == 0)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+ Params = pInst->NewParams;
+
+ /* Modifies filters types and coefficients, clear the taps and
+ re-initializes parameters if sample frequency has changed */
+ if(Params.Fs != pInst->CurrentParams.Fs)
+ {
+ pInst->CurrentParams.Fs = Params.Fs;
+
+ /* Initialize the center freqeuncies as a function of the sample rate */
+ Freq = (LVM_UINT16) ((LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1) / (pInst->nBands + 1));
+ for(ii = pInst->nBands; ii > 0; ii--)
+ {
+ pInst->pFiltersParams[ii-1].CenterFrequency = (LVM_UINT16) (Freq * ii);
+ }
+
+ /* Count the number of relevant filters. If the center frequency of the filter is
+ bigger than the nyquist frequency, then the filter is not relevant and doesn't
+ need to be used */
+ for(ii = pInst->nBands; ii > 0; ii--)
+ {
+ if(pInst->pFiltersParams[ii-1].CenterFrequency < (LVPSA_SampleRateTab[pInst->CurrentParams.Fs]>>1))
+ {
+ pInst->nRelevantFilters = ii;
+ break;
+ }
+ }
+ LVPSA_SetBPFiltersType(pInst, &Params);
+ LVPSA_SetBPFCoefficients(pInst, &Params);
+ LVPSA_SetQPFCoefficients(pInst, &Params);
+ LVPSA_ClearFilterHistory(pInst);
+ pInst->nSamplesBufferUpdate = (LVM_UINT16)LVPSA_nSamplesBufferUpdate[Params.Fs];
+ pInst->BufferUpdateSamplesCount = 0;
+ pInst->DownSamplingFactor = LVPSA_DownSamplingFactor[Params.Fs];
+ pInst->DownSamplingCount = 0;
+ for(ii = 0; ii < (pInst->nBands * pInst->SpectralDataBufferLength); ii++)
+ {
+ pInst->pSpectralDataBufferStart[ii] = 0;
+ }
+ for(ii = 0; ii < pInst->nBands; ii++)
+ {
+ pInst->pPreviousPeaks[ii] = 0;
+ }
+ }
+ else
+ {
+ if(Params.LevelDetectionSpeed != pInst->CurrentParams.LevelDetectionSpeed)
+ {
+ LVPSA_SetQPFCoefficients(pInst, &Params);
+ }
+ }
+
+ pInst->CurrentParams = pInst->NewParams;
+
+ return (LVPSA_OK);
+}
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_SetBPFiltersType */
+/* */
+/* DESCRIPTION: */
+/* Sets the filter type based on the BPFilterType. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* pParams Poniter to conrol parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* 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 */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFiltersType ( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams )
+{
+
+ extern LVM_UINT16 LVPSA_SampleRateTab[]; /* Sample rate table */
+ LVM_UINT16 ii; /* Filter band index */
+ LVM_UINT32 fs = (LVM_UINT32)LVPSA_SampleRateTab[(LVM_UINT16)pParams->Fs]; /* Sample rate */
+ LVM_UINT32 fc; /* Filter centre frequency */
+ LVM_INT16 QFactor; /* Filter Q factor */
+
+ for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+ {
+ /*
+ * Get the filter settings
+ */
+ fc = (LVM_UINT32)pInst->pFiltersParams[ii].CenterFrequency; /* Get the band centre frequency */
+ QFactor =(LVM_INT16) pInst->pFiltersParams[ii].QFactor; /* Get the band Q factor */
+
+
+ /*
+ * For each filter set the type of biquad required
+ */
+ pInst->pBPFiltersPrecision[ii] = LVPSA_SimplePrecisionFilter; /* Default to single precision */
+ if ((LOW_FREQ * fs) >= (fc << 15))
+ {
+ /*
+ * fc <= fs/110
+ */
+ pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+ }
+ else
+ {
+ if (((LOW_FREQ * fs) < (fc << 15)) && ((fc << 15) < (HIGH_FREQ * fs)) && (QFactor > 300))
+ {
+ /*
+ * (fs/110 < fc < fs/85) & (Q>3)
+ */
+ pInst->pBPFiltersPrecision[ii] = LVPSA_DoublePrecisionFilter;
+ }
+ }
+ }
+
+ return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_SetBPFCoefficients */
+/* */
+/* DESCRIPTION: */
+/* Sets the band pass filter coefficients. This uses the type to select */
+/* single or double precision coefficients. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* Params Initialisation parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetBPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams)
+{
+
+ LVM_UINT16 ii;
+
+ /*
+ * Set the coefficients for each band by the init function
+ */
+ for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+ {
+ switch (pInst->pBPFiltersPrecision[ii])
+ {
+ case LVPSA_DoublePrecisionFilter:
+ {
+ BP_C32_Coefs_t Coefficients;
+
+ /*
+ * Calculate the double precision coefficients
+ */
+ LVPSA_BPDoublePrecCoefs((LVM_UINT16)pParams->Fs,
+ &pInst->pFiltersParams[ii],
+ &Coefficients);
+
+ /*
+ * Set the coefficients
+ */
+ BP_1I_D16F32Cll_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+ &pInst->pBP_Taps[ii],
+ &Coefficients);
+ break;
+ }
+
+ case LVPSA_SimplePrecisionFilter:
+ {
+ BP_C16_Coefs_t Coefficients;
+
+ /*
+ * Calculate the single precision coefficients
+ */
+ LVPSA_BPSinglePrecCoefs((LVM_UINT16)pParams->Fs,
+ &pInst->pFiltersParams[ii],
+ &Coefficients);
+
+ /*
+ * Set the coefficients
+ */
+ BP_1I_D16F16Css_TRC_WRA_01_Init ( &pInst->pBP_Instances[ii],
+ &pInst->pBP_Taps[ii],
+ &Coefficients);
+ break;
+ }
+ }
+ }
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_SetQPFCoefficients */
+/* */
+/* DESCRIPTION: */
+/* Sets the quasi peak filters coefficients. This uses the chosen */
+/* LevelDetectionSpeed from the control parameters. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* Params Control parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_SetQPFCoefficients( LVPSA_InstancePr_t *pInst,
+ LVPSA_ControlParams_t *pParams )
+{
+ LVM_UINT16 ii;
+ LVM_Fs_en Fs = pParams->Fs;
+ QPD_C32_Coefs *pCoefficients;
+ extern QPD_C32_Coefs LVPSA_QPD_Coefs[];
+
+
+ pCoefficients = &LVPSA_QPD_Coefs[(pParams->LevelDetectionSpeed * LVPSA_NR_SUPPORTED_RATE) + Fs];
+
+
+ for (ii = 0; ii < pInst->nRelevantFilters; ii++)
+ {
+ LVPSA_QPD_Init (&pInst->pQPD_States[ii],
+ &pInst->pQPD_Taps[ii],
+ pCoefficients );
+ }
+
+ return(LVPSA_OK);
+
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_BPSinglePrecCoefs */
+/* */
+/* DESCRIPTION: */
+/* Calculate single precision coefficients for a band pass filter */
+/* */
+/* PARAMETERS: */
+/* Fs Sampling frequency index */
+/* pFilterParams Pointer to the filter definition */
+/* pCoefficients Pointer to the coefficients */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The equations used are as follows: */
+/* */
+/* t0 = 2 * Pi * Fc / Fs */
+/* */
+/* b2 = -0.5 * (2Q - t0) / (2Q + t0) */
+/* b1 = (0.5 - b2) * cos(t0) */
+/* a0 = (0.5 + b2) / 2 */
+/* */
+/* Where: */
+/* Fc is the centre frequency, DC to Nyquist */
+/* Fs is the sample frequency, 8000 to 48000 in descrete steps */
+/* Q is the Q factor, 0.25 to 12 */
+/* */
+/* 2. This function is entirely based on the LVEQNB_SinglePrecCoefs function */
+/* of the n bands equalizer (LVEQNB */
+/* */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPSinglePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C16_Coefs_t *pCoefficients)
+{
+
+ extern LVM_INT16 LVPSA_TwoPiOnFsTable[];
+ extern LVM_INT16 LVPSA_CosCoef[];
+
+
+ /*
+ * Intermediate variables and temporary values
+ */
+ LVM_INT32 T0;
+ LVM_INT16 D;
+ LVM_INT32 A0;
+ LVM_INT32 B1;
+ LVM_INT32 B2;
+ LVM_INT32 Dt0;
+ LVM_INT32 B2_Den;
+ LVM_INT32 B2_Num;
+ LVM_INT32 COS_T0;
+ LVM_INT16 coef;
+ LVM_INT32 factor;
+ LVM_INT16 t0;
+ LVM_INT16 i;
+
+
+ /*
+ * Get the filter definition
+ */
+ LVM_UINT16 Frequency = pFilterParams->CenterFrequency;
+ LVM_UINT16 QFactor = pFilterParams->QFactor;
+
+
+ /*
+ * Calculating the intermediate values
+ */
+ T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */
+ D = 3200; /* Floating point value 1.000000 (1*100*2^5) */
+ /* Force D = 1 : the function was originally used for a peaking filter.
+ The D parameter do not exist for a BandPass filter coefficients */
+
+ /*
+ * Calculate the B2 coefficient
+ */
+ Dt0 = D * (T0 >> 10);
+ B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
+ B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
+ B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+ /*
+ * Calculate the cosine by a polynomial expansion using the equation:
+ *
+ * Cos += coef(n) * t0^n For n = 0 to 6
+ */
+ T0 = (T0 >> 10) * 20859; /* Scale to 1.0 in 16-bit for range 0 to fs/2 */
+ t0 = (LVM_INT16)(T0 >> 16);
+ factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */
+ COS_T0 = 0; /* Initialise the error to zero */
+ for (i=1; i<7; i++)
+ {
+ coef = LVPSA_CosCoef[i]; /* Get the nth coefficient */
+ COS_T0 += (factor * coef) >> 5; /* The nth partial sum */
+ factor = (factor * t0) >> 15; /* Calculate t0^n */
+ }
+ COS_T0 = COS_T0 << (LVPSA_CosCoef[0]+6); /* Correct the scaling */
+
+
+ B1 = ((0x40000000 - B2) >> 16) * (COS_T0 >> 16); /* B1 = (0.5 - b2) * cos(t0) */
+ A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) / 2 */
+
+ /*
+ * Write coeff into the data structure
+ */
+ pCoefficients->A0 = (LVM_INT16)(A0>>16);
+ pCoefficients->B1 = (LVM_INT16)(B1>>15);
+ pCoefficients->B2 = (LVM_INT16)(B2>>16);
+
+
+ return(LVPSA_OK);
+}
+
+/****************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_BPDoublePrecCoefs */
+/* */
+/* DESCRIPTION: */
+/* Calculate double precision coefficients for a band pass filter */
+/* */
+/* PARAMETERS: */
+/* Fs Sampling frequency index */
+/* pFilterParams Pointer to the filter definition */
+/* pCoefficients Pointer to the coefficients */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* 1. The equations used are as follows: */
+/* */
+/* t0 = 2 * Pi * Fc / Fs */
+/* */
+/* b2 = -0.5 * (2Q - t0) / (2Q + t0) */
+/* b1 = (0.5 - b2) * (1 - coserr(t0)) */
+/* a0 = (0.5 + b2) / 2 */
+/* */
+/* Where: */
+/* Fc is the centre frequency, DC to Fs/50 */
+/* Fs is the sample frequency, 8000 to 48000 in descrete steps */
+/* Q is the Q factor, 0.25 to 12 (represented by 25 to 1200) */
+/* */
+/* 2. The double precision coefficients are only used when fc is less than fs/85, so */
+/* the cosine of t0 is always close to 1.0. Instead of calculating the cosine */
+/* itself the difference from the value 1.0 is calculated, this can be done with */
+/* lower precision maths. */
+/* */
+/* 3. The value of the B2 coefficient is only calculated as a single precision value, */
+/* small errors in this value have a combined effect on the Q and Gain but not the */
+/* the frequency of the filter. */
+/* */
+/* 4. This function is entirely based on the LVEQNB_DoublePrecCoefs function */
+/* of the n bands equalizer (LVEQNB */
+/* */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_BPDoublePrecCoefs( LVM_UINT16 Fs,
+ LVPSA_FilterParam_t *pFilterParams,
+ BP_C32_Coefs_t *pCoefficients)
+{
+
+ extern LVM_INT16 LVPSA_TwoPiOnFsTable[];
+ extern LVM_INT16 LVPSA_DPCosCoef[];
+
+ /*
+ * Intermediate variables and temporary values
+ */
+ LVM_INT32 T0;
+ LVM_INT16 D;
+ LVM_INT32 A0;
+ LVM_INT32 B1;
+ LVM_INT32 B2;
+ LVM_INT32 Dt0;
+ LVM_INT32 B2_Den;
+ LVM_INT32 B2_Num;
+ LVM_INT32 CosErr;
+ LVM_INT16 coef;
+ LVM_INT32 factor;
+ LVM_INT16 t0;
+ LVM_INT16 i;
+
+ /*
+ * Get the filter definition
+ */
+ LVM_UINT16 Frequency = pFilterParams->CenterFrequency;
+ LVM_UINT16 QFactor = pFilterParams->QFactor;
+
+
+ /*
+ * Calculating the intermediate values
+ */
+ T0 = (LVM_INT32)Frequency * LVPSA_TwoPiOnFsTable[Fs]; /* T0 = 2 * Pi * Fc / Fs */
+ D = 3200; /* Floating point value 1.000000 (1*100*2^5) */
+ /* Force D = 1 : the function was originally used for a peaking filter.
+ The D parameter do not exist for a BandPass filter coefficients */
+
+ /*
+ * Calculate the B2 coefficient
+ */
+ Dt0 = D * (T0 >> 10);
+ B2_Den = (LVM_INT32)(((LVM_UINT32)QFactor << 19) + (LVM_UINT32)(Dt0 >> 2));
+ B2_Num = (LVM_INT32)((LVM_UINT32)(Dt0 >> 3) - ((LVM_UINT32)QFactor << 18));
+ B2 = (B2_Num / (B2_Den >> 16)) << 15;
+
+ /*
+ * Calculate the cosine error by a polynomial expansion using the equation:
+ *
+ * CosErr += coef(n) * t0^n For n = 0 to 4
+ */
+ T0 = (T0 >> 6) * 0x7f53; /* Scale to 1.0 in 16-bit for range 0 to fs/50 */
+ t0 = (LVM_INT16)(T0 >> 16);
+ factor = 0x7fff; /* Initialise to 1.0 for the a0 coefficient */
+ CosErr = 0; /* Initialise the error to zero */
+ for (i=1; i<5; i++)
+ {
+ coef = LVPSA_DPCosCoef[i]; /* Get the nth coefficient */
+ CosErr += (factor * coef) >> 5; /* The nth partial sum */
+ factor = (factor * t0) >> 15; /* Calculate t0^n */
+ }
+ CosErr = CosErr << (LVPSA_DPCosCoef[0]); /* Correct the scaling */
+
+ /*
+ * Calculate the B1 and A0 coefficients
+ */
+ B1 = (0x40000000 - B2); /* B1 = (0.5 - b2) */
+ A0 = ((B1 >> 16) * (CosErr >> 10)) >> 6; /* Temporary storage for (0.5 - b2) * coserr(t0) */
+ B1 -= A0; /* B1 = (0.5 - b2) * (1 - coserr(t0)) */
+ A0 = (0x40000000 + B2) >> 1; /* A0 = (0.5 + b2) / 2 */
+
+ /*
+ * Write coeff into the data structure
+ */
+ pCoefficients->A0 = A0;
+ pCoefficients->B1 = B1;
+ pCoefficients->B2 = B2;
+
+ return(LVPSA_OK);
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_ClearFilterHistory */
+/* */
+/* DESCRIPTION: */
+/* Clears the filters' data history */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/* NOTES: */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ClearFilterHistory(LVPSA_InstancePr_t *pInst)
+{
+ LVM_INT8 *pTapAddress;
+ LVM_UINT32 i;
+
+ /* Band Pass filters taps */
+ pTapAddress = (LVM_INT8 *)pInst->pBP_Taps;
+ for(i = 0; i < pInst->nBands * sizeof(Biquad_1I_Order2_Taps_t); i++)
+ {
+ pTapAddress[i] = 0;
+ }
+
+ /* Quasi-peak filters taps */
+ pTapAddress = (LVM_INT8 *)pInst->pQPD_Taps;
+ for(i = 0; i < pInst->nBands * sizeof(QPD_Taps_t); i++)
+ {
+ pTapAddress[i] = 0;
+ }
+
+ return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
new file mode 100755
index 0000000..ab45678
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Init.c
@@ -0,0 +1,197 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "InstAlloc.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Init */
+/* */
+/* DESCRIPTION: */
+/* Initialize the LVPSA module */
+/* */
+/* */
+/* PARAMETERS: */
+/* phInstance Pointer to pointer to the instance */
+/* InitParams Init parameters structure */
+/* ControlParams Control parameters structure */
+/* pMemoryTable Memory table that contains memory areas definition */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Init ( pLVPSA_Handle_t *phInstance,
+ LVPSA_InitParams_t *pInitParams,
+ LVPSA_ControlParams_t *pControlParams,
+ LVPSA_MemTab_t *pMemoryTable )
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst;
+ LVPSA_RETURN errorCode = LVPSA_OK;
+ LVM_UINT32 ii;
+ extern LVM_INT16 LVPSA_GainTable[];
+ LVM_UINT32 BufferLength = 0;
+
+ /* Ints_Alloc instances, needed for memory alignment management */
+ INST_ALLOC Instance;
+ INST_ALLOC Scratch;
+ INST_ALLOC Data;
+ INST_ALLOC Coef;
+
+ /* Check parameters */
+ if((phInstance == LVM_NULL) || (pInitParams == LVM_NULL) || (pControlParams == LVM_NULL) || (pMemoryTable == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION) ||
+ (pInitParams->SpectralDataBufferDuration == 0) ||
+ (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE) ||
+ (pInitParams->MaxInputBlockSize == 0) ||
+ (pInitParams->nBands < LVPSA_NBANDSMIN) ||
+ (pInitParams->nBands > LVPSA_NBANDSMAX) ||
+ (pInitParams->pFiltersParams == 0))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ for(ii = 0; ii < pInitParams->nBands; ii++)
+ {
+ if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+ (pInitParams->pFiltersParams[ii].PostGain > LVPSA_MAXPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].PostGain < LVPSA_MINPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR) ||
+ (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ }
+
+
+ /*Inst_Alloc instances initialization */
+ InstAlloc_Init( &Instance , pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress);
+ InstAlloc_Init( &Scratch , pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress);
+ InstAlloc_Init( &Data , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress);
+ InstAlloc_Init( &Coef , pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress);
+
+
+ /* Set the instance handle if not already initialised */
+ if (*phInstance == LVM_NULL)
+ {
+ *phInstance = InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+ }
+ pLVPSA_Inst =(LVPSA_InstancePr_t*)*phInstance;
+
+
+ /* Check the memory table for NULL pointers */
+ for (ii = 0; ii < LVPSA_NR_MEMORY_REGIONS; ii++)
+ {
+ if (pMemoryTable->Region[ii].Size!=0)
+ {
+ if (pMemoryTable->Region[ii].pBaseAddress==LVM_NULL)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ pLVPSA_Inst->MemoryTable.Region[ii] = pMemoryTable->Region[ii];
+ }
+ }
+
+ /* Initialize module's internal parameters */
+ pLVPSA_Inst->bControlPending = LVM_FALSE;
+ pLVPSA_Inst->nBands = pInitParams->nBands;
+ pLVPSA_Inst->MaxInputBlockSize = pInitParams->MaxInputBlockSize;
+ pLVPSA_Inst->SpectralDataBufferDuration = pInitParams->SpectralDataBufferDuration;
+ pLVPSA_Inst->CurrentParams.Fs = LVM_FS_DUMMY;
+ pLVPSA_Inst->CurrentParams.LevelDetectionSpeed = LVPSA_SPEED_DUMMY;
+
+ { /* for avoiding QAC warnings */
+ LVM_INT32 SDBD=(LVM_INT32)pLVPSA_Inst->SpectralDataBufferDuration;
+ LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+ LVM_INT32 BL;
+
+ MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+
+ BufferLength=(LVM_UINT32)BL;
+ }
+
+ if((BufferLength * LVPSA_InternalRefreshTime) != pLVPSA_Inst->SpectralDataBufferDuration)
+ {
+ pLVPSA_Inst->SpectralDataBufferLength = BufferLength + 1;
+ }
+ else
+ {
+ pLVPSA_Inst->SpectralDataBufferLength = BufferLength;
+ }
+
+
+ /* Assign the pointers */
+
+ pLVPSA_Inst->pPostGains = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+ pLVPSA_Inst->pFiltersParams = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+ pLVPSA_Inst->pSpectralDataBufferStart = InstAlloc_AddMember( &Instance, pInitParams->nBands * pLVPSA_Inst->SpectralDataBufferLength * sizeof(LVM_UINT8) );
+ pLVPSA_Inst->pPreviousPeaks = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+ pLVPSA_Inst->pBPFiltersPrecision = InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+
+ pLVPSA_Inst->pBP_Instances = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
+ pLVPSA_Inst->pQPD_States = InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+
+ pLVPSA_Inst->pBP_Taps = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
+ pLVPSA_Inst->pQPD_Taps = InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+
+
+ /* Copy filters parameters in the private instance */
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pLVPSA_Inst->pFiltersParams[ii] = pInitParams->pFiltersParams[ii];
+ }
+
+ /* Set Post filters gains*/
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pLVPSA_Inst->pPostGains[ii] =(LVM_UINT16) LVPSA_GainTable[pInitParams->pFiltersParams[ii].PostGain + 15];
+ }
+ pLVPSA_Inst->pSpectralDataBufferWritePointer = pLVPSA_Inst->pSpectralDataBufferStart;
+
+
+ /* Initialize control dependant internal parameters */
+ errorCode = LVPSA_Control (*phInstance, pControlParams);
+
+ if(errorCode!=0)
+ {
+ return errorCode;
+ }
+
+ errorCode = LVPSA_ApplyNewSettings (pLVPSA_Inst);
+
+ if(errorCode!=0)
+ {
+ return errorCode;
+ }
+
+ return(errorCode);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
new file mode 100755
index 0000000..059cb4e
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Memory.c
@@ -0,0 +1,177 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "InstAlloc.h"
+
+/****************************************************************************************/
+/* */
+/* 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 */
+/* InitParams Pointer to the instance init parameters */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/****************************************************************************************/
+LVPSA_RETURN LVPSA_Memory ( pLVPSA_Handle_t hInstance,
+ LVPSA_MemTab_t *pMemoryTable,
+ LVPSA_InitParams_t *pInitParams )
+{
+ LVM_UINT32 ii;
+ LVM_UINT32 BufferLength;
+ INST_ALLOC Instance;
+ INST_ALLOC Scratch;
+ INST_ALLOC Data;
+ INST_ALLOC Coef;
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+
+
+ InstAlloc_Init( &Instance , LVM_NULL);
+ InstAlloc_Init( &Scratch , LVM_NULL);
+ InstAlloc_Init( &Data , LVM_NULL);
+ InstAlloc_Init( &Coef , LVM_NULL);
+
+
+ if((pMemoryTable == LVM_NULL) || (pInitParams == LVM_NULL))
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+
+ /*
+ * Fill in the memory table
+ */
+ if (hInstance == LVM_NULL)
+ {
+
+ /* Check init parameter */
+ if( (pInitParams->SpectralDataBufferDuration > LVPSA_MAXBUFFERDURATION) ||
+ (pInitParams->SpectralDataBufferDuration == 0) ||
+ (pInitParams->MaxInputBlockSize > LVPSA_MAXINPUTBLOCKSIZE) ||
+ (pInitParams->MaxInputBlockSize == 0) ||
+ (pInitParams->nBands < LVPSA_NBANDSMIN) ||
+ (pInitParams->nBands > LVPSA_NBANDSMAX) ||
+ (pInitParams->pFiltersParams == 0))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ for(ii = 0; ii < pInitParams->nBands; ii++)
+ {
+ if((pInitParams->pFiltersParams[ii].CenterFrequency > LVPSA_MAXCENTERFREQ) ||
+ (pInitParams->pFiltersParams[ii].PostGain > LVPSA_MAXPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].PostGain < LVPSA_MINPOSTGAIN) ||
+ (pInitParams->pFiltersParams[ii].QFactor < LVPSA_MINQFACTOR) ||
+ (pInitParams->pFiltersParams[ii].QFactor > LVPSA_MAXQFACTOR))
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+ }
+
+ /*
+ * Instance memory
+ */
+
+ InstAlloc_AddMember( &Instance, sizeof(LVPSA_InstancePr_t) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT16) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_FilterParam_t) );
+
+ {
+ /* for avoiding QAC warnings as MUL32x32INTO32 works on LVM_INT32 only*/
+ LVM_INT32 SDBD=(LVM_INT32)pInitParams->SpectralDataBufferDuration;
+ LVM_INT32 IRTI=(LVM_INT32)LVPSA_InternalRefreshTimeInv;
+ LVM_INT32 BL;
+
+ MUL32x32INTO32(SDBD,IRTI,BL,LVPSA_InternalRefreshTimeShift)
+ BufferLength=(LVM_UINT32)BL;
+ }
+
+
+ if((BufferLength * LVPSA_InternalRefreshTime) != pInitParams->SpectralDataBufferDuration)
+ {
+ BufferLength++;
+ }
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * BufferLength * sizeof(LVM_UINT8) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVM_UINT8) );
+ InstAlloc_AddMember( &Instance, pInitParams->nBands * sizeof(LVPSA_BPFilterPrecision_en) );
+ pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Size = InstAlloc_GetTotal(&Instance);
+ pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].Type = LVPSA_PERSISTENT;
+ pMemoryTable->Region[LVPSA_MEMREGION_INSTANCE].pBaseAddress = LVM_NULL;
+
+ /*
+ * Scratch memory
+ */
+ InstAlloc_AddMember( &Scratch, 2 * pInitParams->MaxInputBlockSize * sizeof(LVM_INT16) );
+ pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Size = InstAlloc_GetTotal(&Scratch);
+ pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].Type = LVPSA_SCRATCH;
+ pMemoryTable->Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress = LVM_NULL;
+
+ /*
+ * Persistent coefficients memory
+ */
+ InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(Biquad_Instance_t) );
+ InstAlloc_AddMember( &Coef, pInitParams->nBands * sizeof(QPD_State_t) );
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Size = InstAlloc_GetTotal(&Coef);
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].Type = LVPSA_PERSISTENT_COEF;
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_COEF].pBaseAddress = LVM_NULL;
+
+ /*
+ * Persistent data memory
+ */
+ InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(Biquad_1I_Order2_Taps_t) );
+ InstAlloc_AddMember( &Data, pInitParams->nBands * sizeof(QPD_Taps_t) );
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Size = InstAlloc_GetTotal(&Data);
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].Type = LVPSA_PERSISTENT_DATA;
+ pMemoryTable->Region[LVPSA_MEMREGION_PERSISTENT_DATA].pBaseAddress = LVM_NULL;
+
+ }
+ else
+ {
+ /* Read back memory allocation table */
+ *pMemoryTable = pLVPSA_Inst->MemoryTable;
+ }
+
+ return(LVPSA_OK);
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
new file mode 100755
index 0000000..eb9fa8f
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Private.h
@@ -0,0 +1,159 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#ifndef _LVPSA_PRIVATE_H_
+#define _LVPSA_PRIVATE_H_
+
+#include "LVPSA.h"
+#include "BIQUAD.h"
+#include "LVPSA_QPD.h"
+#include "LVM_Macros.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**********************************************************************************
+ CONSTANT DEFINITIONS
+***********************************************************************************/
+
+/* Memory */
+#define LVPSA_INSTANCE_ALIGN 4 /* 32-bit alignment for structures */
+#define LVPSA_SCRATCH_ALIGN 4 /* 32-bit alignment for long data */
+#define LVPSA_COEF_ALIGN 4 /* 32-bit alignment for long words */
+#define LVPSA_DATA_ALIGN 4 /* 32-bit alignment for long data */
+
+#define LVPSA_MEMREGION_INSTANCE 0 /* Offset to instance memory region in memory table */
+#define LVPSA_MEMREGION_PERSISTENT_COEF 1 /* Offset to persistent coefficients memory region in memory table */
+#define LVPSA_MEMREGION_PERSISTENT_DATA 2 /* Offset to persistent taps memory region in memory table */
+#define LVPSA_MEMREGION_SCRATCH 3 /* Offset to scratch memory region in memory table */
+
+#define LVPSA_NR_SUPPORTED_RATE 9 /* From 8000Hz to 48000Hz */
+#define LVPSA_NR_SUPPORTED_SPEED 3 /* LOW, MEDIUM, HIGH */
+
+#define LVPSA_MAXBUFFERDURATION 4000 /* Maximum length in ms of the levels buffer */
+#define LVPSA_MAXINPUTBLOCKSIZE 5000 /* Maximum length in mono samples of the block to process */
+#define LVPSA_NBANDSMIN 1 /* Minimum number of frequency band */
+#define LVPSA_NBANDSMAX 30 /* Maximum number of frequency band */
+#define LVPSA_MAXCENTERFREQ 20000 /* Maximum possible center frequency */
+#define LVPSA_MINPOSTGAIN -15 /* Minimum possible post gain */
+#define LVPSA_MAXPOSTGAIN 15 /* Maximum possible post gain */
+#define LVPSA_MINQFACTOR 25 /* Minimum possible Q factor */
+#define LVPSA_MAXQFACTOR 1200 /* Maximum possible Q factor */
+
+#define LVPSA_MAXLEVELDECAYFACTOR 0x4111 /* Decay factor for the maximum values calculation */
+#define LVPSA_MAXLEVELDECAYSHIFT 14 /* Decay shift for the maximum values calculation */
+
+#define LVPSA_MAXUNSIGNEDCHAR 0xFF
+
+#define LVPSA_FsInvertShift 31
+#define LVPSA_GAINSHIFT 11
+#define LVPSA_FREQSHIFT 25
+
+/**********************************************************************************
+ TYPES DEFINITIONS
+***********************************************************************************/
+
+#define LVPSA_InternalRefreshTime 0x0014 /* 20 ms (50Hz) in Q16.0 */
+#define LVPSA_InternalRefreshTimeInv 0x0666 /* 1/20ms left shifted by 15 */
+#define LVPSA_InternalRefreshTimeShift 15
+
+
+/* Precision of the filter */
+typedef enum
+{
+ LVPSA_SimplePrecisionFilter, /* Simple precision */
+ LVPSA_DoublePrecisionFilter /* Double precision */
+} LVPSA_BPFilterPrecision_en;
+
+typedef struct
+{
+ LVM_CHAR bControlPending; /* Flag incating a change of the control parameters */
+ LVM_UINT16 nBands; /* Number of bands of the spectrum analyzer */
+ LVM_UINT16 MaxInputBlockSize; /* Maximum input data buffer size */
+
+ LVPSA_ControlParams_t CurrentParams; /* Current control parameters of the module */
+ LVPSA_ControlParams_t NewParams; /* New control parameters given by the user */
+ LVPSA_MemTab_t MemoryTable;
+
+ LVPSA_BPFilterPrecision_en *pBPFiltersPrecision; /* Points a nBands elements array that contains the filter precision for each band */
+ Biquad_Instance_t *pBP_Instances; /* Points a nBands elements array that contains the band pass filter instance for each band */
+ Biquad_1I_Order2_Taps_t *pBP_Taps; /* Points a nBands elements array that contains the band pass filter taps for each band */
+ QPD_State_t *pQPD_States; /* Points a nBands elements array that contains the QPD filter instance for each band */
+ QPD_Taps_t *pQPD_Taps; /* Points a nBands elements array that contains the QPD filter taps for each band */
+ LVM_UINT16 *pPostGains; /* Points a nBands elements array that contains the post-filter gains for each band */
+
+ LVPSA_FilterParam_t *pFiltersParams; /* Copy of the filters parameters from the input parameters */
+
+
+ LVM_UINT16 nSamplesBufferUpdate; /* Number of samples to make 20ms */
+ LVM_INT32 BufferUpdateSamplesCount; /* Counter used to know when to put a new value in the buffer */
+ LVM_UINT16 nRelevantFilters; /* Number of relevent filters depending on sampling frequency and bands center frequency */
+ LVM_UINT16 LocalSamplesCount; /* Counter used to update the SpectralDataBufferAudioTime */
+
+ LVM_UINT16 DownSamplingFactor; /* Down sampling factor depending on the sampling frequency */
+ LVM_UINT16 DownSamplingCount; /* Counter used for the downsampling handling */
+
+ LVM_UINT16 SpectralDataBufferDuration; /* Length of the buffer in time (ms) defined by the application */
+ LVM_UINT8 *pSpectralDataBufferStart; /* Starting address of the buffer */
+ LVM_UINT8 *pSpectralDataBufferWritePointer; /* Current position of the writting pointer of the buffer */
+ LVPSA_Time SpectralDataBufferAudioTime; /* AudioTime at which the last value save occured in the buffer */
+ LVM_UINT32 SpectralDataBufferLength; /* Number of spectrum data value that the buffer can contain (per band)
+ = SpectralDataBufferDuration/20ms */
+
+ LVM_UINT8 *pPreviousPeaks; /* Points to a nBands elements array that contains the previous peak value of the level
+ detection. Those values are decremented after each call to the GetSpectrum function */
+
+}LVPSA_InstancePr_t, *pLVPSA_InstancePr_t;
+
+
+
+/**********************************************************************************
+ FUNCTIONS PROTOTYPE
+***********************************************************************************/
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_ApplyNewSettings */
+/* */
+/* DESCRIPTION: */
+/* Reinitialize some parameters and changes filters' coefficients if */
+/* some control parameters have changed. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the instance */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Always succeeds */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_ApplyNewSettings (LVPSA_InstancePr_t *pInst);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _LVPSA_PRIVATE_H */
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
new file mode 100755
index 0000000..d88a751
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
@@ -0,0 +1,260 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA.h"
+#include "LVPSA_Private.h"
+#include "LVM_Macros.h"
+#include "VectorArithmetic.h"
+
+#define LVM_MININT_32 0x80000000
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_Process */
+/* */
+/* DESCRIPTION: */
+/* The process applies band pass filters to the signal. Each output */
+/* feeds a quasi peak filter for level detection. */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* pLVPSA_InputSamples Pointer to the input samples buffer */
+/* InputBlockSize Number of mono samples to process */
+/* AudioTime Playback time of the input samples */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_Process ( pLVPSA_Handle_t hInstance,
+ LVM_INT16 *pLVPSA_InputSamples,
+ LVM_UINT16 InputBlockSize,
+ LVPSA_Time AudioTime )
+
+{
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+ LVM_INT16 *pScratch;
+ LVM_INT16 ii;
+ LVM_INT32 AudioTimeInc;
+ extern LVM_UINT32 LVPSA_SampleRateInvTab[];
+ LVM_UINT8 *pWrite_Save; /* Position of the write pointer at the beginning of the process */
+
+ /******************************************************************************
+ CHECK PARAMETERS
+ *******************************************************************************/
+ if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+ if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
+ {
+ return(LVPSA_ERROR_INVALIDPARAM);
+ }
+
+ pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
+ pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+
+ /******************************************************************************
+ APPLY NEW SETTINGS IF NEEDED
+ *******************************************************************************/
+ if (pLVPSA_Inst->bControlPending == LVM_TRUE)
+ {
+ pLVPSA_Inst->bControlPending = 0;
+ LVPSA_ApplyNewSettings( pLVPSA_Inst);
+ }
+
+ /******************************************************************************
+ PROCESS SAMPLES
+ *******************************************************************************/
+ /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
+ Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize);
+ Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize);
+
+ for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
+ {
+ switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
+ {
+ case LVPSA_SimplePrecisionFilter:
+ BP_1I_D16F16C14_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
+ pScratch,
+ pScratch + InputBlockSize,
+ (LVM_INT16)InputBlockSize);
+ break;
+
+ case LVPSA_DoublePrecisionFilter:
+ BP_1I_D16F32C30_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
+ pScratch,
+ pScratch + InputBlockSize,
+ (LVM_INT16)InputBlockSize);
+ break;
+ default:
+ break;
+ }
+
+
+ LVPSA_QPD_Process ( pLVPSA_Inst,
+ pScratch + InputBlockSize,
+ (LVM_INT16)InputBlockSize,
+ ii);
+ }
+
+ /******************************************************************************
+ UPDATE SpectralDataBufferAudioTime
+ *******************************************************************************/
+
+ if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
+ {
+ MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
+ (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
+ AudioTimeInc,
+ LVPSA_FsInvertShift)
+ pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
+ }
+
+ return(LVPSA_OK);
+}
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_GetSpectrum */
+/* */
+/* DESCRIPTION: */
+/* Gets the levels values at a certain point in time */
+/* */
+/* */
+/* PARAMETERS: */
+/* hInstance Pointer to the instance */
+/* GetSpectrumAudioTime Retrieve the values at this time */
+/* pCurrentValues Pointer to a buffer that will contain levels' values */
+/* pMaxValues Pointer to a buffer that will contain max levels' values */
+/* */
+/* */
+/* RETURNS: */
+/* LVPSA_OK Succeeds */
+/* otherwise Error due to bad parameters */
+/* */
+/************************************************************************************/
+LVPSA_RETURN LVPSA_GetSpectrum ( pLVPSA_Handle_t hInstance,
+ LVPSA_Time GetSpectrumAudioTime,
+ LVM_UINT8 *pCurrentValues,
+ LVM_UINT8 *pPeakValues )
+
+{
+
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+ LVM_INT32 StatusDelta, ii;
+ LVM_UINT8 *pRead;
+
+ if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
+ {
+ return(LVPSA_ERROR_NULLADDRESS);
+ }
+
+
+ /* First find the place where to look in the status buffer */
+ if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
+ {
+ MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
+ if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
+ {
+ StatusDelta += 1;
+ }
+ }
+ else
+ {
+ /* This part handles the wrap around */
+ MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
+ if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
+ {
+ StatusDelta += 1;
+ }
+ }
+ /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
+ if(
+ ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+ ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
+ (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
+
+ ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
+ (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
+ ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
+ (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
+ (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
+
+ (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
+ (!StatusDelta))
+ {
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pCurrentValues[ii] = 0;
+ pPeakValues[ii] = 0;
+ }
+ return(LVPSA_OK);
+ }
+ /* Set the reading pointer */
+ if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
+ {
+ pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
+ }
+ else
+ {
+ pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer - StatusDelta * pLVPSA_Inst->nBands;
+ }
+
+
+ /* Read the status buffer and fill the output buffers */
+ for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
+ {
+ pCurrentValues[ii] = pRead[ii];
+ if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
+ {
+ pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
+ }
+ else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
+ {
+ LVM_INT32 temp;
+ /*Re-compute max values for decay */
+ temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
+ temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
+ /* If the gain has no effect, "help" the value to increase */
+ if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
+ {
+ temp += 1;
+ }
+ /* Saturate */
+ temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
+ /* Store new max level */
+ pLVPSA_Inst->pPreviousPeaks[ii] = (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
+ }
+
+ pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
+ }
+
+ return(LVPSA_OK);
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
new file mode 100755
index 0000000..641357e
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD.h
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#ifndef _LVPSA_QPD_H_
+#define _LVPSA_QPD_H_
+
+#include "LVM_Types.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+typedef struct
+{
+ LVM_INT32 *pDelay; /* pointer to the delayed samples (data of 32 bits) */
+ LVM_INT32 Coefs[2]; /* pointer to the filter coefficients */
+}QPD_State_t, *pQPD_State_t;
+
+typedef struct
+{
+ LVM_INT32 KP; /*should store a0*/
+ LVM_INT32 KM; /*should store b2*/
+
+} QPD_C32_Coefs, *PQPD_C32_Coefs;
+
+typedef struct
+{
+ LVM_INT32 Storage[1];
+
+} QPD_Taps_t, *pQPD_Taps_t;
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Process */
+/* */
+/* DESCRIPTION: */
+/* Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/* in the buffer every 20 ms. */
+/* */
+/* PARAMETERS: */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Process ( void *hInstance,
+ LVM_INT16 *pInSamps,
+ LVM_INT16 numSamples,
+ LVM_INT16 BandIndex);
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Init */
+/* */
+/* DESCRIPTION: */
+/* Initialize a quasi peak filter instance. */
+/* */
+/* PARAMETERS: */
+/* pInstance Pointer to the instance */
+/* pTaps Pointer to the filter's taps */
+/* pCoef Pointer to the filter's coefficients */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Init ( QPD_State_t *pInstance,
+ QPD_Taps_t *pTaps,
+ QPD_C32_Coefs *pCoef );
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
new file mode 100755
index 0000000..37abe40
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Init.c
@@ -0,0 +1,50 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA_QPD.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Init */
+/* */
+/* DESCRIPTION: */
+/* Initialize a quasi peak filter instance. */
+/* */
+/* PARAMETERS: */
+/* pQPD_State Pointer to the filter state */
+/* pTaps Pointer to the filter's taps */
+/* pCoef Pointer to the filter's coefficients */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Init ( pQPD_State_t pQPD_State,
+ QPD_Taps_t *pTaps,
+ QPD_C32_Coefs *pCoef )
+{
+ pQPD_State->pDelay = pTaps->Storage;
+ pQPD_State->Coefs[0] = pCoef->KP;
+ pQPD_State->Coefs[1] = pCoef->KM;
+}
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
new file mode 100755
index 0000000..7087475
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_QPD_Process.c
@@ -0,0 +1,220 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+#include "LVPSA_QPD.h"
+#include "LVPSA_Private.h"
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_WritePeak */
+/* */
+/* DESCRIPTION: */
+/* Write a level value in the buffer in the corresponding band. */
+/* */
+/* PARAMETERS: */
+/* pInst Pointer to the LVPSA instance */
+/* ppWrite Pointer to pointer to the buffer */
+/* CallNumber Number of the band the value should be written in */
+/* Value Value to write in the buffer */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak( pLVPSA_InstancePr_t pLVPSA_Inst,
+ LVM_UINT8 **ppWrite,
+ LVM_INT16 BandIndex,
+ LVM_INT16 Value );
+
+
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_Process */
+/* */
+/* DESCRIPTION: */
+/* Apply downsampling, post gain, quasi peak filtering and write the levels values */
+/* in the buffer every 20 ms. */
+/* */
+/* PARAMETERS: */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_Process ( void *hInstance,
+ LVM_INT16 *pInSamps,
+ LVM_INT16 numSamples,
+ LVM_INT16 BandIndex)
+{
+
+ /******************************************************************************
+ PARAMETERS
+ *******************************************************************************/
+ LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
+ QPD_State_t *pQPDState = (QPD_State_t*)&pLVPSA_Inst->pQPD_States[BandIndex];
+
+ /* Pointer to taps */
+ LVM_INT32* pDelay = pQPDState->pDelay;
+
+ /* Parameters needed during quasi peak calculations */
+ LVM_INT32 X0;
+ LVM_INT32 temp,temp2;
+ LVM_INT32 accu;
+ LVM_INT16 Xg0;
+ LVM_INT16 D0;
+ LVM_INT16 V0 = (LVM_INT16)(*pDelay);
+
+ /* Filter's coef */
+ LVM_INT32 Kp = pQPDState->Coefs[0];
+ LVM_INT32 Km = pQPDState->Coefs[1];
+
+ LVM_INT16 ii = numSamples;
+
+ LVM_UINT8 *pWrite = pLVPSA_Inst->pSpectralDataBufferWritePointer;
+ LVM_INT32 BufferUpdateSamplesCount = pLVPSA_Inst->BufferUpdateSamplesCount;
+ LVM_UINT16 DownSamplingFactor = pLVPSA_Inst->DownSamplingFactor;
+
+ /******************************************************************************
+ INITIALIZATION
+ *******************************************************************************/
+ /* Correct the pointer to take the first down sampled signal sample */
+ pInSamps += pLVPSA_Inst->DownSamplingCount;
+ /* Correct also the number of samples */
+ ii = (LVM_INT16)(ii - (LVM_INT16)pLVPSA_Inst->DownSamplingCount);
+
+ while (ii > 0)
+ {
+ /* Apply post gain */
+ X0 = ((*pInSamps) * pLVPSA_Inst->pPostGains[BandIndex]) >> (LVPSA_GAINSHIFT-1); /* - 1 to compensate scaling in process function*/
+ pInSamps = pInSamps + DownSamplingFactor;
+
+ /* Saturate and take absolute value */
+ if(X0 < 0)
+ X0 = -X0;
+ if (X0 > 0x7FFF)
+ Xg0 = 0x7FFF;
+ else
+ Xg0 = (LVM_INT16)(X0);
+
+
+ /* Quasi peak filter calculation */
+ D0 = (LVM_INT16)(Xg0 - V0);
+
+ temp2 = (LVM_INT32)D0;
+ MUL32x32INTO32(temp2,Kp,accu,31);
+
+ D0 = (LVM_INT16)(D0>>1);
+ if (D0 < 0){
+ D0 = (LVM_INT16)(-D0);
+ }
+
+ temp2 = (LVM_INT32)D0;
+ MUL32x32INTO32((LVM_INT32)D0,Km,temp,31);
+ accu +=temp + Xg0;
+
+ if (accu > 0x7FFF)
+ accu = 0x7FFF;
+ else if(accu < 0)
+ accu = 0x0000;
+
+ V0 = (LVM_INT16)accu;
+
+ if(((pLVPSA_Inst->nSamplesBufferUpdate - BufferUpdateSamplesCount) < DownSamplingFactor))
+ {
+ LVPSA_QPD_WritePeak( pLVPSA_Inst,
+ &pWrite,
+ BandIndex,
+ V0);
+ BufferUpdateSamplesCount -= pLVPSA_Inst->nSamplesBufferUpdate;
+ pLVPSA_Inst->LocalSamplesCount = (LVM_UINT16)(numSamples - ii);
+ }
+ BufferUpdateSamplesCount+=DownSamplingFactor;
+
+ ii = (LVM_INT16)(ii-DownSamplingFactor);
+
+ }
+
+ /* Store last taps in memory */
+ *pDelay = (LVM_INT32)(V0);
+
+ /* If this is the last call to the function after last band processing,
+ update the parameters. */
+ if(BandIndex == (pLVPSA_Inst->nRelevantFilters-1))
+ {
+ pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+ /* Adjustment for 11025Hz input, 220,5 is normally
+ the exact number of samples for 20ms.*/
+ if((pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite)&&(pLVPSA_Inst->CurrentParams.Fs == LVM_FS_11025))
+ {
+ if(pLVPSA_Inst->nSamplesBufferUpdate == 220)
+ {
+ pLVPSA_Inst->nSamplesBufferUpdate = 221;
+ }
+ else
+ {
+ pLVPSA_Inst->nSamplesBufferUpdate = 220;
+ }
+ }
+ pLVPSA_Inst->pSpectralDataBufferWritePointer = pWrite;
+ pLVPSA_Inst->BufferUpdateSamplesCount = BufferUpdateSamplesCount;
+ pLVPSA_Inst->DownSamplingCount = (LVM_UINT16)(-ii);
+ }
+}
+
+/************************************************************************************/
+/* */
+/* FUNCTION: LVPSA_QPD_WritePeak */
+/* */
+/* DESCRIPTION: */
+/* Write a level value in the spectrum data buffer in the corresponding band. */
+/* */
+/* PARAMETERS: */
+/* pLVPSA_Inst Pointer to the LVPSA instance */
+/* ppWrite Pointer to pointer to the buffer */
+/* CallNumber Number of the band the value should be written in */
+/* Value Value to write in the spectrum data buffer */
+/* */
+/* RETURNS: void */
+/* */
+/************************************************************************************/
+void LVPSA_QPD_WritePeak( pLVPSA_InstancePr_t pLVPSA_Inst,
+ LVM_UINT8 **ppWrite,
+ LVM_INT16 BandIndex,
+ LVM_INT16 Value )
+{
+ LVM_UINT8 *pWrite = *ppWrite;
+
+
+ /* Write the value and update the write pointer */
+ *(pWrite + BandIndex) = (LVM_UINT8)(Value>>7);
+ pWrite += pLVPSA_Inst->nBands;
+ if (pWrite == (pLVPSA_Inst->pSpectralDataBufferStart + pLVPSA_Inst->nBands * pLVPSA_Inst->SpectralDataBufferLength))
+ {
+ pWrite = pLVPSA_Inst->pSpectralDataBufferStart;
+ }
+
+ *ppWrite = pWrite;
+
+}
+
diff --git a/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
new file mode 100755
index 0000000..f4a35c5
--- /dev/null
+++ b/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Tables.c
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+/************************************************************************/
+/* */
+/* Project:: PSA_01_ARMC_01 */
+/* $Author: beq07716 $*/
+/* $Revision: 1006 $*/
+/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/
+/* */
+/************************************************************************/
+
+
+/************************************************************************************/
+/* */
+/* Includes */
+/* */
+/************************************************************************************/
+
+#include "LVPSA.h"
+#include "LVPSA_QPD.h"
+/************************************************************************************/
+/* */
+/* Sample rate table */
+/* */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT16 LVPSA_SampleRateTab[] = { 8000, /* 8kS/s */
+ 11025,
+ 12000,
+ 16000,
+ 22050,
+ 24000,
+ 32000,
+ 44100,
+ 48000}; /* 48kS/s */
+
+/************************************************************************************/
+/* */
+/* Sample rate inverse table */
+/* */
+/************************************************************************************/
+
+/*
+ * Sample rate table for converting between the enumerated type and the actual
+ * frequency
+ */
+const LVM_UINT32 LVPSA_SampleRateInvTab[] = { 268435, /* 8kS/s */
+ 194783,
+ 178957,
+ 134218,
+ 97391,
+ 89478,
+ 67109,
+ 48696,
+ 44739}; /* 48kS/s */
+
+
+
+/************************************************************************************/
+/* */
+/* Number of samples in 20ms */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the number of samples
+ * during 20ms
+ */
+const LVM_UINT16 LVPSA_nSamplesBufferUpdate[] = { 160, /* 8kS/s */
+ 220,
+ 240,
+ 320,
+ 441,
+ 480,
+ 640,
+ 882,
+ 960}; /* 48kS/s */
+/************************************************************************************/
+/* */
+/* Down sampling factors */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for converting between the enumerated type and the down sampling factor
+ */
+const LVM_UINT16 LVPSA_DownSamplingFactor[] = { 5, /* 8000 S/s */
+ 7, /* 11025 S/s */
+ 8, /* 12000 S/s */
+ 10, /* 16000 S/s */
+ 15, /* 22050 S/s */
+ 16, /* 24000 S/s */
+ 21, /* 32000 S/s */
+ 30, /* 44100 S/s */
+ 32}; /* 48000 S/s */
+
+
+/************************************************************************************/
+/* */
+/* Coefficient calculation tables */
+/* */
+/************************************************************************************/
+
+/*
+ * Table for 2 * Pi / Fs
+ */
+const LVM_INT16 LVPSA_TwoPiOnFsTable[] = { 26354, /* 8kS/s */
+ 19123,
+ 17569,
+ 13177,
+ 9561,
+ 8785,
+ 6588,
+ 4781,
+ 4392}; /* 48kS/s */
+
+/*
+ * Gain table
+ */
+const LVM_INT16 LVPSA_GainTable[] = { 364, /* -15dB gain */
+ 408,
+ 458,
+ 514,
+ 577,
+ 647,
+ 726,
+ 815,
+ 914,
+ 1026,
+ 1151,
+ 1292,
+ 1449,
+ 1626,
+ 1825,
+ 2048, /* 0dB gain */
+ 2297,
+ 2578,
+ 2892,
+ 3245,
+ 3641,
+ 4096,
+ 4584,
+ 5144,
+ 5772,
+ 6476,
+ 7266,
+ 8153,
+ 9148,
+ 10264,
+ 11576}; /* +15dB gain */
+
+/************************************************************************************/
+/* */
+/* Cosone polynomial coefficients */
+/* */
+/************************************************************************************/
+
+/*
+ * Coefficients for calculating the cosine with the equation:
+ *
+ * Cos(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3 + a4*x^4 + a5*x^5)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi. The output is in the range 32767 to -32768 representing the range
+ * +1.0 to -1.0
+ */
+const LVM_INT16 LVPSA_CosCoef[] = { 3, /* Shifts */
+ 4096, /* a0 */
+ -36, /* a1 */
+ -19725, /* a2 */
+ -2671, /* a3 */
+ 23730, /* a4 */
+ -9490}; /* a5 */
+
+/*
+ * Coefficients for calculating the cosine error with the equation:
+ *
+ * CosErr(x) = (2^Shifts)*(a0 + a1*x + a2*x^2 + a3*x^3)
+ *
+ * These coefficients expect the input, x, to be in the range 0 to 32768 respresenting
+ * a range of 0 to Pi/25. The output is in the range 0 to 32767 representing the range
+ * 0.0 to 0.0078852986
+ *
+ * This is used to give a double precision cosine over the range 0 to Pi/25 using the
+ * the equation:
+ *
+ * Cos(x) = 1.0 - CosErr(x)
+ */
+const LVM_INT16 LVPSA_DPCosCoef[] = { 1, /* Shifts */
+ 0, /* a0 */
+ -6, /* a1 */
+ 16586, /* a2 */
+ -44}; /* a3 */
+
+/************************************************************************************/
+/* */
+/* Quasi peak filter coefficients table */
+/* */
+/************************************************************************************/
+const QPD_C32_Coefs LVPSA_QPD_Coefs[] = {
+
+ {0x80CEFD2B,0x00CB9B17}, /* 8kS/s */ /* LVPSA_SPEED_LOW */
+ {0x80D242E7,0x00CED11D},
+ {0x80DCBAF5,0x00D91679},
+ {0x80CEFD2B,0x00CB9B17},
+ {0x80E13739,0x00DD7CD3},
+ {0x80DCBAF5,0x00D91679},
+ {0x80D94BAF,0x00D5B7E7},
+ {0x80E13739,0x00DD7CD3},
+ {0x80DCBAF5,0x00D91679}, /* 48kS/s */
+
+ {0x8587513D,0x055C22CF}, /* 8kS/s */ /* LVPSA_SPEED_MEDIUM */
+ {0x859D2967,0x0570F007},
+ {0x85E2EFAC,0x05B34D79},
+ {0x8587513D,0x055C22CF},
+ {0x8600C7B9,0x05CFA6CF},
+ {0x85E2EFAC,0x05B34D79},
+ {0x85CC1018,0x059D8F69},
+ {0x8600C7B9,0x05CFA6CF},//{0x8600C7B9,0x05CFA6CF},
+ {0x85E2EFAC,0x05B34D79}, /* 48kS/s */
+
+ {0xA115EA7A,0x1CDB3F5C}, /* 8kS/s */ /* LVPSA_SPEED_HIGH */
+ {0xA18475F0,0x1D2C83A2},
+ {0xA2E1E950,0x1E2A532E},
+ {0xA115EA7A,0x1CDB3F5C},
+ {0xA375B2C6,0x1E943BBC},
+ {0xA2E1E950,0x1E2A532E},
+ {0xA26FF6BD,0x1DD81530},
+ {0xA375B2C6,0x1E943BBC},
+ {0xA2E1E950,0x1E2A532E}}; /* 48kS/s */
+