summaryrefslogtreecommitdiffstats
path: root/media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c
diff options
context:
space:
mode:
Diffstat (limited to 'media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c')
-rwxr-xr-xmedia/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c260
1 files changed, 260 insertions, 0 deletions
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);
+}