M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@ -0,0 +1,290 @@
/*
* 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.
*/
#ifndef _LVPSA_H_
#define _LVPSA_H_
#include "LVM_Types.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/****************************************************************************************/
/* */
/* CONSTANTS DEFINITIONS */
/* */
/****************************************************************************************/
/* Memory table*/
#define LVPSA_NR_MEMORY_REGIONS 4 /* Number of memory regions */
/****************************************************************************************/
/* */
/* TYPES DEFINITIONS */
/* */
/****************************************************************************************/
/* Memory Types */
typedef enum
{
LVPSA_PERSISTENT = LVM_PERSISTENT,
LVPSA_PERSISTENT_DATA = LVM_PERSISTENT_DATA,
LVPSA_PERSISTENT_COEF = LVM_PERSISTENT_COEF,
LVPSA_SCRATCH = LVM_SCRATCH,
LVPSA_MEMORY_DUMMY = LVM_MAXINT_32 /* Force 32 bits enum, don't use it! */
} LVPSA_MemoryTypes_en;
/* Level detection speed control parameters */
typedef enum
{
LVPSA_SPEED_LOW, /* Low speed level detection */
LVPSA_SPEED_MEDIUM, /* Medium speed level detection */
LVPSA_SPEED_HIGH, /* High speed level detection */
LVPSA_SPEED_DUMMY = LVM_MAXINT_32 /* Force 32 bits enum, don't use it! */
} LVPSA_LevelDetectSpeed_en;
/* Filter control parameters */
typedef struct
{
LVM_UINT16 CenterFrequency; /* Center frequency of the band-pass filter (in Hz) */
LVM_UINT16 QFactor; /* Quality factor of the filter (in 1/100) */
LVM_INT16 PostGain; /* Postgain to apply after the filtering (in dB Q16.0) */
} LVPSA_FilterParam_t;
/* LVPSA initialization parameters */
typedef struct
{
LVM_UINT16 SpectralDataBufferDuration; /* Spectral data buffer duration in time (ms in Q16.0) */
LVM_UINT16 MaxInputBlockSize; /* Maximum expected input block size (in samples) */
LVM_UINT16 nBands; /* Number of bands of the SA */
LVPSA_FilterParam_t *pFiltersParams; /* Points to nBands filter param structures for filters settings */
} LVPSA_InitParams_t, *pLVPSA_InitParams_t;
/* LVPSA control parameters */
typedef struct
{
LVM_Fs_en Fs; /* Input sampling rate */
LVPSA_LevelDetectSpeed_en LevelDetectionSpeed; /* Level detection speed */
} LVPSA_ControlParams_t, *pLVPSA_ControlParams_t;
/* Memory region definition */
typedef struct
{
LVM_UINT32 Size; /* Region size in bytes */
LVPSA_MemoryTypes_en Type; /* Region type */
void *pBaseAddress; /* Pointer to the region base address */
} LVPSA_MemoryRegion_t;
/* Memory table containing the region definitions */
typedef struct
{
LVPSA_MemoryRegion_t Region[LVPSA_NR_MEMORY_REGIONS];/* One definition for each region */
} LVPSA_MemTab_t;
/* Audio time type */
typedef LVM_INT32 LVPSA_Time;
/* Module instance Handle */
typedef void *pLVPSA_Handle_t;
/* LVPSA return codes */
typedef enum
{
LVPSA_OK, /* The function ran without any problem */
LVPSA_ERROR_INVALIDPARAM, /* A parameter is incorrect */
LVPSA_ERROR_WRONGTIME, /* An incorrect AudioTime is used */
LVPSA_ERROR_NULLADDRESS, /* A pointer has a NULL value */
LVPSA_RETURN_DUMMY = LVM_MAXINT_32 /* Force 32 bits enum, don't use it! */
} LVPSA_RETURN;
/*********************************************************************************************************************************
FUNCTIONS PROTOTYPE
**********************************************************************************************************************************/
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_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 */
/* pInitParams 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 );
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_Init */
/* */
/* DESCRIPTION: */
/* Initializes the LVPSA module. */
/* */
/* */
/* PARAMETERS: */
/* phInstance Pointer to the instance Handle */
/* pInitParams Pointer to the instance init parameters */
/* pControlParams Pointer to the instance control parameters */
/* pMemoryTable Pointer to the memory definition table */
/* */
/* */
/* 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 );
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_Control */
/* */
/* DESCRIPTION: */
/* Controls the LVPSA module. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pNewParams Pointer to the instance new control parameters */
/* */
/* RETURNS: */
/* LVPSA_OK Succeeds */
/* otherwise Error due to bad parameters */
/* */
/*********************************************************************************************************************************/
LVPSA_RETURN LVPSA_Control ( pLVPSA_Handle_t hInstance,
LVPSA_ControlParams_t *pNewParams );
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_Process */
/* */
/* DESCRIPTION: */
/* The process calculates the levels of the frequency bands. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pLVPSA_InputSamples Pointer to the input samples buffer */
/* InputBlockSize Number of mono samples to process */
/* AudioTime Playback time of the first input sample */
/* */
/* */
/* 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 );
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_GetSpectrum */
/* */
/* DESCRIPTION: */
/* This function is used for memory allocation and free. */
/* */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* GetSpectrumAudioTime Time to retrieve the values at */
/* pCurrentValues Pointer to an empty buffer : Current level values output */
/* pPeakValues Pointer to an empty buffer : Peak level values output */
/* */
/* */
/* 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 );
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_GetControlParams */
/* */
/* DESCRIPTION: */
/* Get the current control parameters of the LVPSA module. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pParams Pointer to an empty control parameters structure */
/* RETURNS: */
/* LVPSA_OK Succeeds */
/* otherwise Error due to bad parameters */
/* */
/*********************************************************************************************************************************/
LVPSA_RETURN LVPSA_GetControlParams ( pLVPSA_Handle_t hInstance,
LVPSA_ControlParams_t *pParams );
/*********************************************************************************************************************************/
/* */
/* FUNCTION: LVPSA_GetInitParams */
/* */
/* DESCRIPTION: */
/* Get the initialization parameters of the LVPSA module. */
/* */
/* PARAMETERS: */
/* hInstance Instance Handle */
/* pParams Pointer to an empty init parameters structure */
/* RETURNS: */
/* LVPSA_OK Succeeds */
/* otherwise Error due to bad parameters */
/* */
/*********************************************************************************************************************************/
LVPSA_RETURN LVPSA_GetInitParams ( pLVPSA_Handle_t hInstance,
LVPSA_InitParams_t *pParams );
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _LVPSA_H */

View File

@ -0,0 +1,707 @@
/*
* 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.
*/
#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);
}

View File

@ -0,0 +1,189 @@
/*
* 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.
*/
#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);
}

View File

@ -0,0 +1,169 @@
/*
* 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.
*/
#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);
}

View File

@ -0,0 +1,151 @@
/*
* 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.
*/
#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 */

View File

@ -0,0 +1,252 @@
/*
* 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.
*/
#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);
}

View File

@ -0,0 +1,90 @@
/*
* 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.
*/
#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

View File

@ -0,0 +1,42 @@
/*
* 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.
*/
#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;
}

View File

@ -0,0 +1,212 @@
/*
* 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.
*/
#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;
}

View File

@ -0,0 +1,241 @@
/*
* Copyright (C) 2004-2010 NXP Software
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/************************************************************************************/
/* */
/* Includes */
/* */
/************************************************************************************/
#include "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 */