LVPSA_Process.c revision d918324d44aa48b3b064ea9b87d0c520c38f15a9
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/************************************************************************************/
46LVPSA_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/************************************************************************************/
155LVPSA_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