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