diff options
Diffstat (limited to 'media/libeffects/lvm/lib/SpectrumAnalyzer/src')
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 */ + |