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