LVPSA_Process.c revision 2c8e5cab3faa6d360e222b7a6c40a80083d021ac
1/* 2 * Copyright (C) 2004-2010 NXP Software 3 * Copyright (C) 2010 The Android Open Source Project 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18/************************************************************************/ 19/* */ 20/* Project:: PSA_01_ARMC_01 */ 21/* $Author: beq07716 $*/ 22/* $Revision: 1006 $*/ 23/* $Date: 2010-06-28 14:01:47 +0200 (Mon, 28 Jun 2010) $*/ 24/* */ 25/************************************************************************/ 26#include "LVPSA.h" 27#include "LVPSA_Private.h" 28#include "LVM_Macros.h" 29#include "VectorArithmetic.h" 30 31#define LVM_MININT_32 0x80000000 32 33 34/************************************************************************************/ 35/* */ 36/* FUNCTION: LVPSA_Process */ 37/* */ 38/* DESCRIPTION: */ 39/* The process applies band pass filters to the signal. Each output */ 40/* feeds a quasi peak filter for level detection. */ 41/* */ 42/* PARAMETERS: */ 43/* hInstance Pointer to the instance */ 44/* pLVPSA_InputSamples Pointer to the input samples buffer */ 45/* InputBlockSize Number of mono samples to process */ 46/* AudioTime Playback time of the input samples */ 47/* */ 48/* */ 49/* RETURNS: */ 50/* LVPSA_OK Succeeds */ 51/* otherwise Error due to bad parameters */ 52/* */ 53/************************************************************************************/ 54LVPSA_RETURN LVPSA_Process ( pLVPSA_Handle_t hInstance, 55 LVM_INT16 *pLVPSA_InputSamples, 56 LVM_UINT16 InputBlockSize, 57 LVPSA_Time AudioTime ) 58 59{ 60 LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance; 61 LVM_INT16 *pScratch; 62 LVM_INT16 ii; 63 LVM_INT32 AudioTimeInc; 64 extern LVM_UINT32 LVPSA_SampleRateInvTab[]; 65 LVM_UINT8 *pWrite_Save; /* Position of the write pointer at the beginning of the process */ 66 67 /****************************************************************************** 68 CHECK PARAMETERS 69 *******************************************************************************/ 70 if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL) 71 { 72 return(LVPSA_ERROR_NULLADDRESS); 73 } 74 if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize) 75 { 76 return(LVPSA_ERROR_INVALIDPARAM); 77 } 78 79 pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress; 80 pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer; 81 82 /****************************************************************************** 83 APPLY NEW SETTINGS IF NEEDED 84 *******************************************************************************/ 85 if (pLVPSA_Inst->bControlPending == LVM_TRUE) 86 { 87 pLVPSA_Inst->bControlPending = 0; 88 LVPSA_ApplyNewSettings( pLVPSA_Inst); 89 } 90 91 /****************************************************************************** 92 PROCESS SAMPLES 93 *******************************************************************************/ 94 /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */ 95 Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize); 96 Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize); 97 98 for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++) 99 { 100 switch(pLVPSA_Inst->pBPFiltersPrecision[ii]) 101 { 102 case LVPSA_SimplePrecisionFilter: 103 BP_1I_D16F16C14_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii], 104 pScratch, 105 pScratch + InputBlockSize, 106 (LVM_INT16)InputBlockSize); 107 break; 108 109 case LVPSA_DoublePrecisionFilter: 110 BP_1I_D16F32C30_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii], 111 pScratch, 112 pScratch + InputBlockSize, 113 (LVM_INT16)InputBlockSize); 114 break; 115 default: 116 break; 117 } 118 119 120 LVPSA_QPD_Process ( pLVPSA_Inst, 121 pScratch + InputBlockSize, 122 (LVM_INT16)InputBlockSize, 123 ii); 124 } 125 126 /****************************************************************************** 127 UPDATE SpectralDataBufferAudioTime 128 *******************************************************************************/ 129 130 if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save) 131 { 132 MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)), 133 (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs], 134 AudioTimeInc, 135 LVPSA_FsInvertShift) 136 pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc; 137 } 138 139 return(LVPSA_OK); 140} 141 142 143/************************************************************************************/ 144/* */ 145/* FUNCTION: LVPSA_GetSpectrum */ 146/* */ 147/* DESCRIPTION: */ 148/* Gets the levels values at a certain point in time */ 149/* */ 150/* */ 151/* PARAMETERS: */ 152/* hInstance Pointer to the instance */ 153/* GetSpectrumAudioTime Retrieve the values at this time */ 154/* pCurrentValues Pointer to a buffer that will contain levels' values */ 155/* pMaxValues Pointer to a buffer that will contain max levels' values */ 156/* */ 157/* */ 158/* RETURNS: */ 159/* LVPSA_OK Succeeds */ 160/* otherwise Error due to bad parameters */ 161/* */ 162/************************************************************************************/ 163LVPSA_RETURN LVPSA_GetSpectrum ( pLVPSA_Handle_t hInstance, 164 LVPSA_Time GetSpectrumAudioTime, 165 LVM_UINT8 *pCurrentValues, 166 LVM_UINT8 *pPeakValues ) 167 168{ 169 170 LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance; 171 LVM_INT32 StatusDelta, ii; 172 LVM_UINT8 *pRead; 173 174 if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL) 175 { 176 return(LVPSA_ERROR_NULLADDRESS); 177 } 178 179 180 /* First find the place where to look in the status buffer */ 181 if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime) 182 { 183 MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift); 184 if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime)) 185 { 186 StatusDelta += 1; 187 } 188 } 189 else 190 { 191 /* This part handles the wrap around */ 192 MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift) 193 if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)))) 194 { 195 StatusDelta += 1; 196 } 197 } 198 /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/ 199 if( 200 ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&& 201 ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&& 202 (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))|| 203 204 ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&& 205 (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))|| 206 ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))|| 207 (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&& 208 (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))|| 209 210 (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) || 211 (!StatusDelta)) 212 { 213 for(ii = 0; ii < pLVPSA_Inst->nBands; ii++) 214 { 215 pCurrentValues[ii] = 0; 216 pPeakValues[ii] = 0; 217 } 218 return(LVPSA_OK); 219 } 220 /* Set the reading pointer */ 221 if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart)) 222 { 223 pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands; 224 } 225 else 226 { 227 pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer - StatusDelta * pLVPSA_Inst->nBands; 228 } 229 230 231 /* Read the status buffer and fill the output buffers */ 232 for(ii = 0; ii < pLVPSA_Inst->nBands; ii++) 233 { 234 pCurrentValues[ii] = pRead[ii]; 235 if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii]) 236 { 237 pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii]; 238 } 239 else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0) 240 { 241 LVM_INT32 temp; 242 /*Re-compute max values for decay */ 243 temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]); 244 temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT); 245 /* If the gain has no effect, "help" the value to increase */ 246 if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii])) 247 { 248 temp += 1; 249 } 250 /* Saturate */ 251 temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp; 252 /* Store new max level */ 253 pLVPSA_Inst->pPreviousPeaks[ii] = (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp); 254 } 255 256 pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii]; 257 } 258 259 return(LVPSA_OK); 260} 261