diff options
Diffstat (limited to 'media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c')
-rwxr-xr-x | media/libeffects/lvm/lib/SpectrumAnalyzer/src/LVPSA_Process.c | 260 |
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); +} |