• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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