12c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*
22c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2004-2010 NXP Software
32c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Copyright (C) 2010 The Android Open Source Project
42c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
52c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Licensed under the Apache License, Version 2.0 (the "License");
62c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * you may not use this file except in compliance with the License.
72c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * You may obtain a copy of the License at
82c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
92c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *      http://www.apache.org/licenses/LICENSE-2.0
102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent *
112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * Unless required by applicable law or agreed to in writing, software
122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * distributed under the License is distributed on an "AS IS" BASIS,
132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * See the License for the specific language governing permissions and
152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent * limitations under the License.
162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent */
172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include    "LVPSA.h"
192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include    "LVPSA_Private.h"
202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include    "LVM_Macros.h"
212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#include    "VectorArithmetic.h"
222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent#define LVM_MININT_32   0x80000000
242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:            LVPSA_Process                                               */
292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  The process applies band pass filters to the signal. Each output                */
322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  feeds a quasi peak filter for level detection.                                  */
332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance           Pointer to the instance                                     */
362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pLVPSA_InputSamples Pointer to the input samples buffer                         */
372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  InputBlockSize      Number of mono samples to process                           */
382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  AudioTime           Playback time of the input samples                          */
392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVPSA_OK            Succeeds                                                    */
432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  otherwise           Error due to bad parameters                                 */
442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
462c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVPSA_RETURN LVPSA_Process           ( pLVPSA_Handle_t      hInstance,
472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                       LVM_INT16           *pLVPSA_InputSamples,
482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                       LVM_UINT16           InputBlockSize,
492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                       LVPSA_Time           AudioTime            )
502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVPSA_InstancePr_t     *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT16               *pScratch;
542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT16               ii;
552c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT32               AudioTimeInc;
562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    extern LVM_UINT32       LVPSA_SampleRateInvTab[];
572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_UINT8               *pWrite_Save;         /* Position of the write pointer at the beginning of the process  */
582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /******************************************************************************
602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent       CHECK PARAMETERS
612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    *******************************************************************************/
622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(hInstance == LVM_NULL || pLVPSA_InputSamples == LVM_NULL)
632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        return(LVPSA_ERROR_NULLADDRESS);
652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(InputBlockSize == 0 || InputBlockSize > pLVPSA_Inst->MaxInputBlockSize)
672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        return(LVPSA_ERROR_INVALIDPARAM);
692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pScratch = (LVM_INT16*)pLVPSA_Inst->MemoryTable.Region[LVPSA_MEMREGION_SCRATCH].pBaseAddress;
722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    pWrite_Save = pLVPSA_Inst->pSpectralDataBufferWritePointer;
732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /******************************************************************************
752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent       APPLY NEW SETTINGS IF NEEDED
762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    *******************************************************************************/
772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if (pLVPSA_Inst->bControlPending == LVM_TRUE)
782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pLVPSA_Inst->bControlPending = 0;
802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVPSA_ApplyNewSettings( pLVPSA_Inst);
812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /******************************************************************************
842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent       PROCESS SAMPLES
852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    *******************************************************************************/
862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /* Put samples in range [-0.5;0.5[ for BP filters (see Biquads documentation) */
872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Copy_16( pLVPSA_InputSamples,pScratch,(LVM_INT16)InputBlockSize);
882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    Shift_Sat_v16xv16(-1,pScratch,pScratch,(LVM_INT16)InputBlockSize);
892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    for (ii = 0; ii < pLVPSA_Inst->nRelevantFilters; ii++)
912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        switch(pLVPSA_Inst->pBPFiltersPrecision[ii])
932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            case LVPSA_SimplePrecisionFilter:
952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                BP_1I_D16F16C14_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                              pScratch,
972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                              pScratch + InputBlockSize,
982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                              (LVM_INT16)InputBlockSize);
992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                break;
1002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            case LVPSA_DoublePrecisionFilter:
1022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                BP_1I_D16F32C30_TRC_WRA_01  ( &pLVPSA_Inst->pBP_Instances[ii],
1032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                              pScratch,
1042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                              pScratch + InputBlockSize,
1052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                              (LVM_INT16)InputBlockSize);
1062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                break;
1072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            default:
1082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                break;
1092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        LVPSA_QPD_Process   ( pLVPSA_Inst,
1132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                              pScratch + InputBlockSize,
1142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                              (LVM_INT16)InputBlockSize,
1152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                              ii);
1162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /******************************************************************************
1192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent       UPDATE SpectralDataBufferAudioTime
1202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    *******************************************************************************/
1212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(pLVPSA_Inst->pSpectralDataBufferWritePointer != pWrite_Save)
1232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        MUL32x32INTO32((AudioTime + (LVM_INT32)((LVM_INT32)pLVPSA_Inst->LocalSamplesCount*1000)),
1252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                        (LVM_INT32)LVPSA_SampleRateInvTab[pLVPSA_Inst->CurrentParams.Fs],
1262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                        AudioTimeInc,
1272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                        LVPSA_FsInvertShift)
1282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pLVPSA_Inst->SpectralDataBufferAudioTime = AudioTime + AudioTimeInc;
1292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVPSA_OK);
1322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
1332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
1362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* FUNCTION:            LVPSA_GetSpectrum                                           */
1382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* DESCRIPTION:                                                                     */
1402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  Gets the levels values at a certain point in time                               */
1412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* PARAMETERS:                                                                      */
1442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  hInstance            Pointer to the instance                                    */
1452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  GetSpectrumAudioTime Retrieve the values at this time                           */
1462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pCurrentValues       Pointer to a buffer that will contain levels' values       */
1472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  pMaxValues           Pointer to a buffer that will contain max levels' values   */
1482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/* RETURNS:                                                                         */
1512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  LVPSA_OK            Succeeds                                                    */
1522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*  otherwise           Error due to bad parameters                                 */
1532c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/*                                                                                  */
1542c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent/************************************************************************************/
1552c8e5cab3faa6d360e222b7a6c40a80083d021acEric LaurentLVPSA_RETURN LVPSA_GetSpectrum       ( pLVPSA_Handle_t      hInstance,
1562c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                       LVPSA_Time           GetSpectrumAudioTime,
1572c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                       LVM_UINT8           *pCurrentValues,
1582c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                                       LVM_UINT8           *pPeakValues           )
1592c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1602c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent{
1612c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1622c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVPSA_InstancePr_t      *pLVPSA_Inst = (LVPSA_InstancePr_t*)hInstance;
1632c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_INT32               StatusDelta, ii;
1642c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    LVM_UINT8               *pRead;
1652c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1662c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(hInstance == LVM_NULL || pCurrentValues == LVM_NULL || pPeakValues == LVM_NULL)
1672c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1682c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        return(LVPSA_ERROR_NULLADDRESS);
1692c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1702c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1712c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1722c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /* First find the place where to look in the status buffer */
1732c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(GetSpectrumAudioTime <= pLVPSA_Inst->SpectralDataBufferAudioTime)
1742c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1752c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        MUL32x32INTO32((pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift);
1762c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if((StatusDelta * LVPSA_InternalRefreshTime) != (pLVPSA_Inst->SpectralDataBufferAudioTime - GetSpectrumAudioTime))
1772c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
1782c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            StatusDelta += 1;
1792c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1802c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1812c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    else
1822c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
1832c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        /* This part handles the wrap around */
1842c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        MUL32x32INTO32(((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime)),LVPSA_InternalRefreshTimeInv,StatusDelta,LVPSA_InternalRefreshTimeShift)
1852c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if(((LVM_INT32)(StatusDelta * LVPSA_InternalRefreshTime)) != ((LVM_INT32)((pLVPSA_Inst->SpectralDataBufferAudioTime - (LVM_INT32)LVM_MININT_32) + ((LVM_INT32)LVM_MAXINT_32 - GetSpectrumAudioTime))))
1862c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
1872c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            StatusDelta += 1;
1882c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
1892c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
1902c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /* Check whether the desired level is not too "old" (see 2.10 in LVPSA_DesignNotes.doc)*/
1912c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if(
1922c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        ((GetSpectrumAudioTime < pLVPSA_Inst->SpectralDataBufferAudioTime)&&
1932c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         ((GetSpectrumAudioTime<0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>0))&&
1942c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         (((LVM_INT32)(-GetSpectrumAudioTime + pLVPSA_Inst->SpectralDataBufferAudioTime))>LVM_MAXINT_32))||
1952c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
1962c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         ((GetSpectrumAudioTime > pLVPSA_Inst->SpectralDataBufferAudioTime)&&
1972c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime>=0))||
1982c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent          ((GetSpectrumAudioTime<=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))||
1992c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         (((GetSpectrumAudioTime>=0)&&(pLVPSA_Inst->SpectralDataBufferAudioTime<=0))&&
2002c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent         (((LVM_INT32)(GetSpectrumAudioTime - pLVPSA_Inst->SpectralDataBufferAudioTime))<LVM_MAXINT_32))))||
2012c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2022c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (StatusDelta > (LVM_INT32)pLVPSA_Inst->SpectralDataBufferLength) ||
2032c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        (!StatusDelta))
2042c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2052c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
2062c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2072c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            pCurrentValues[ii]  = 0;
2082c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            pPeakValues[ii]      = 0;
2092c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2102c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        return(LVPSA_OK);
2112c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2122c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /* Set the reading pointer */
2132c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    if((LVM_INT32)(StatusDelta * pLVPSA_Inst->nBands) > (pLVPSA_Inst->pSpectralDataBufferWritePointer - pLVPSA_Inst->pSpectralDataBufferStart))
2142c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2152c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer + (pLVPSA_Inst->SpectralDataBufferLength - (LVM_UINT32)StatusDelta) * pLVPSA_Inst->nBands;
2162c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2172c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    else
2182c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2192c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pRead = pLVPSA_Inst->pSpectralDataBufferWritePointer  - StatusDelta * pLVPSA_Inst->nBands;
2202c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2212c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2222c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2232c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    /* Read the status buffer and fill the output buffers */
2242c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    for(ii = 0; ii < pLVPSA_Inst->nBands; ii++)
2252c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    {
2262c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pCurrentValues[ii] = pRead[ii];
2272c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        if(pLVPSA_Inst->pPreviousPeaks[ii] <= pRead[ii])
2282c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2292c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            pLVPSA_Inst->pPreviousPeaks[ii] = pRead[ii];
2302c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2312c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        else if(pLVPSA_Inst->pPreviousPeaks[ii] != 0)
2322c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        {
2332c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            LVM_INT32 temp;
2342c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            /*Re-compute max values for decay */
2352c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            temp = (LVM_INT32)(LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]);
2362c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            temp = ((temp * LVPSA_MAXLEVELDECAYFACTOR)>>LVPSA_MAXLEVELDECAYSHIFT);
2372c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            /* If the gain has no effect, "help" the value to increase */
2382c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            if(temp == (LVPSA_MAXUNSIGNEDCHAR - pLVPSA_Inst->pPreviousPeaks[ii]))
2392c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            {
2402c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent                temp += 1;
2412c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            }
2422c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            /* Saturate */
2432c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            temp = (temp > LVPSA_MAXUNSIGNEDCHAR) ? LVPSA_MAXUNSIGNEDCHAR : temp;
2442c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            /* Store new max level */
2452c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent            pLVPSA_Inst->pPreviousPeaks[ii] =  (LVM_UINT8)(LVPSA_MAXUNSIGNEDCHAR - temp);
2462c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        }
2472c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2482c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent        pPeakValues[ii] = pLVPSA_Inst->pPreviousPeaks[ii];
2492c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    }
2502c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent
2512c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent    return(LVPSA_OK);
2522c8e5cab3faa6d360e222b7a6c40a80083d021acEric Laurent}
253