Home | History | Annotate | Download | only in src
      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