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 #ifdef BUILD_FLOAT
LVPSA_Process(pLVPSA_Handle_t hInstance,LVM_FLOAT * pLVPSA_InputSamples,LVM_UINT16 InputBlockSize,LVPSA_Time AudioTime)47 LVPSA_RETURN LVPSA_Process ( pLVPSA_Handle_t hInstance,
48 LVM_FLOAT *pLVPSA_InputSamples,
49 LVM_UINT16 InputBlockSize,
50 LVPSA_Time AudioTime )
51
52 {
53 LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
54 LVM_FLOAT *pScratch;
55 LVM_INT16 ii;
56 LVM_INT32 AudioTimeInc;
57 extern LVM_UINT32 LVPSA_SampleRateInvTab[];
58 LVM_UINT8 *pWrite_Save; /* Position of the write pointer
59 at the beginning of the process */
60
61 /******************************************************************************
62 CHECK PARAMETERS
63 *******************************************************************************/
64 if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
65 {
66 return(LVPSA_ERROR_NULLADDRESS);
67 }
68 if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
69 {
70 return(LVPSA_ERROR_INVALIDPARAM);
71 }
72
73 pScratch = (LVM_FLOAT*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
74 pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
75
76 /******************************************************************************
77 APPLY NEW SETTINGS IF NEEDED
78 *******************************************************************************/
79 if (pLVPSA_Inst->bControlPending == LVM_TRUE)
80 {
81 pLVPSA_Inst->bControlPending = 0;
82 LVPSA_ApplyNewSettings( pLVPSA_Inst);
83 }
84
85 /******************************************************************************
86 PROCESS SAMPLES
87 *******************************************************************************/
88 /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
89 Copy_Float(pLVPSA_InputSamples, pScratch, (LVM_INT16)InputBlockSize);
90 Shift_Sat_Float(-1, pScratch, pScratch, (LVM_INT16)InputBlockSize);
91
92 for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
93 {
94 switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
95 {
96 case LVPSA_SimplePrecisionFilter:
97 BP_1I_D16F16C14_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
98 pScratch,
99 pScratch + InputBlockSize,
100 (LVM_INT16)InputBlockSize);
101 break;
102
103 case LVPSA_DoublePrecisionFilter:
104 BP_1I_D16F32C30_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
105 pScratch,
106 pScratch + InputBlockSize,
107 (LVM_INT16)InputBlockSize);
108 break;
109 default:
110 break;
111 }
112
113
114 LVPSA_QPD_Process_Float ( pLVPSA_Inst,
115 pScratch + InputBlockSize,
116 (LVM_INT16)InputBlockSize,
117 ii);
118 }
119
120 /******************************************************************************
121 UPDATE SpectralDataBufferAudioTime
122 *******************************************************************************/
123
124 if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
125 {
126 MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
127 (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
128 AudioTimeInc,
129 LVPSA_FsInvertShift)
130 pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
131 }
132
133 return(LVPSA_OK);
134 }
135 #else
LVPSA_Process(pLVPSA_Handle_t hInstance,LVM_INT16 * pLVPSA_InputSamples,LVM_UINT16 InputBlockSize,LVPSA_Time AudioTime)136 LVPSA_RETURN LVPSA_Process ( pLVPSA_Handle_t hInstance,
137 LVM_INT16 *pLVPSA_InputSamples,
138 LVM_UINT16 InputBlockSize,
139 LVPSA_Time AudioTime )
140
141 {
142 LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
143 LVM_INT16 *pScratch;
144 LVM_INT16 ii;
145 LVM_INT32 AudioTimeInc;
146 extern LVM_UINT32 LVPSA_SampleRateInvTab[];
147 LVM_UINT8 *pWrite_Save; /* Position of the write pointer at the beginning of the process */
148
149 /******************************************************************************
150 CHECK PARAMETERS
151 *******************************************************************************/
152 if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
153 {
154 return(LVPSA_ERROR_NULLADDRESS);
155 }
156 if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
157 {
158 return(LVPSA_ERROR_INVALIDPARAM);
159 }
160
161 pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
162 pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
163
164 /******************************************************************************
165 APPLY NEW SETTINGS IF NEEDED
166 *******************************************************************************/
167 if (pLVPSA_Inst->bControlPending == LVM_TRUE)
168 {
169 pLVPSA_Inst->bControlPending = 0;
170 LVPSA_ApplyNewSettings( pLVPSA_Inst);
171 }
172
173 /******************************************************************************
174 PROCESS SAMPLES
175 *******************************************************************************/
176 /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
177 Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize);
178 Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize);
179
180 for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
181 {
182 switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
183 {
184 case LVPSA_SimplePrecisionFilter:
185 BP_1I_D16F16C14_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
186 pScratch,
187 pScratch + InputBlockSize,
188 (LVM_INT16)InputBlockSize);
189 break;
190
191 case LVPSA_DoublePrecisionFilter:
192 BP_1I_D16F32C30_TRC_WRA_01 ( &pLVPSA_Inst->pBP_Instances[ii],
193 pScratch,
194 pScratch + InputBlockSize,
195 (LVM_INT16)InputBlockSize);
196 break;
197 default:
198 break;
199 }
200
201
202 LVPSA_QPD_Process ( pLVPSA_Inst,
203 pScratch + InputBlockSize,
204 (LVM_INT16)InputBlockSize,
205 ii);
206 }
207
208 /******************************************************************************
209 UPDATE SpectralDataBufferAudioTime
210 *******************************************************************************/
211
212 if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
213 {
214 MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
215 (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
216 AudioTimeInc,
217 LVPSA_FsInvertShift)
218 pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
219 }
220
221 return(LVPSA_OK);
222 }
223 #endif
224
225 /************************************************************************************/
226 /* */
227 /* FUNCTION: LVPSA_GetSpectrum */
228 /* */
229 /* DESCRIPTION: */
230 /* Gets the levels values at a certain point in time */
231 /* */
232 /* */
233 /* PARAMETERS: */
234 /* hInstance Pointer to the instance */
235 /* GetSpectrumAudioTime Retrieve the values at this time */
236 /* pCurrentValues Pointer to a buffer that will contain levels' values */
237 /* pMaxValues Pointer to a buffer that will contain max levels' values */
238 /* */
239 /* */
240 /* RETURNS: */
241 /* LVPSA_OK Succeeds */
242 /* otherwise Error due to bad parameters */
243 /* */
244 /************************************************************************************/
LVPSA_GetSpectrum(pLVPSA_Handle_t hInstance,LVPSA_Time GetSpectrumAudioTime,LVM_UINT8 * pCurrentValues,LVM_UINT8 * pPeakValues)245 LVPSA_RETURN LVPSA_GetSpectrum ( pLVPSA_Handle_t hInstance,
246 LVPSA_Time GetSpectrumAudioTime,
247 LVM_UINT8 *pCurrentValues,
248 LVM_UINT8 *pPeakValues )
249
250 {
251
252 LVPSA_InstancePr_t *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
253 LVM_INT32 StatusDelta, ii;
254 LVM_UINT8 *pRead;
255
256 if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
257 {
258 return(LVPSA_ERROR_NULLADDRESS);
259 }
260
261
262 /* First find the place where to look in the status buffer */
263 if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
264 {
265 MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
266 if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
267 {
268 StatusDelta += 1;
269 }
270 }
271 else
272 {
273 /* This part handles the wrap around */
274 MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
275 if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
276 {
277 StatusDelta += 1;
278 }
279 }
280 /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
281 if(
282 ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
283 ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
284 (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
285
286 ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
287 (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
288 ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
289 (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
290 (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
291
292 (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
293 (!StatusDelta))
294 {
295 for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
296 {
297 pCurrentValues[ii] = 0;
298 pPeakValues[ii] = 0;
299 }
300 return(LVPSA_OK);
301 }
302 /* Set the reading pointer */
303 if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
304 {
305 pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
306 }
307 else
308 {
309 pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer - StatusDelta * pLVPSA_Inst->nBands;
310 }
311
312
313 /* Read the status buffer and fill the output buffers */
314 for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
315 {
316 pCurrentValues[ii] = pRead[ii];
317 if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
318 {
319 pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
320 }
321 else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
322 {
323 LVM_INT32 temp;
324 /*Re-compute max values for decay */
325 temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
326 temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
327 /* If the gain has no effect, "help" the value to increase */
328 if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
329 {
330 temp += 1;
331 }
332 /* Saturate */
333 temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
334 /* Store new max level */
335 pLVPSA_Inst->pPreviousPeaks[ii] = (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
336 }
337
338 pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
339 }
340
341 return(LVPSA_OK);
342 }
343