LCOV - code coverage report
Current view: top level - lib_dec - TonalComponentDetection_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 401 661 60.7 %
Date: 2025-05-03 01:55:50 Functions: 11 18 61.1 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #define _USE_MATH_DEFINES
       6             : 
       7             : #include <assert.h>
       8             : #include <stdint.h>
       9             : #include "options.h"
      10             : #include "cnst.h"
      11             : #include "rom_basop_util.h"
      12             : #include "rom_com.h"
      13             : #include "basop_util.h"
      14             : #include "prot_fx.h"
      15             : #include "ivas_prot_fx.h"
      16             : 
      17             : /*---------------------------------------------------------------------*
      18             :  * Local function prototypes
      19             :  *---------------------------------------------------------------------*/
      20             : static void calcPseudoSpec( const Word32 *mdctSpec, const Word16 mdctSpec_exp, const Word16 nSamples, Word16 floorPowerSpectrum, Word32 *powerSpec, Word16 *powerSpec_exp );
      21             : static void getEnvelope( const Word16 nSamples, const Word32 *powerSpec, Word16 F0, Word32 *envelope, Word32 *smoothedSpectrum );
      22             : static void GetF0( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word16 *const pF0 );
      23             : static void ivas_GetF0_fx( Word16 const nSamples, Word16 const nSamplesCore, Word32 const *const powerSpectrum, Word32 const pitchLag, Word16 *const pOrigF0, Word16 *const pF0 );
      24             : static void findStrongestHarmonics( const Word16 nSamples, const Word32 *powerSpectrum, const Word16 F0, const Word16 nTotalHarmonics, Word16 *pHarmonicIndexes, Word16 *pnHarmonics );
      25             : static void CorrectF0( const Word16 *pHarmonicIndexes, const Word16 nHarmonics, Word16 *pF0 );
      26             : static void ivas_CorrectF0_fx( const Word16 *pHarmonicIndexes, const Word16 nHarmonics, Word16 *pF0 );
      27             : static void findCandidates( const Word16 nSamples, const Word32 *MDCTSpectrum, const Word16 MDCTSpectrum_exp, Word16 *thresholdModificationNew, Word16 floorPowerSpectrum );
      28             : static void modifyThreshold( Word16 i, Word16 F0, Word16 threshold, Word16 *thresholdModification );
      29             : static void modifyThresholds( Word16 F0, Word16 origF0, Word16 *thresholdModification );
      30             : static void RefineThresholdsUsingPitch( const Word16 nSamples, const Word16 nSamplesCore, const Word32 powerSpectrum[], const Word32 lastPitchLag, const Word32 currentPitchLag, Word16 *pF0, Word16 *thresholdModification );
      31             : static void ivas_RefineThresholdsUsingPitch_fx( const Word16 nSamples, const Word16 nSamplesCore, const Word32 powerSpectrum[], const Word32 lastPitchLag, const Word32 currentPitchLag, Word16 *pF0, Word16 *thresholdModification );
      32             : static void findTonalComponents( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, Word16 F0, Word16 *thresholdModification, Word16 element_mode );
      33             : static void ivas_findTonalComponents_fx( Word16 *indexOfTonalPeak, Word16 *lowerIndex, Word16 *upperIndex, Word16 *numIndexes, Word16 nSamples, const Word32 *powerSpectrum, const Word16 powerSpectrum_e, Word16 F0, Word16 *thresholdModification, Word16 element_mode );
      34             : 
      35             : /*-------------------------------------------------------------------*
      36             :  * DetectTonalComponents()
      37             :  *
      38             :  * Detect tonal components in the lastMDCTSpectrum, use
      39             :  * secondLastPowerSpectrum for the precise location of the peaks and
      40             :  * store them in indexOfTonalPeak.  Updates lowerIndex, upperIndex,
      41             :  * pNumIndexes accordingly.
      42             :  *-------------------------------------------------------------------*/
      43             : 
      44        1425 : void ivas_DetectTonalComponents_fx(
      45             :     Word16 indexOfTonalPeak[],    /*Q0*/
      46             :     Word16 lowerIndex[],          /*Q0*/
      47             :     Word16 upperIndex[],          /*Q0*/
      48             :     Word16 *pNumIndexes,          /*Q0*/
      49             :     const Word32 lastPitchLag,    /*Qx*/
      50             :     const Word32 currentPitchLag, /*Qx*/
      51             :     const Word16 lastMDCTSpectrum[],
      52             :     const Word16 lastMDCTSpectrum_exp,
      53             :     const Word16 scaleFactors[],
      54             :     const Word16 scaleFactors_exp[],
      55             :     const Word16 scaleFactors_max_e,
      56             :     const Word32 secondLastPowerSpectrum[], /*Q31-secondLastPowerSpectrum_e*/
      57             :     const Word16 secondLastPowerSpectrum_e,
      58             :     const Word16 nSamples,
      59             :     const Word16 nSamplesCore,
      60             :     Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins  Q0*/
      61             :     const PsychoacousticParameters *psychParamsCurrent,
      62             :     Word16 element_mode /* i: element mode */
      63             : )
      64             : {
      65             :     Word16 F0;
      66             :     Word16 thresholdModification[L_FRAME_MAX], lastMDCTSpect_exp;
      67             :     Word32 pScaledMdctSpectrum[L_FRAME_MAX];
      68             :     Word16 nBands;
      69             :     Word32 sns_int_scf_fx[FDNS_NPTS]; /*Q16*/
      70             :     Word16 q_pScaledMdctSpectrum;
      71             : 
      72        1425 :     set32_fx( pScaledMdctSpectrum, 0, L_FRAME_MAX );
      73             : 
      74      751351 :     FOR( Word16 i = 0; i < nSamples; i++ )
      75             :     {
      76      749926 :         pScaledMdctSpectrum[i] = L_shl( lastMDCTSpectrum[i], 16 ); /*15-lastMDCTSpectrum_exp+16 -> 31 - lastMDCTSpectrum_exp*/
      77      749926 :         move32();
      78             :     }
      79       92625 :     FOR( Word16 i = 0; i < FDNS_NPTS; i++ )
      80             :     {
      81       91200 :         sns_int_scf_fx[i] = L_shl_sat( scaleFactors[i], add( 1, scaleFactors_exp[i] ) ); // Q16
      82       91200 :         move32();
      83             :     }
      84        1425 :     IF( psychParamsCurrent == NULL )
      85             :     {
      86         697 :         nBands = FDNS_NPTS;
      87         697 :         move16();
      88             :         // PMT("add nBands argument to mdct_shaping_16")
      89             : 
      90         697 :         mdct_shaping_16( lastMDCTSpectrum, nSamplesCore, nSamples, scaleFactors, scaleFactors_exp, scaleFactors_max_e, pScaledMdctSpectrum );
      91         697 :         lastMDCTSpect_exp = add( lastMDCTSpectrum_exp, scaleFactors_max_e );
      92             :     }
      93             :     ELSE
      94             :     {
      95         728 :         q_pScaledMdctSpectrum = sub( 31, lastMDCTSpectrum_exp );
      96         728 :         sns_shape_spectrum_fx( pScaledMdctSpectrum, &q_pScaledMdctSpectrum, psychParamsCurrent, sns_int_scf_fx, 16, nSamplesCore, NULL );
      97         728 :         q_pScaledMdctSpectrum = add( q_pScaledMdctSpectrum, 1 );
      98         728 :         Word16 tmp_e = sub( 31, q_pScaledMdctSpectrum );
      99         728 :         nBands = psychParamsCurrent->nBands;
     100         728 :         move16();
     101             :         // till nSamplesCore different Q and nSamples - nSamplesCore in different Q
     102         728 :         Scale_sig32( pScaledMdctSpectrum + nSamplesCore, sub( nSamples, nSamplesCore ), sub( lastMDCTSpectrum_exp, tmp_e ) ); /*q_pScaledMdctSpectrum+lastMDCTSpectrum_exp-tmp_e*/
     103         728 :         lastMDCTSpect_exp = sub( 31, q_pScaledMdctSpectrum );
     104             : 
     105      119351 :         FOR( Word16 i = nSamplesCore; i < nSamples; ++i )
     106             :         {
     107      118623 :             Word64 tmp = W_mult_32_32( pScaledMdctSpectrum[i], sns_int_scf_fx[nBands - 1] ); /*q_pScaledMdctSpectrum+16+1*/
     108      118623 :             pScaledMdctSpectrum[i] = W_extract_h( W_shl( tmp, Q15 ) );                       /*q_pScaledMdctSpectrum*/
     109      118623 :             move32();
     110             :         }
     111             :     }
     112             : 
     113             :     /* Guard bit */
     114        1425 :     lastMDCTSpect_exp = add( lastMDCTSpect_exp, 1 );
     115        1425 :     scale_sig32( pScaledMdctSpectrum, nSamples, -1 ); /*q_pScaledMdctSpectrum - 1*/
     116             : 
     117             :     /* Find peak candidates in the last frame. */
     118        1425 :     findCandidates( nSamples, pScaledMdctSpectrum, lastMDCTSpect_exp, thresholdModification, floorPowerSpectrum );
     119             : 
     120             :     /* Refine peak candidates using the pitch information */
     121        1425 :     ivas_RefineThresholdsUsingPitch_fx( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification );
     122             : 
     123             :     /* Find peaks in the second last frame */
     124        1425 :     ivas_findTonalComponents_fx( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, secondLastPowerSpectrum_e, F0, thresholdModification, element_mode );
     125        1425 : }
     126             : 
     127           0 : void DetectTonalComponents(
     128             :     Word16 indexOfTonalPeak[],    /*Q0*/
     129             :     Word16 lowerIndex[],          /*Q0*/
     130             :     Word16 upperIndex[],          /*Q0*/
     131             :     Word16 *pNumIndexes,          /*Q0*/
     132             :     const Word32 lastPitchLag,    /*Qx*/
     133             :     const Word32 currentPitchLag, /*Qx*/
     134             :     const Word16 lastMDCTSpectrum[],
     135             :     const Word16 lastMDCTSpectrum_exp,
     136             :     const Word16 scaleFactors[],
     137             :     const Word16 scaleFactors_exp[],
     138             :     const Word16 scaleFactors_max_e,
     139             :     const Word32 secondLastPowerSpectrum[], /*Qx*/
     140             :     const Word16 nSamples,
     141             :     const Word16 nSamplesCore,
     142             :     Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins  Q0*/
     143             :     Word16 element_mode
     144             : #ifdef IVAS_CODE_MDCT_GSHAPE
     145             :     ,
     146             :     const PsychoacousticParameters *psychParamsCurrent
     147             : #endif
     148             : )
     149             : {
     150             :     Word16 F0;
     151             :     Word16 thresholdModification[L_FRAME_MAX], lastMDCTSpect_exp;
     152             :     Word32 pScaledMdctSpectrum[L_FRAME_MAX];
     153             : #ifdef IVAS_CODE_MDCT_GSHAPE
     154             :     Word16 nBands;
     155             :     IF( psychParamsCurrent == NULL )
     156             :     {
     157             :         nBands = FDNS_NPTS;
     158             :         PMT( "add nBands argument to mdct_shaping_16" )
     159             : #endif
     160             : 
     161           0 :         mdct_shaping_16( lastMDCTSpectrum, nSamplesCore, nSamples, scaleFactors, scaleFactors_exp, scaleFactors_max_e, pScaledMdctSpectrum );
     162             : #ifdef IVAS_CODE_MDCT_GSHAPE
     163             :     }
     164             :     ELSE
     165             :     {
     166             :         sns_shape_spectrum( pScaledMdctSpectrum, psychParamsCurrent, scaleFactors, nSamplesCore );
     167             :         nBands = psychParamsCurrent->nBands;
     168             :     }
     169             : #endif
     170             : 
     171           0 :     lastMDCTSpect_exp = add( lastMDCTSpectrum_exp, scaleFactors_max_e );
     172             : 
     173             :     /* Find peak candidates in the last frame. */
     174           0 :     findCandidates( nSamples, pScaledMdctSpectrum, lastMDCTSpect_exp, thresholdModification, floorPowerSpectrum );
     175             : 
     176             :     /* Refine peak candidates using the pitch information */
     177           0 :     RefineThresholdsUsingPitch( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification );
     178             : 
     179             :     /* Find peaks in the second last frame */
     180           0 :     findTonalComponents( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, F0, thresholdModification, element_mode );
     181           0 : }
     182             : 
     183             : /*-------------------------------------------------------------------*
     184             :  * RefineTonalComponents()
     185             :  *
     186             :  *-------------------------------------------------------------------*/
     187             : /* When called, the tonal components are already stored in
     188             :  * indexOfTonalPeak.  Detect tonal components in the lastMDCTSpectrum,
     189             :  * use secondLastPowerSpectrum for the precise location of the peaks and
     190             :  * then keep in indexOfTonalPeak only the tonal components that are
     191             :  * again detected Updates indexOfTonalPeak, lowerIndex, upperIndex,
     192             :  * phaseDiff, phases, pNumIndexes accordingly. */
     193           0 : void RefineTonalComponents(
     194             :     Word16 indexOfTonalPeak[],    /*Q0*/
     195             :     Word16 lowerIndex[],          /*Q0*/
     196             :     Word16 upperIndex[],          /*Q0*/
     197             :     Word16 phaseDiff[],           /*Q12*/
     198             :     Word16 phases[],              /*Q13*/
     199             :     Word16 *pNumIndexes,          /*Q0*/
     200             :     const Word32 lastPitchLag,    /*Qx*/
     201             :     const Word32 currentPitchLag, /*Qx*/
     202             :     const Word16 lastMDCTSpectrum[],
     203             :     const Word16 lastMDCTSpectrum_exp,
     204             :     const Word16 scaleFactors[],
     205             :     const Word16 scaleFactors_exp[],
     206             :     const Word16 scaleFactors_max_e,
     207             :     const Word32 secondLastPowerSpectrum[], /*Qx*/
     208             :     const Word16 nSamples,
     209             :     const Word16 nSamplesCore,
     210             :     const Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins  Q0*/
     211             :     Word16 element_mode
     212             : #ifdef IVAS_CODE_MDCT_GSHAPE
     213             :     ,
     214             :     const PsychoacousticParameters *psychParamsCurrent
     215             : #endif
     216             : )
     217             : {
     218             :     Word16 newIndexOfTonalPeak[MAX_NUMBER_OF_IDX]; /*Q0*/
     219             :     Word16 newLowerIndex[MAX_NUMBER_OF_IDX];       /*Q0*/
     220             :     Word16 newUpperIndex[MAX_NUMBER_OF_IDX];       /*Q0*/
     221             :     Word16 newNumIndexes, nPreservedPeaks;
     222             :     Word16 iNew, iOld, j;
     223             :     Word16 *pOldPhase, *pNewPhase;
     224             : 
     225             : 
     226           0 :     DetectTonalComponents( newIndexOfTonalPeak, newLowerIndex, newUpperIndex, &newNumIndexes, lastPitchLag, currentPitchLag, lastMDCTSpectrum,
     227             :                            lastMDCTSpectrum_exp, scaleFactors, scaleFactors_exp, scaleFactors_max_e, secondLastPowerSpectrum, nSamples, nSamplesCore, floorPowerSpectrum, element_mode
     228             : #ifdef IVAS_CODE_MDCT_GSHAPE
     229             :                            ,
     230             :                            psychParamsCurrent
     231             : #endif
     232             :     );
     233             : 
     234           0 :     nPreservedPeaks = 0;
     235           0 :     move16();
     236           0 :     iNew = 0;
     237           0 :     move16();
     238           0 :     pOldPhase = phases; /*Q13*/
     239           0 :     pNewPhase = phases; /*Q13*/
     240             : 
     241           0 :     FOR( iOld = 0; iOld < *pNumIndexes; iOld++ )
     242             :     {
     243             :         /* We don't want that the old peak index is at the border of the new peak region, that is why >= newUpperIndex and > newLowerIndex */
     244           0 :         test();
     245           0 :         WHILE( LT_16( iNew, newNumIndexes ) && GE_16( indexOfTonalPeak[iOld], newUpperIndex[iNew] ) )
     246             :         {
     247           0 :             iNew = add( iNew, 1 );
     248             :         }
     249             : 
     250           0 :         test();
     251           0 :         IF( LT_16( iNew, newNumIndexes ) && GT_16( indexOfTonalPeak[iOld], newLowerIndex[iNew] ) )
     252             :         {
     253           0 :             newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld]; /*Q0*/
     254           0 :             move16();
     255           0 :             newLowerIndex[nPreservedPeaks] = lowerIndex[iOld]; /*Q0*/
     256           0 :             move16();
     257           0 :             newUpperIndex[nPreservedPeaks] = upperIndex[iOld]; /*Q0*/
     258           0 :             move16();
     259           0 :             phaseDiff[nPreservedPeaks] = phaseDiff[iOld]; /*Q12*/
     260           0 :             move16();
     261             : 
     262           0 :             FOR( j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++ )
     263             :             {
     264           0 :                 *pNewPhase++ = *pOldPhase++; /*Q13*/
     265           0 :                 move16();
     266             :             }
     267           0 :             nPreservedPeaks = add( nPreservedPeaks, 1 );
     268             :         }
     269             :         ELSE
     270             :         {
     271           0 :             pOldPhase += sub( upperIndex[iOld], add( lowerIndex[iOld], 1 ) ); /*Q13*/
     272             :         }
     273             :     }
     274             : 
     275           0 :     FOR( iNew = 0; iNew < nPreservedPeaks; iNew++ )
     276             :     {
     277           0 :         indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew]; /*Q0*/
     278           0 :         move16();
     279           0 :         lowerIndex[iNew] = newLowerIndex[iNew]; /*Q0*/
     280           0 :         move16();
     281           0 :         upperIndex[iNew] = newUpperIndex[iNew]; /*Q0*/
     282           0 :         move16();
     283             :     }
     284           0 :     *pNumIndexes = nPreservedPeaks; /*Q0*/
     285           0 :     move16();
     286           0 :     return;
     287             : }
     288             : 
     289           0 : void ivas_RefineTonalComponents_fx(
     290             :     Word16 indexOfTonalPeak[],    /*Q0*/
     291             :     Word16 lowerIndex[],          /*Q0*/
     292             :     Word16 upperIndex[],          /*Q0*/
     293             :     Word16 phaseDiff[],           /*Q12*/
     294             :     Word16 phases[],              /*Q13*/
     295             :     Word16 *pNumIndexes,          /*Q0*/
     296             :     const Word32 lastPitchLag,    /*Qx*/
     297             :     const Word32 currentPitchLag, /*Qx*/
     298             :     const Word16 lastMDCTSpectrum[],
     299             :     const Word16 lastMDCTSpectrum_exp,
     300             :     const Word16 scaleFactors[],
     301             :     const Word16 scaleFactors_exp[],
     302             :     const Word16 scaleFactors_max_e,
     303             :     const Word32 secondLastPowerSpectrum[], /*Q31-secondLastPowerSpectrum_e*/
     304             :     const Word16 secondLastPowerSpectrum_e,
     305             :     const Word16 nSamples,
     306             :     const Word16 nSamplesCore,
     307             :     const Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins  Q0*/
     308             :     Word16 element_mode,
     309             :     const PsychoacousticParameters *psychParamsCurrent )
     310             : {
     311             :     Word16 newIndexOfTonalPeak[MAX_NUMBER_OF_IDX]; /*Q0*/
     312             :     Word16 newLowerIndex[MAX_NUMBER_OF_IDX];       /*Q0*/
     313             :     Word16 newUpperIndex[MAX_NUMBER_OF_IDX];       /*Q0*/
     314             :     Word16 newNumIndexes, nPreservedPeaks;
     315             :     Word16 iNew, iOld, j;
     316             :     Word16 *pOldPhase, *pNewPhase;
     317             : 
     318             : 
     319           0 :     ivas_DetectTonalComponents_fx( newIndexOfTonalPeak, newLowerIndex, newUpperIndex, &newNumIndexes, lastPitchLag, currentPitchLag, lastMDCTSpectrum,
     320             :                                    lastMDCTSpectrum_exp, scaleFactors, scaleFactors_exp, scaleFactors_max_e, secondLastPowerSpectrum, secondLastPowerSpectrum_e, nSamples, nSamplesCore, floorPowerSpectrum,
     321             :                                    psychParamsCurrent, element_mode );
     322             : 
     323           0 :     nPreservedPeaks = 0;
     324           0 :     move16();
     325           0 :     iNew = 0;
     326           0 :     move16();
     327           0 :     pOldPhase = phases; /*Q13*/
     328           0 :     pNewPhase = phases; /*Q13*/
     329             : 
     330           0 :     FOR( iOld = 0; iOld < *pNumIndexes; iOld++ )
     331             :     {
     332             :         /* We don't want that the old peak index is at the border of the new peak region, that is why >= newUpperIndex and > newLowerIndex */
     333           0 :         test();
     334           0 :         WHILE( LT_16( iNew, newNumIndexes ) && GE_16( indexOfTonalPeak[iOld], newUpperIndex[iNew] ) )
     335             :         {
     336           0 :             iNew = add( iNew, 1 );
     337             :         }
     338             : 
     339           0 :         test();
     340           0 :         IF( LT_16( iNew, newNumIndexes ) && GT_16( indexOfTonalPeak[iOld], newLowerIndex[iNew] ) )
     341             :         {
     342           0 :             newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld]; /*Q0*/
     343           0 :             move16();
     344           0 :             newLowerIndex[nPreservedPeaks] = lowerIndex[iOld]; /*Q0*/
     345           0 :             move16();
     346           0 :             newUpperIndex[nPreservedPeaks] = upperIndex[iOld]; /*Q0*/
     347           0 :             move16();
     348           0 :             phaseDiff[nPreservedPeaks] = phaseDiff[iOld]; /*Q12*/
     349           0 :             move16();
     350             : 
     351           0 :             FOR( j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++ )
     352             :             {
     353           0 :                 *pNewPhase++ = *pOldPhase++; /*Q13*/
     354           0 :                 move16();
     355             :             }
     356           0 :             nPreservedPeaks = add( nPreservedPeaks, 1 );
     357             :         }
     358             :         ELSE
     359             :         {
     360           0 :             pOldPhase += sub( upperIndex[iOld], add( lowerIndex[iOld], 1 ) ); /*Q13*/
     361             :         }
     362             :     }
     363             : 
     364           0 :     FOR( iNew = 0; iNew < nPreservedPeaks; iNew++ )
     365             :     {
     366           0 :         indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew]; /*Q0*/
     367           0 :         move16();
     368           0 :         lowerIndex[iNew] = newLowerIndex[iNew]; /*Q0*/
     369           0 :         move16();
     370           0 :         upperIndex[iNew] = newUpperIndex[iNew]; /*Q0*/
     371           0 :         move16();
     372             :     }
     373           0 :     *pNumIndexes = nPreservedPeaks; /*Q0*/
     374           0 :     move16();
     375           0 :     return;
     376             : }
     377             : /*-------------------------------------------------------------------*
     378             :  * Local functions
     379             :  *-------------------------------------------------------------------*/
     380        1425 : static void calcPseudoSpec(
     381             :     const Word32 *mdctSpec,    /* i: MDCT spectrum                        */
     382             :     const Word16 mdctSpec_exp, /* i: exponent of MDCT spectrum            */
     383             :     const Word16 nSamples,     /* i: frame size                           */
     384             :     Word16 floorPowerSpectrum, /* i: lower limit for power spectrum bins  Q0*/
     385             :     Word32 *powerSpec,         /* o: estimated power spectrum             */
     386             :     Word16 *powerSpec_exp      /* o: exponent of estimated power spectrum */
     387             : )
     388             : {
     389             :     Word16 k;
     390             :     Word32 x, L_tmp, L_tmp_floor;
     391             :     Word16 tmp_loop;
     392             : 
     393             : 
     394        1425 :     *powerSpec_exp = add( add( mdctSpec_exp, mdctSpec_exp ), 5 );
     395        1425 :     move16();
     396             : 
     397        1425 :     k = sub( 31, *powerSpec_exp );
     398             :     /* If the signal is bellow floor, special care is needed for *powerSpec_exp */
     399        1425 :     IF( LT_16( add( 16 - 3, norm_s( floorPowerSpectrum ) ), k ) ) /*extra 3 bits of headroom for MA filter in getEnvelope*/
     400             :     {
     401          72 :         k = add( 16 - 3, norm_s( floorPowerSpectrum ) );             /*extra 3 bits of headroom for MA filter in getEnvelope*/
     402          72 :         L_tmp_floor = L_shl( L_deposit_l( floorPowerSpectrum ), k ); /*Q : 13+norm_s( floorPowerSpectrum )*/
     403          72 :         set32_fx( powerSpec, L_tmp_floor, nSamples );                /*Q : 13+norm_s( floorPowerSpectrum )*/
     404          72 :         *powerSpec_exp = sub( 31, k );
     405             :     }
     406             :     ELSE
     407             :     {
     408        1353 :         L_tmp_floor = L_shl( L_deposit_l( floorPowerSpectrum ), k ); /*Q : 31 - *powerSpec_exp*/
     409             : 
     410        1353 :         tmp_loop = sub( nSamples, 2 );
     411      718187 :         FOR( k = 1; k <= tmp_loop; k++ )
     412             :         {
     413      716834 :             x = L_sub( L_shr( mdctSpec[k + 1], 1 ), L_shr( mdctSpec[k - 1], 1 ) ); /* An MDST estimate */ /*30-mdctSpec_exp*/
     414             : 
     415      716834 :             x = L_shr( Mpy_32_32( x, x ), 3 ); /*26-2*mdctSpec_exp*/
     416             : 
     417      716834 :             L_tmp = Mpy_32_32( mdctSpec[k], mdctSpec[k] ); /*31-2*mdctSpec_exp*/
     418      716834 :             L_tmp = L_shr( L_tmp, 5 );                     /*26-2*mdctSpec_exp*/
     419             : 
     420      716834 :             powerSpec[k] = L_max( L_tmp_floor, L_add( L_tmp, x ) ); /*Q : 31 - *powerSpec_exp*/
     421      716834 :             move32();
     422             :         }
     423             :     }
     424             : 
     425        1425 :     powerSpec[0] = L_shr( powerSpec[1], 1 ); /*0.5f * powerSpec[1]*/
     426        1425 :     move32();
     427        1425 :     powerSpec[nSamples - 1] = L_shr( powerSpec[nSamples - 2], 1 ); /*0.5f * powerSpec[nSamples - 2]*/
     428        1425 :     move32();
     429        1425 :     return;
     430             : }
     431             : 
     432             : #define LEVEL_EXP 3 /*+4*/
     433        2850 : static void getEnvelope(
     434             :     const Word16 nSamples,   /*i:               Q0 */
     435             :     const Word32 *powerSpec, /*i: powerSpec_exp    */
     436             :     Word16 F0,               /*i:              5Q10*/
     437             :     Word32 *envelope,        /*o: powerSpec_exp + LEVEL_EXP Q28*/
     438             :     Word32 *smoothedSpectrum /*o: powerSpec_exp + LEVEL_EXP Q28*/
     439             : )
     440             : {
     441             :     Word16 nFilterLength, nHalfFilterLength, nSecondHalfFilterLength, n1, n2;
     442             :     Word16 level, inv_len;
     443             :     Word16 i;
     444             :     Word32 sum, tmp;
     445             : 
     446        2850 :     IF( F0 == 0 )
     447             :     {
     448        2492 :         nFilterLength = 15; /*Q0*/
     449        2492 :         move16();
     450             :     }
     451         358 :     ELSE IF( F0 <= 10240 /*10.0f Q10*/ )
     452             :     {
     453          76 :         nFilterLength = 11; /*Q0*/
     454          76 :         move16();
     455             :     }
     456         282 :     ELSE IF( F0 >= 22528 /*22.0f Q10*/ )
     457             :     {
     458             :         /* For F0 >= 22 peak is isolated well enough with the filter length of 23.
     459             :            This case is however not triggered due to the limit of pit_min,
     460             :            but the line is left for security reasons. */
     461          16 :         nFilterLength = 23; /*Q0*/
     462          16 :         move16();
     463             :     }
     464             :     ELSE
     465             :     {
     466         266 :         nFilterLength = s_or( 1, shr( F0, 10 ) ); /*1+2*(int)(F0/2); F0->Q10*/
     467         266 :         move16();
     468             :     }
     469             : 
     470        2850 :     nHalfFilterLength = shr( nFilterLength, 1 );
     471             : 
     472        2850 :     n1 = add( nHalfFilterLength, 1 );
     473             : 
     474        2850 :     nSecondHalfFilterLength = sub( nFilterLength, nHalfFilterLength );
     475             : 
     476        2850 :     n2 = sub( nSecondHalfFilterLength, 1 );
     477             : 
     478        2850 :     assert( ( nFilterLength >= 7 ) && ( nFilterLength <= 23 ) && ( nFilterLength % 2 == 1 ) );
     479             : 
     480             : 
     481        2850 :     sum = L_deposit_l( 0 );
     482        2850 :     level = 31089 /*LEVEL_ABOVE_ENVELOPE Q12*/; /*Q12*/
     483        2850 :     move16();
     484             : 
     485       22653 :     FOR( i = 0; i < n2; i++ )
     486             :     {
     487       19803 :         sum = L_add( sum, powerSpec[i] ); /*powerSpec_exp*/
     488             :     }
     489             :     /* No need for PTR_INIT for powerSpec[i+n2] as we continue from the previous loop */
     490       25503 :     FOR( i = 0; i < n1; i++ )
     491             :     {
     492       22653 :         sum = L_add_sat( sum, powerSpec[i + n2] );                     /*powerSpec_exp*/
     493       22653 :         tmp = Mpy_32_16_1( sum /*Q31,powerSpec_exp*/, level /*Q12*/ ); /*Q28,powerSpec_exp*/
     494       22653 :         envelope[i] /*Q28,powerSpec_exp*/ = Mpy_32_16_1( tmp /*Q28,powerSpec_exp*/, InvIntTable[i + nSecondHalfFilterLength] /*Q15*/ );
     495       22653 :         move32();
     496             :     }
     497             : 
     498        2850 :     inv_len = mult_r( level, InvIntTable[nFilterLength] ); /*Q12*/
     499     1460246 :     FOR( i = n1; i < nSamples - n2; i++ )
     500             :     {
     501     1457396 :         sum = L_add_sat( sum, L_sub( powerSpec[i + n2], powerSpec[i - n1] ) ); /*powerSpec_exp*/
     502     1457396 :         envelope[i] = Mpy_32_16_1( sum, inv_len );                             /*Q28*/
     503     1457396 :         move32();
     504             :     }
     505             : 
     506       22653 :     FOR( i = nSamples - n2; i < nSamples; i++ )
     507             :     {
     508       19803 :         sum = L_sub( sum, powerSpec[i - n1] );
     509       19803 :         tmp = Mpy_32_16_1( sum, level );                                                         /*Q28*/
     510       19803 :         envelope[i] = Mpy_32_16_1( tmp, InvIntTable[( nSamples - ( i - nHalfFilterLength ) )] ); /*Q28*/
     511       19803 :         move32();
     512             :     }
     513             : 
     514     1497002 :     FOR( i = 1; i < nSamples - 1; i++ )
     515             :     {
     516     1494152 :         smoothedSpectrum[i] = L_add( L_add( Mpy_32_16_1( powerSpec[i - 1], 3072 /*0.75f Q12*/ ), L_shr( powerSpec[i], LEVEL_EXP ) ), Mpy_32_16_1( powerSpec[i + 1], 3072 /*0.75f Q12*/ ) ); /*Q28*/
     517     1494152 :         move32();
     518             :     }
     519             : 
     520        2850 :     move32();
     521        2850 :     move32();
     522        2850 :     smoothedSpectrum[0] = L_add( Mpy_32_16_1( powerSpec[1], 3072 /*0.75f Q12*/ ), L_shr( powerSpec[0], LEVEL_EXP ) );                                  /*Q28*/
     523        2850 :     smoothedSpectrum[nSamples - 1] = L_add( Mpy_32_16_1( powerSpec[nSamples - 2], 3072 /*0.75f Q12*/ ), L_shr( powerSpec[nSamples - 1], LEVEL_EXP ) ); /**/
     524        2850 :     return;
     525             : }
     526             : 
     527           0 : static void GetF0(
     528             :     Word16 /*short*/ const nSamples,     /*i   -  Q0 */
     529             :     Word16 /*short*/ const nSamplesCore, /*i   -  Q0 */
     530             :     Word32 /*int*/ const *const powerSpectrum,
     531             :     /*i   -  Qx */                   /*is justed handed over and given back*/
     532             :     Word32 /*int*/ const pitchLag,   /*i   -  Q16*/
     533             :     Word16 /*short*/ *const pOrigF0, /*o   -  Q10*/
     534             :     Word16 /*short*/ *const pF0 )    /*o   -  Q10*/
     535             : {
     536             :     Word16 /*short*/ tmpPitchLag;
     537             :     Word16 /*short*/ rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; /*Q0*/
     538             :     Word16 /*short*/ nTotalHarmonics, nStrongHarmonics;
     539             :     Word16 tmp;
     540             : 
     541             : 
     542           0 :     assert( LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore );
     543             : 
     544             :     /* Use only F0 >= 100 Hz */
     545           0 :     test();
     546           0 :     IF( ( pitchLag > 0 ) && ( LE_16( round_fx( pitchLag ), shr( nSamplesCore, 1 ) ) ) )
     547             :     {
     548             : 
     549             :         tmpPitchLag                             /*"halfPitchLag" in FLC - read as Q5 for comparison to halfpitchlag Q4*/
     550           0 :             = round_fx( L_shl( pitchLag, 4 ) ); /*no division by 2, will be done in following division -
     551             :                                            furthermore, do a leftshift before rounding, to preserve more accuracy -
     552             :                                            will be accommodated also in following division*/
     553             : 
     554             :         /**pF0 = nSamplesCore/tmpPitchLag;*/
     555           0 :         BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/
     556           0 :         move16();
     557           0 :         *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/
     558           0 :         move16();
     559           0 :         *pOrigF0 = *pF0; /*Q10*/
     560           0 :         move16();
     561           0 :         tmp = 2 * LAST_HARMONIC_POS_TO_CHECK;
     562           0 :         if ( LT_16( nSamples, 2 * LAST_HARMONIC_POS_TO_CHECK ) )
     563             :         {
     564           0 :             move16();
     565           0 :             tmp = nSamples;
     566             :         }
     567           0 :         BASOP_Util_Divide_MantExp( tmp, 15, *pF0, 5, &nTotalHarmonics, &tmp );
     568           0 :         nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) );
     569             : 
     570             : 
     571             :         /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */
     572           0 :         findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics );
     573             : 
     574           0 :         CorrectF0( rgiStrongHarmonics, nStrongHarmonics, pF0 );
     575             :     }
     576             :     ELSE
     577             :     {
     578           0 :         move16();
     579           0 :         move16();
     580           0 :         *pF0 = 0;
     581           0 :         *pOrigF0 = 0;
     582             :     }
     583           0 :     return;
     584             : }
     585             : 
     586        1425 : static void ivas_GetF0_fx(
     587             :     Word16 /*short*/ const nSamples,     /*i   -  Q0 */
     588             :     Word16 /*short*/ const nSamplesCore, /*i   -  Q0 */
     589             :     Word32 /*int*/ const *const powerSpectrum,
     590             :     /*i   -  Qx */                   /*is justed handed over and given back*/
     591             :     Word32 /*int*/ const pitchLag,   /*i   -  Q16*/
     592             :     Word16 /*short*/ *const pOrigF0, /*o   -  Q10*/
     593             :     Word16 /*short*/ *const pF0 )    /*o   -  Q10*/
     594             : {
     595             :     Word16 /*short*/ tmpPitchLag;
     596             :     Word16 /*short*/ rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH]; /*Q0*/
     597             :     Word16 /*short*/ nTotalHarmonics, nStrongHarmonics;
     598             :     Word16 tmp;
     599             : 
     600             : 
     601        1425 :     assert( LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore );
     602             : 
     603             :     /* Use only F0 >= 100 Hz */
     604        1425 :     test();
     605        1425 :     IF( ( pitchLag > 0 ) && ( LE_16( round_fx( pitchLag ), shr( nSamplesCore, 1 ) ) ) )
     606             :     {
     607             : 
     608             :         tmpPitchLag                             /*"halfPitchLag" in FLC - read as Q5 for comparison to halfpitchlag Q4*/
     609         368 :             = round_fx( L_shl( pitchLag, 4 ) ); /*no division by 2, will be done in following division -
     610             :                                            furthermore, do a leftshift before rounding, to preserve more accuracy -
     611             :                                            will be accommodated also in following division*/
     612             : 
     613             :         /**pF0 = nSamplesCore/tmpPitchLag;*/
     614         368 :         BASOP_Util_Divide_MantExp( nSamplesCore, 0, tmpPitchLag, -( 1 /*division by 2*/ + 4 /*accommodate accuracy-prevention-leftshift*/ ), pF0, &tmp ); /*pF0 is Q15*/
     615         368 :         move16();
     616         368 :         *pF0 = shr_sat( *pF0, sub( 5, tmp ) ); /*Q10 without scalingfactor*/
     617         368 :         move16();
     618         368 :         *pOrigF0 = *pF0; /*Q10*/
     619         368 :         move16();
     620         368 :         tmp = 2 * LAST_HARMONIC_POS_TO_CHECK;
     621         368 :         if ( LT_16( nSamples, 2 * LAST_HARMONIC_POS_TO_CHECK ) )
     622             :         {
     623          24 :             move16();
     624          24 :             tmp = nSamples;
     625             :         }
     626         368 :         BASOP_Util_Divide_MantExp( tmp, 15, *pF0, 5, &nTotalHarmonics, &tmp );
     627         368 :         nTotalHarmonics = shl( nTotalHarmonics, sub( tmp, 15 ) );
     628             : 
     629             : 
     630             :         /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */
     631         368 :         findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics );
     632             : 
     633         368 :         ivas_CorrectF0_fx( rgiStrongHarmonics, nStrongHarmonics, pF0 );
     634             :     }
     635             :     ELSE
     636             :     {
     637        1057 :         move16();
     638        1057 :         move16();
     639        1057 :         *pF0 = 0;
     640        1057 :         *pOrigF0 = 0;
     641             :     }
     642        1425 :     return;
     643             : }
     644             : 
     645             : 
     646         368 : static void findStrongestHarmonics(
     647             :     const Word16 nSamples,
     648             :     const Word32 *powerSpectrum, /*Qx*/
     649             :     const Word16 F0 /*5Q10*/,
     650             :     const Word16 nTotalHarmonics,
     651             :     Word16 *pHarmonicIndexes, /*Q0*/
     652             :     Word16 *pnHarmonics /*Q0*/ )
     653             : {
     654             :     Word32 peaks[MAX_PEAKS_FROM_PITCH] /*Qx*/, smallestPeak;
     655             :     Word16 nPeaksToCheck, nPeaks, iSmallestPeak;
     656             :     Word16 i, l, k;
     657             :     (void) nSamples;
     658             : 
     659             : 
     660         368 :     nPeaks = 0;
     661         368 :     move16();
     662             : 
     663         368 :     iSmallestPeak = 0;
     664         368 :     move16();
     665         368 :     smallestPeak = 0x7fffffff;
     666         368 :     move32();
     667             : 
     668         368 :     nPeaksToCheck = s_min( nTotalHarmonics, MAX_PEAKS_FROM_PITCH + 1 );
     669             : 
     670        4014 :     FOR( i = 1; i < nPeaksToCheck; i++ )
     671             :     {
     672             :         Word32 newPeak;
     673             : 
     674        3646 :         k = extract_h( L_shl( L_mult( i, F0 ), 5 ) ); /*k = (int)(i*F0); Q0*/
     675        3646 :         assert( k > 0 && k < 2 * LAST_HARMONIC_POS_TO_CHECK && k < nSamples );
     676             : 
     677        3646 :         newPeak = L_add( powerSpectrum[k], 0 ); /*Qx*/
     678             : 
     679        3646 :         peaks[nPeaks] = newPeak; /*Qx*/
     680        3646 :         move32();
     681        3646 :         pHarmonicIndexes[nPeaks] = i;
     682        3646 :         move16();
     683             : 
     684        3646 :         IF( LE_32( newPeak, smallestPeak ) )
     685             :         {
     686        2084 :             iSmallestPeak = nPeaks;
     687        2084 :             move16();
     688        2084 :             smallestPeak = L_add( newPeak, 0 );
     689             :         }
     690             : 
     691        3646 :         nPeaks = add( nPeaks, 1 );
     692             :     }
     693             : 
     694        4534 :     FOR( ; i < nTotalHarmonics; i++ )
     695             :     {
     696             :         Word32 newPeak;
     697             : 
     698        4166 :         k = extract_h( L_shl( L_mult( i, F0 ), 5 ) ); /*Q0*/
     699        4166 :         assert( k > 0 && k < 2 * LAST_HARMONIC_POS_TO_CHECK && k < nSamples );
     700             : 
     701        4166 :         newPeak = L_add( powerSpectrum[k], 0 ); /*Qx*/
     702             : 
     703        4166 :         IF( GT_32( newPeak, smallestPeak ) )
     704             :         {
     705         643 :             peaks[iSmallestPeak] = newPeak; /*Qx*/
     706         643 :             move32();
     707         643 :             pHarmonicIndexes[iSmallestPeak] = i;
     708         643 :             move16();
     709         643 :             smallestPeak = L_add( newPeak, 0 );
     710             : 
     711        7073 :             FOR( l = 0; l < MAX_PEAKS_FROM_PITCH; l++ )
     712             :             {
     713        6430 :                 IF( peaks[l] <= smallestPeak )
     714             :                 {
     715        1318 :                     iSmallestPeak = l;
     716        1318 :                     move16();
     717        1318 :                     smallestPeak = L_add( peaks[l], 0 );
     718             :                 }
     719             :             }
     720             :         }
     721             :     }
     722             : 
     723         368 :     sort_fx( pHarmonicIndexes, 0, sub( nPeaks, 1 ) );
     724             : 
     725         368 :     *pnHarmonics = nPeaks; /*Q0*/
     726         368 :     move16();
     727         368 :     return;
     728             : }
     729             : 
     730             : /* Use new F0, for which harmonics are most common in pHarmonicIndexes */
     731           0 : static void CorrectF0(
     732             :     const Word16 /*short*/ *pHarmonicIndexes, /*I    - Q0  */
     733             :     const Word16 /*short*/ nHarmonics,        /*I    - Q0  */
     734             :     Word16 /*short*/ *pF0 )                   /*I/O  - Q10 range: {0}, [4..18) */
     735             : {
     736             :     Word16 /*short*/ i;
     737             :     Word16 /*short*/ F0;
     738             :     Word16 /*short*/ diff[MAX_PEAKS_FROM_PITCH - 1], sortedDiff[MAX_PEAKS_FROM_PITCH - 1]; /*Q0*/
     739             :     Word16 /*short*/ iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult;                   /*Q0*/
     740             : 
     741             :     Word16 tmp;
     742             : 
     743           0 :     F0 = *pF0; /*Q10*/
     744             : 
     745           0 :     test();
     746           0 :     IF( F0 > 0 && nHarmonics != 0 )
     747             :     {
     748           0 :         tmp = sub( nHarmonics, 1 );
     749           0 :         FOR( i = 0; i < tmp; i++ )
     750             :         {
     751           0 :             diff[i] = sub( pHarmonicIndexes[i + 1], pHarmonicIndexes[i] ); /*Q0*/
     752           0 :             move16();
     753           0 :             sortedDiff[i] = diff[i]; /*Q0*/
     754           0 :             move16();
     755             :         }
     756           0 :         sort_fx( sortedDiff, 0, sub( nHarmonics, 1 + 1 ) );
     757           0 :         iMostCommonDiff = sortedDiff[0]; /*Q0*/
     758           0 :         move16();
     759           0 :         nSameDiff = 1;
     760           0 :         move16();
     761           0 :         i = 1;
     762           0 :         move16();
     763           0 :         IF( EQ_16( imult1616( sortedDiff[0], pHarmonicIndexes[0] ), 1 ) )
     764             :         {
     765             :             /* Find how many distances between peaks have length 1 */
     766           0 :             FOR( ; i < tmp; i++ )
     767             :             {
     768           0 :                 if ( EQ_16( sortedDiff[i], 1 ) )
     769             :                 {
     770           0 :                     nSameDiff = add( nSameDiff, 1 );
     771             :                 }
     772             :             }
     773             :         }
     774           0 :         nMostCommonDiff = nSameDiff; /*Q0*/
     775           0 :         move16();
     776             : 
     777             :         /* If there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
     778             :         /* Otherwise find the most common distance between peaks */
     779           0 :         IF( LT_16( nSameDiff, 3 ) )
     780             :         {
     781             :             /* Find the most common difference */
     782           0 :             FOR( i = nSameDiff; i < tmp; i++ )
     783             :             {
     784           0 :                 IF( EQ_16( sortedDiff[i], sortedDiff[i - 1] ) )
     785             :                 {
     786           0 :                     nSameDiff = add( nSameDiff, 1 );
     787             :                 }
     788             :                 ELSE
     789             :                 {
     790           0 :                     IF( GT_16( nSameDiff, nMostCommonDiff ) )
     791             :                     {
     792           0 :                         nMostCommonDiff = nSameDiff; /*Q0*/
     793           0 :                         move16();
     794           0 :                         iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
     795           0 :                         move16();
     796             :                     }
     797             :                     ELSE
     798             :                     {
     799           0 :                         test();
     800           0 :                         IF( EQ_16( nSameDiff, nMostCommonDiff ) && GT_16( abs_s( sub( iMostCommonDiff, pHarmonicIndexes[0] ) ), abs_s( sub( sortedDiff[i - 1], pHarmonicIndexes[0] ) ) ) )
     801             :                         {
     802           0 :                             nMostCommonDiff = nSameDiff; /*Q0*/
     803           0 :                             move16();
     804           0 :                             iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
     805           0 :                             move16();
     806             :                         }
     807             :                     }
     808           0 :                     nSameDiff = 1;
     809           0 :                     move16();
     810             :                 }
     811             :             }
     812           0 :             IF( GT_16( nSameDiff, nMostCommonDiff ) )
     813             :             {
     814           0 :                 nMostCommonDiff = nSameDiff; /*Q0*/
     815           0 :                 move16();
     816           0 :                 iMostCommonDiff = sortedDiff[nHarmonics - 2]; /*Q0*/
     817           0 :                 move16();
     818             :             }
     819             :         }
     820             : 
     821             :         /* If there are enough peaks at the same distance */
     822           0 :         IF( GE_16( nMostCommonDiff, MAX_PEAKS_FROM_PITCH / 2 ) )
     823             :         {
     824           0 :             iMult = 1;
     825           0 :             move16();
     826           0 :             FOR( i = 0; i < tmp; i++ )
     827             :             {
     828           0 :                 IF( EQ_16( diff[i], iMostCommonDiff ) )
     829             :                 {
     830           0 :                     iMult = pHarmonicIndexes[i]; /*Q0*/
     831           0 :                     move16();
     832           0 :                     BREAK;
     833             :                 }
     834             :                 /* for rare cases of octave mismatch or missing harmonics */
     835           0 :                 test();
     836           0 :                 test();
     837           0 :                 IF( GT_16( sub( nHarmonics, 2 ), i ) && ( EQ_16( diff[i], diff[i + 1] ) ) && ( EQ_16( add( diff[i], diff[i + 1] ), iMostCommonDiff ) ) )
     838             :                 {
     839           0 :                     iMult = pHarmonicIndexes[i]; /*Q0*/
     840           0 :                     move16();
     841           0 :                     BREAK;
     842             :                 }
     843             :             }
     844             : 
     845             :             /* If the real F0 is much higher than the original F0 from the pitch */
     846             : 
     847           0 :             IF( LE_16( iMult, 3 ) )
     848             :             {
     849             :                 /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */
     850           0 :                 F0 = round_fx_sat( L_shl_sat( L_mult( iMostCommonDiff /*Q0*/, F0 /*Q10*/ ), 15 ) ); /*Q10*/
     851             :             }
     852             :             ELSE
     853             :             {
     854           0 :                 F0 = 0;
     855           0 :                 move16();
     856             :             }
     857             :         }
     858             :         /* Otherwise if there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
     859             :         /* Otherwise don't use F0 */
     860             :         ELSE
     861             :         {
     862           0 :             test();
     863           0 :             if ( ( GT_16( iMostCommonDiff, 1 ) ) || ( LT_16( nMostCommonDiff, 3 ) ) )
     864             :             {
     865             :                 /* Not enough peaks at the same distance => don't use the pitch. */
     866           0 :                 F0 = 0;
     867           0 :                 move16();
     868             :             }
     869             :         }
     870           0 :         *pF0 = F0;
     871           0 :         move16();
     872             :     }
     873           0 :     return;
     874             : }
     875             : 
     876         368 : static void ivas_CorrectF0_fx(
     877             :     const Word16 /*short*/ *pHarmonicIndexes, /*I    - Q0  */
     878             :     const Word16 /*short*/ nHarmonics,        /*I    - Q0  */
     879             :     Word16 /*short*/ *pF0 )                   /*I/O  - Q10 range: {0}, [4..18) */
     880             : {
     881             :     Word16 /*short*/ i;
     882             :     Word16 /*short*/ F0;
     883             :     Word16 /*short*/ diff[MAX_PEAKS_FROM_PITCH - 1], sortedDiff[MAX_PEAKS_FROM_PITCH - 1]; /*Q0*/
     884             :     Word16 /*short*/ iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult;                   /*Q0*/
     885             : 
     886             :     Word16 tmp;
     887             : 
     888        3680 :     FOR( i = 0; i < MAX_PEAKS_FROM_PITCH - 1; i++ )
     889             :     {
     890        3312 :         diff[i] = 0;
     891        3312 :         sortedDiff[i] = 0;
     892        3312 :         move16();
     893        3312 :         move16();
     894             :     }
     895             : 
     896         368 :     F0 = *pF0; /*Q10*/
     897             : 
     898         368 :     test();
     899         368 :     IF( F0 > 0 && nHarmonics != 0 )
     900             :     {
     901         368 :         tmp = sub( nHarmonics, 1 );
     902        3646 :         FOR( i = 0; i < tmp; i++ )
     903             :         {
     904        3278 :             diff[i] = sub( pHarmonicIndexes[i + 1], pHarmonicIndexes[i] ); /*Q0*/
     905        3278 :             move16();
     906        3278 :             sortedDiff[i] = diff[i]; /*Q0*/
     907        3278 :             move16();
     908             :         }
     909         368 :         sort_fx( sortedDiff, 0, sub( nHarmonics, 1 + 1 ) );
     910         368 :         iMostCommonDiff = sortedDiff[0]; /*Q0*/
     911         368 :         move16();
     912         368 :         nSameDiff = 1;
     913         368 :         move16();
     914         368 :         i = 1;
     915         368 :         move16();
     916         368 :         IF( EQ_16( imult1616( sortedDiff[0], pHarmonicIndexes[0] ), 1 ) )
     917             :         {
     918             :             /* Find how many distances between peaks have length 1 */
     919        2954 :             FOR( ; i < tmp; i++ )
     920             :             {
     921        2622 :                 if ( EQ_16( sortedDiff[i], 1 ) )
     922             :                 {
     923        2223 :                     nSameDiff = add( nSameDiff, 1 );
     924             :                 }
     925             :             }
     926             :         }
     927         368 :         nMostCommonDiff = nSameDiff; /*Q0*/
     928         368 :         move16();
     929             : 
     930             :         /* If there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
     931             :         /* Otherwise find the most common distance between peaks */
     932         368 :         IF( LT_16( nSameDiff, 3 ) )
     933             :         {
     934             :             /* Find the most common difference */
     935         369 :             FOR( i = nSameDiff; i < tmp; i++ )
     936             :             {
     937         327 :                 IF( EQ_16( sortedDiff[i], sortedDiff[i - 1] ) )
     938             :                 {
     939         262 :                     nSameDiff = add( nSameDiff, 1 );
     940             :                 }
     941             :                 ELSE
     942             :                 {
     943          65 :                     IF( GT_16( nSameDiff, nMostCommonDiff ) )
     944             :                     {
     945          39 :                         nMostCommonDiff = nSameDiff; /*Q0*/
     946          39 :                         move16();
     947          39 :                         iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
     948          39 :                         move16();
     949             :                     }
     950             :                     ELSE
     951             :                     {
     952          26 :                         test();
     953          26 :                         IF( EQ_16( nSameDiff, nMostCommonDiff ) && GT_16( abs_s( sub( iMostCommonDiff, pHarmonicIndexes[0] ) ), abs_s( sub( sortedDiff[i - 1], pHarmonicIndexes[0] ) ) ) )
     954             :                         {
     955           1 :                             nMostCommonDiff = nSameDiff; /*Q0*/
     956           1 :                             move16();
     957           1 :                             iMostCommonDiff = sortedDiff[i - 1]; /*Q0*/
     958           1 :                             move16();
     959             :                         }
     960             :                     }
     961          65 :                     nSameDiff = 1;
     962          65 :                     move16();
     963             :                 }
     964             :             }
     965          42 :             IF( GT_16( nSameDiff, nMostCommonDiff ) )
     966             :             {
     967          18 :                 nMostCommonDiff = nSameDiff; /*Q0*/
     968          18 :                 move16();
     969          18 :                 iMostCommonDiff = sortedDiff[nHarmonics - 2]; /*Q0*/
     970          18 :                 move16();
     971             :             }
     972             :         }
     973             : 
     974             :         /* If there are enough peaks at the same distance */
     975         368 :         IF( GE_16( nMostCommonDiff, MAX_PEAKS_FROM_PITCH / 2 ) )
     976             :         {
     977         350 :             iMult = 1;
     978         350 :             move16();
     979         360 :             FOR( i = 0; i < tmp; i++ )
     980             :             {
     981         360 :                 IF( EQ_16( diff[i], iMostCommonDiff ) )
     982             :                 {
     983         337 :                     iMult = pHarmonicIndexes[i]; /*Q0*/
     984         337 :                     move16();
     985         337 :                     BREAK;
     986             :                 }
     987             :                 /* for rare cases of octave mismatch or missing harmonics */
     988          23 :                 test();
     989          23 :                 test();
     990          23 :                 IF( GT_16( sub( nHarmonics, 2 ), i ) && ( EQ_16( diff[i], diff[i + 1] ) ) && ( EQ_16( add( diff[i], diff[i + 1] ), iMostCommonDiff ) ) )
     991             :                 {
     992          13 :                     iMult = pHarmonicIndexes[i]; /*Q0*/
     993          13 :                     move16();
     994          13 :                     BREAK;
     995             :                 }
     996             :             }
     997             : 
     998             :             /* If the real F0 is much higher than the original F0 from the pitch */
     999             : 
    1000         350 :             IF( LE_16( iMult, 3 ) )
    1001             :             {
    1002             :                 /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */
    1003         344 :                 F0 = round_fx_sat( L_shl_sat( L_mult( iMostCommonDiff /*Q0*/, F0 /*Q10*/ ), 15 ) ); /*Q10*/
    1004             :             }
    1005             :             ELSE
    1006             :             {
    1007           6 :                 F0 = 0;
    1008           6 :                 move16();
    1009             :             }
    1010             :         }
    1011             :         /* Otherwise if there are at least 3 distances between peaks with length 1 and if the 1st harmonic is in pHarmonicIndexes then keep the original F0 */
    1012             :         /* Otherwise don't use F0 */
    1013             :         ELSE
    1014             :         {
    1015          18 :             test();
    1016          18 :             if ( ( GT_16( iMostCommonDiff, 1 ) ) || ( LT_16( nMostCommonDiff, 3 ) ) )
    1017             :             {
    1018             :                 /* Not enough peaks at the same distance => don't use the pitch. */
    1019           4 :                 F0 = 0;
    1020           4 :                 move16();
    1021             :             }
    1022             :         }
    1023         368 :         *pF0 = F0;
    1024         368 :         move16();
    1025             :     }
    1026         368 :     return;
    1027             : }
    1028             : 
    1029        3532 : static void modifyThreshold(
    1030             :     Word16 /*short*/ i,                        /*I   - Q0 */
    1031             :     Word16 /*short*/ F0,                       /*I   - Q10*/
    1032             :     Word16 /*short*/ threshold,                /*I   - Q10*/
    1033             :     Word16 * /*short*/ thresholdModification ) /*I/O - Q10*/
    1034             : {
    1035             :     Word32 harmonic;
    1036             :     Word16 fractional /*Q15*/;
    1037             :     Word16 k /*Q0*/;
    1038             :     Word16 twoTimesFract /*Q10*/;
    1039             : 
    1040             : 
    1041        3532 :     harmonic = L_mult( shl( i, 5 ), F0 );                                            /*Q0 * Q10 = 15Q16*/
    1042        3532 :     k = extract_h( harmonic );                                                       /*Q0*/
    1043        3532 :     fractional = lshr( extract_l( harmonic ), 1 ); /* Fractional part of the i*F0 */ /*Q15*/
    1044        3532 :     twoTimesFract = mult( 2048 /*2 in Q10*/, fractional /*Q15*/ ); /*Q10*/           /* threshold if the center of the peek is between k-1 and k, threshold+2 if the center of the peek is between k and k+1 */
    1045             : 
    1046        3532 :     move16();
    1047        3532 :     thresholdModification[k] = threshold;
    1048        3532 :     move16();
    1049        3532 :     thresholdModification[k - 1] = add( threshold /*Q10*/, twoTimesFract /*Q10*/ ); /*Q10*/
    1050        3532 :     move16();
    1051        3532 :     thresholdModification[k + 1] = add( threshold /*Q10*/, sub( 2048 /*2 in Q10*/, twoTimesFract /*Q10*/ ) /*Q10*/ ); /*Q10*/
    1052        3532 :     return;
    1053             : }
    1054             : 
    1055        1425 : static void modifyThresholds(
    1056             :     Word16 /*short*/ F0,                       /*I   - Q10*/
    1057             :     Word16 /*short*/ origF0,                   /*I   - Q10*/
    1058             :     Word16 * /*short*/ thresholdModification ) /*I/O - Q10*/
    1059             : {
    1060             :     Word16 /*int*/ i, /*int*/ nHarmonics;
    1061             :     Word16 tmp, tmpM, tmpE;
    1062             : 
    1063             : 
    1064        1425 :     IF( origF0 > 0 )
    1065             :     {
    1066         368 :         IF( F0 == 0 )
    1067             :         {
    1068          10 :             nHarmonics /*Q0*/ = s_min( MAX_PEAKS_FROM_PITCH /*Q0*/, shl( ( div_s( LAST_HARMONIC_POS_TO_CHECK /*Q0*/, origF0 /*Q10*/ ) /*Q15*2^10*/ ), -5 /*Q0*2^-5*/ ) /*Q0*/ );
    1069             : 
    1070         109 :             FOR( i = 1; i <= nHarmonics; i++ )
    1071             :             {
    1072          99 :                 modifyThreshold( i, origF0, 717 /*0.7f Q10*/ /*0.7f in Q10*/, thresholdModification );
    1073             :             }
    1074             :         }
    1075         368 :         IF( F0 > 0 )
    1076             :         {
    1077         358 :             nHarmonics /*Q0*/ = s_min( MAX_PEAKS_FROM_PITCH /*Q0*/, shl( ( div_s( LAST_HARMONIC_POS_TO_CHECK /*Q0*/, F0 /*Q10*/ ) /*Q15*2^10*/ ), -5 /*Q0*2^-5*/ ) /*Q0*/ );
    1078             : 
    1079             :             /*(int)(F0/origF0+0.5f)*/
    1080         358 :             BASOP_Util_Divide_MantExp( F0, 0, origF0, 0, &tmpM, &tmpE );
    1081         358 :             tmp = round_fx( L_shl( L_deposit_l( tmpM ), add( tmpE, 1 ) ) );
    1082             : 
    1083         746 :             FOR( i = tmp; i > 0; i-- )
    1084             :             {
    1085         388 :                 modifyThreshold( i, origF0, 358 /*0.35f Q10*/, thresholdModification );
    1086             :             }
    1087        3403 :             FOR( i = 1; i <= nHarmonics; i++ )
    1088             :             {
    1089        3045 :                 modifyThreshold( i, F0, 358 /*0.35f Q10*/, thresholdModification );
    1090             :             }
    1091             :         }
    1092             :     }
    1093        1425 :     return;
    1094             : }
    1095             : 
    1096        1425 : static void findCandidates(
    1097             :     const Word16 nSamples,            /* i: frame size                           */
    1098             :     const Word32 *MDCTSpectrum,       /* i: MDCT spectrum                        */
    1099             :     const Word16 MDCTSpectrum_exp,    /* i: exponent of MDCT spectrum            */
    1100             :     Word16 *thresholdModificationNew, /* o: threshold modification Q10           */
    1101             :     Word16 floorPowerSpectrum         /* i: lower limit for power spectrum bins  Q0*/
    1102             : )
    1103             : {
    1104             :     Word32 powerSpectrum[L_FRAME_MAX];
    1105             :     Word16 powerSpectrum_exp;
    1106             :     Word32 envelope[L_FRAME_MAX];         /*powerSpec_exp + LEVEL_EXP*/
    1107             :     Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
    1108             :     Word16 upperIdx, lowerIdx;
    1109             :     Word16 k, j;
    1110             :     Word32 biggerNeighbor;
    1111             :     Word16 tmp_loop1, tmp_loop2, tmp_loop3;
    1112             : 
    1113             : 
    1114        1425 :     calcPseudoSpec( MDCTSpectrum, MDCTSpectrum_exp, nSamples, floorPowerSpectrum, powerSpectrum, &powerSpectrum_exp );
    1115             : 
    1116        1425 :     getEnvelope( nSamples, powerSpectrum, 0, envelope, smoothedSpectrum );
    1117             : 
    1118        1425 :     set16_fx( thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples ); /*Q10*/
    1119             : 
    1120        1425 :     k = GROUP_LENGTH / 2;
    1121        1425 :     move16();
    1122        1425 :     tmp_loop1 = sub( nSamples, ( GROUP_LENGTH - GROUP_LENGTH / 2 ) );
    1123        1425 :     tmp_loop2 = sub( nSamples, 1 );
    1124      668896 :     WHILE( LE_16( k, tmp_loop1 ) )
    1125             :     {
    1126      667471 :         IF( GT_32( smoothedSpectrum[k], envelope[k] ) )
    1127             :         {
    1128             :             /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */
    1129             :             /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
    1130        6265 :             biggerNeighbor = L_max( powerSpectrum[k - 1], powerSpectrum[k + 1] ); /*powerSpectrum_exp*/
    1131             : 
    1132        6265 :             IF( GE_32( powerSpectrum[k], biggerNeighbor ) )
    1133             :             {
    1134             :                 /* Find the right foot */
    1135        3702 :                 upperIdx = add( k, 1 );
    1136       73801 :                 WHILE( LT_16( upperIdx, tmp_loop2 ) )
    1137             :                 {
    1138             : 
    1139       73655 :                     IF( LT_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx + 1] ) )
    1140             :                     {
    1141             :                         /* Side lobes may increase for certain amount */
    1142        7014 :                         IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[upperIdx + 1] ) )
    1143             :                         {
    1144        3174 :                             BREAK;
    1145             :                         }
    1146             :                         /* Check for further decrease after a side lobe increase */
    1147        4397 :                         FOR( j = add( upperIdx, 1 ); j < tmp_loop2; j++ )
    1148             :                         {
    1149        4397 :                             IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j + 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
    1150             :                             {
    1151        3840 :                                 BREAK;
    1152             :                             }
    1153             :                         }
    1154             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
    1155             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
    1156        3840 :                         IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) )
    1157             :                         {
    1158         382 :                             BREAK;
    1159             :                         }
    1160        3458 :                         upperIdx = sub( j, 1 );
    1161             :                     }
    1162       70099 :                     upperIdx = add( upperIdx, 1 );
    1163             :                 }
    1164             :                 /* left foot */
    1165        3702 :                 lowerIdx = sub( k, 1 );
    1166       43563 :                 WHILE( lowerIdx > 0 )
    1167             :                 {
    1168             : 
    1169       43339 :                     IF( LT_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx - 1] ) )
    1170             :                     {
    1171             :                         /* Side lobes may increase for certain amount */
    1172        6397 :                         IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[lowerIdx - 1] ) )
    1173             :                         {
    1174        3064 :                             BREAK;
    1175             :                         }
    1176             :                         /* Check for further decrease after a side lobe increase */
    1177        3918 :                         FOR( j = sub( lowerIdx, 1 ); j > 0; j-- )
    1178             :                         {
    1179        3918 :                             IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j - 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
    1180             :                             {
    1181        3333 :                                 BREAK;
    1182             :                             }
    1183             :                         }
    1184             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
    1185             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
    1186        3333 :                         IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[lowerIdx - 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx] ) ) )
    1187             :                         {
    1188         414 :                             BREAK;
    1189             :                         }
    1190        2919 :                         lowerIdx = add( j, 1 );
    1191             :                     }
    1192       39861 :                     lowerIdx = sub( lowerIdx, 1 );
    1193             :                 }
    1194             : 
    1195             :                 /* Check if there is a bigger peak up to the next peak foot */
    1196        3702 :                 tmp_loop3 = s_min( upperIdx, tmp_loop1 );
    1197      124737 :                 FOR( j = s_max( GROUP_LENGTH / 2, lowerIdx ); j <= tmp_loop3; j++ )
    1198             :                 {
    1199      121035 :                     if ( GT_32( powerSpectrum[j], powerSpectrum[k] ) )
    1200             :                     {
    1201          18 :                         k = j;
    1202          18 :                         move16();
    1203             :                     }
    1204             :                 }
    1205             : 
    1206             :                 /* Modify thresholds for the following frame */
    1207        3702 :                 tmp_loop3 = add( k, 2 );
    1208       14808 :                 FOR( j = sub( k, 1 ); j < tmp_loop3; j++ )
    1209             :                 {
    1210       11106 :                     thresholdModificationNew[j] = BIG_THRESHOLD; /*Q10*/
    1211       11106 :                     move16();
    1212             : 
    1213       11106 :                     if ( GT_32( smoothedSpectrum[j], envelope[j] ) )
    1214             :                     {
    1215        7219 :                         thresholdModificationNew[j] = SMALL_THRESHOLD; /*Q10*/
    1216        7219 :                         move16();
    1217             :                     }
    1218             :                 }
    1219             :                 /* Jump to the next foot of the peak. */
    1220        3702 :                 k = upperIdx;
    1221        3702 :                 move16();
    1222             :             }
    1223             :         }
    1224      667471 :         k = add( k, 1 );
    1225             :     }
    1226        1425 :     return;
    1227             : }
    1228             : 
    1229           0 : static void RefineThresholdsUsingPitch(
    1230             :     const Word16 nSamples,
    1231             :     const Word16 nSamplesCore,
    1232             :     const Word32 powerSpectrum[], /*Qx*/
    1233             :     const Word32 lastPitchLag,    /*Qx*/
    1234             :     const Word32 currentPitchLag, /*Qx*/
    1235             :     Word16 *pF0,                  /*Q10*/
    1236             :     Word16 *thresholdModification /*Q10*/
    1237             : )
    1238             : {
    1239             :     Word16 pitchIsStable;
    1240             :     Word16 origF0;
    1241             :     Word32 L_tmp;
    1242             : 
    1243             :     /*pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f);*/
    1244           0 :     pitchIsStable = 0;
    1245           0 :     move16();
    1246           0 :     L_tmp = L_abs( L_sub( lastPitchLag, currentPitchLag ) );
    1247           0 :     if ( LT_32( L_tmp, 16384l /*0.25f Q16*/ ) )
    1248             :     {
    1249           0 :         pitchIsStable = 1;
    1250           0 :         move16();
    1251             :     }
    1252             : 
    1253           0 :     IF( pitchIsStable )
    1254             :     {
    1255           0 :         GetF0( nSamples,
    1256             :                nSamplesCore,
    1257             :                powerSpectrum, lastPitchLag, &origF0, pF0 );
    1258             : 
    1259           0 :         modifyThresholds( *pF0, origF0, thresholdModification );
    1260             :     }
    1261             :     ELSE
    1262             :     {
    1263           0 :         *pF0 = 0;
    1264           0 :         move16();
    1265             :     }
    1266           0 :     return;
    1267             : }
    1268             : 
    1269        1425 : static void ivas_findTonalComponents_fx(
    1270             :     Word16 *indexOfTonalPeak,    /* OUT Q0*/
    1271             :     Word16 *lowerIndex,          /* OUT Q0*/
    1272             :     Word16 *upperIndex,          /* OUT Q0*/
    1273             :     Word16 *numIndexes,          /* OUT Q0*/
    1274             :     Word16 nSamples,             /* IN */
    1275             :     const Word32 *powerSpectrum, /* IN Q31-powerSpectrum_e*/
    1276             :     const Word16 powerSpectrum_e,
    1277             :     Word16 F0,                     /* IN */
    1278             :     Word16 *thresholdModification, /* IN Q10*/
    1279             :     Word16 element_mode )          /* IN */
    1280             : {
    1281             :     Word32 envelope[L_FRAME_MAX];         /*powerSpec_exp + LEVEL_EXP*/
    1282             :     Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
    1283             :     Word16 nrOfFIS;
    1284             :     Word16 upperIdx, lowerIdx, lowerBound;
    1285             :     Word16 k, j, m;
    1286             :     Word32 biggerNeighbor;
    1287             :     Word16 tmp_loop1, tmp_loop2, tmp_loop3;
    1288             : 
    1289        1425 :     getEnvelope( nSamples, powerSpectrum, F0, envelope, smoothedSpectrum );
    1290             : 
    1291             : 
    1292        1425 :     nrOfFIS = 0;
    1293        1425 :     move16();
    1294        1425 :     lowerBound = 0;
    1295        1425 :     move16();
    1296             : 
    1297        1425 :     k = GROUP_LENGTH / 2;
    1298        1425 :     move16();
    1299        1425 :     tmp_loop1 = sub( nSamples, ( GROUP_LENGTH - GROUP_LENGTH / 2 ) );
    1300        1425 :     tmp_loop2 = sub( nSamples, 1 );
    1301      692973 :     WHILE( LE_16( k, tmp_loop1 ) )
    1302             :     {
    1303      691548 :         Word64 mult_64 = W_mult_32_16( envelope[k], thresholdModification[k] ); // (Q31-(powerSpectrum_e+LEVEL_EXP))+1+10
    1304      691548 :         Word16 lshift = W_norm( mult_64 );
    1305      691548 :         Word32 mult_32 = W_extract_h( W_shl( mult_64, lshift ) ); //(Q31-(powerSpectrum_e+LEVEL_EXP) + lshift )+11 -32
    1306      691548 :         Word16 mult_exp = sub( Q31, sub( add( sub( Q31, add( powerSpectrum_e, LEVEL_EXP ) ), add( 10, lshift ) ), 31 ) );
    1307      691548 :         Word16 flag = BASOP_Util_Cmp_Mant32Exp( smoothedSpectrum[k], ( powerSpectrum_e + LEVEL_EXP ), mult_32, mult_exp );
    1308             :         /* There is 3 bits headroom in envelope and max of thresholdModification is 16384, so shifting left for 4 would produce overflow only when the result is anyhow close to 1 */
    1309      691548 :         IF( EQ_16( flag, 1 ) )
    1310             :         {
    1311             :             /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */
    1312             :             /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
    1313        4113 :             biggerNeighbor = L_max( powerSpectrum[k - 1], powerSpectrum[k + 1] ); /*Qx*/
    1314             : 
    1315        4113 :             IF( GE_32( powerSpectrum[k], biggerNeighbor ) )
    1316             :             {
    1317             :                 /* Find the right foot */
    1318        2939 :                 upperIdx = add( k, 1 );
    1319       49600 :                 WHILE( LT_16( upperIdx, tmp_loop2 ) )
    1320             :                 {
    1321       49549 :                     IF( LT_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx + 1] ) )
    1322             :                     {
    1323             :                         /* Side lobes may increase for certain amount */
    1324        3185 :                         IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[upperIdx + 1] ) )
    1325             :                         {
    1326        1242 :                             BREAK;
    1327             :                         }
    1328             :                         /* Check for further decrease after a side lobe increase */
    1329        2460 :                         FOR( j = add( upperIdx, 1 ); j < tmp_loop2; j++ )
    1330             :                         {
    1331        2460 :                             IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j + 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
    1332             :                             {
    1333        1943 :                                 BREAK;
    1334             :                             }
    1335             :                         }
    1336             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
    1337             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
    1338        1943 :                         test();
    1339        1943 :                         test();
    1340        1943 :                         test();
    1341        1943 :                         IF( ( EQ_16( element_mode, EVS_MONO ) && GT_32( Mpy_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ||
    1342             :                             ( NE_16( element_mode, EVS_MONO ) && ( GT_64( W_mult_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), W_mult_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ) )
    1343             :                         {
    1344             :                             BREAK;
    1345             :                         }
    1346         297 :                         upperIdx = sub( j, 1 );
    1347             :                     }
    1348       46661 :                     upperIdx = add( upperIdx, 1 );
    1349             :                 }
    1350             :                 /* left foot */
    1351        2939 :                 lowerIdx = sub( k, 1 );
    1352       17711 :                 WHILE( GT_16( lowerIdx, lowerBound ) )
    1353             :                 {
    1354       16730 :                     IF( LT_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx - 1] ) )
    1355             :                     {
    1356             :                         /* Side lobes may increase for certain amount */
    1357        3684 :                         IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[lowerIdx - 1] ) )
    1358             :                         {
    1359        1357 :                             BREAK;
    1360             :                         }
    1361             :                         /* Check for further decrease after a side lobe increase */
    1362        2817 :                         FOR( j = sub( lowerIdx, 1 ); j > 0; j-- )
    1363             :                         {
    1364        2817 :                             IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j - 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
    1365             :                             {
    1366        2327 :                                 BREAK;
    1367             :                             }
    1368             :                         }
    1369             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
    1370             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
    1371        2327 :                         IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[lowerIdx - 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx] ) ) )
    1372             :                         {
    1373         601 :                             BREAK;
    1374             :                         }
    1375        1726 :                         lowerIdx = add( j, 1 );
    1376             :                     }
    1377       14772 :                     lowerIdx = sub( lowerIdx, 1 );
    1378             :                 }
    1379             : 
    1380        2939 :                 lowerBound = upperIdx;
    1381        2939 :                 move16();
    1382             : 
    1383             :                 /* Check if there is a bigger peak up to the next peak foot */
    1384        2939 :                 tmp_loop3 = s_min( upperIdx, tmp_loop1 );
    1385       73539 :                 FOR( j = s_max( GROUP_LENGTH / 2, lowerIdx ); j <= tmp_loop3; j++ )
    1386             :                 {
    1387       70600 :                     if ( GT_32( powerSpectrum[j], powerSpectrum[k] ) )
    1388             :                     {
    1389             : 
    1390           7 :                         k = j;
    1391           7 :                         move16();
    1392             :                     }
    1393             :                 }
    1394             : 
    1395        2939 :                 assert( ( nrOfFIS == 0 ) || ( indexOfTonalPeak[nrOfFIS - 1] < k ) );
    1396             : 
    1397        2939 :                 lowerIndex[nrOfFIS] = sub( k, GROUP_LENGTH / 2 );
    1398        2939 :                 move16();
    1399             : 
    1400        2939 :                 upperIndex[nrOfFIS] = add( k, ( GROUP_LENGTH - GROUP_LENGTH / 2 - 1 ) );
    1401        2939 :                 move16();
    1402             : 
    1403        2939 :                 test();
    1404        2939 :                 IF( ( nrOfFIS > 0 ) && ( LE_16( lowerIndex[nrOfFIS], upperIndex[nrOfFIS - 1] ) ) )
    1405             :                 {
    1406          20 :                     m = shr( add( k, indexOfTonalPeak[nrOfFIS - 1] ), 1 );
    1407          20 :                     upperIndex[nrOfFIS - 1] = m;
    1408          20 :                     move16();
    1409          20 :                     lowerIndex[nrOfFIS] = add( m, 1 );
    1410          20 :                     move16();
    1411             :                 }
    1412             : 
    1413        2939 :                 indexOfTonalPeak[nrOfFIS++] = k;
    1414        2939 :                 move16();
    1415             : 
    1416        2939 :                 IF( EQ_16( nrOfFIS, MAX_NUMBER_OF_IDX ) )
    1417             :                 {
    1418           0 :                     BREAK;
    1419             :                 }
    1420             :                 /* Jump to the next foot of the peak. */
    1421        2939 :                 k = upperIdx;
    1422        2939 :                 move16();
    1423             :             }
    1424             :         }
    1425      691548 :         k = add( k, 1 );
    1426             :     }
    1427             : 
    1428        1425 :     *numIndexes = nrOfFIS;
    1429        1425 :     move16();
    1430        1425 :     return;
    1431             : }
    1432             : 
    1433             : 
    1434        1425 : static void ivas_RefineThresholdsUsingPitch_fx(
    1435             :     const Word16 nSamples,
    1436             :     const Word16 nSamplesCore,
    1437             :     const Word32 powerSpectrum[], /*Qx*/
    1438             :     const Word32 lastPitchLag,    /*Qx*/
    1439             :     const Word32 currentPitchLag, /*Qx*/
    1440             :     Word16 *pF0,                  /*Q10*/
    1441             :     Word16 *thresholdModification /*Q10*/
    1442             : )
    1443             : {
    1444             :     Word16 pitchIsStable;
    1445             :     Word16 origF0;
    1446             :     Word32 L_tmp;
    1447             : 
    1448             :     /*pitchIsStable = (fabs(lastPitchLag-currentPitchLag) < 0.25f);*/
    1449        1425 :     pitchIsStable = 0;
    1450        1425 :     move16();
    1451        1425 :     L_tmp = L_abs( L_sub( lastPitchLag, currentPitchLag ) );
    1452        1425 :     if ( LT_32( L_tmp, 16384l /*0.25f Q16*/ ) )
    1453             :     {
    1454        1425 :         pitchIsStable = 1;
    1455        1425 :         move16();
    1456             :     }
    1457             : 
    1458        1425 :     IF( pitchIsStable )
    1459             :     {
    1460        1425 :         ivas_GetF0_fx( nSamples,
    1461             :                        nSamplesCore,
    1462             :                        powerSpectrum, lastPitchLag, &origF0, pF0 );
    1463             : 
    1464        1425 :         modifyThresholds( *pF0, origF0, thresholdModification );
    1465             :     }
    1466             :     ELSE
    1467             :     {
    1468           0 :         *pF0 = 0;
    1469           0 :         move16();
    1470             :     }
    1471        1425 :     return;
    1472             : }
    1473           0 : static void findTonalComponents(
    1474             :     Word16 *indexOfTonalPeak,      /* OUT Q0*/
    1475             :     Word16 *lowerIndex,            /* OUT Q0*/
    1476             :     Word16 *upperIndex,            /* OUT Q0*/
    1477             :     Word16 *numIndexes,            /* OUT Q0*/
    1478             :     Word16 nSamples,               /* IN */
    1479             :     const Word32 *powerSpectrum,   /* IN Qx*/
    1480             :     Word16 F0,                     /* IN */
    1481             :     Word16 *thresholdModification, /* IN Q10*/
    1482             :     Word16 element_mode )          /* IN */
    1483             : {
    1484             :     Word32 envelope[L_FRAME_MAX];         /*powerSpec_exp + LEVEL_EXP*/
    1485             :     Word32 smoothedSpectrum[L_FRAME_MAX]; /*powerSpec_exp + LEVEL_EXP*/
    1486             :     Word16 nrOfFIS;
    1487             :     Word16 upperIdx, lowerIdx, lowerBound;
    1488             :     Word16 k, j, m;
    1489             :     Word32 biggerNeighbor;
    1490             :     Word16 tmp_loop1, tmp_loop2, tmp_loop3;
    1491             : 
    1492           0 :     getEnvelope( nSamples, powerSpectrum, F0, envelope, smoothedSpectrum );
    1493             : 
    1494             : 
    1495           0 :     nrOfFIS = 0;
    1496           0 :     move16();
    1497           0 :     lowerBound = 0;
    1498           0 :     move16();
    1499             : 
    1500           0 :     k = GROUP_LENGTH / 2;
    1501           0 :     move16();
    1502           0 :     tmp_loop1 = sub( nSamples, ( GROUP_LENGTH - GROUP_LENGTH / 2 ) );
    1503           0 :     tmp_loop2 = sub( nSamples, 1 );
    1504           0 :     WHILE( LE_16( k, tmp_loop1 ) )
    1505             :     {
    1506             :         /* There is 3 bits headroom in envelope and max of thresholdModification is 16384, so shifting left for 4 would produce overflow only when the result is anyhow close to 1 */
    1507           0 :         IF( GT_32( L_shr( smoothedSpectrum[k], 1 ), L_shl( Mpy_32_16_1( envelope[k] /*Q28,powerSpec_exp*/, thresholdModification[k] /*Q10*/ ), 4 ) ) )
    1508             :         {
    1509             :             /* The check that bin at k is bigger than bins at k-1 and k+1 is needed to avoid deadlocks when the thresholds are low. */
    1510             :             /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
    1511           0 :             biggerNeighbor = L_max( powerSpectrum[k - 1], powerSpectrum[k + 1] ); /*Qx*/
    1512             : 
    1513           0 :             IF( GE_32( powerSpectrum[k], biggerNeighbor ) )
    1514             :             {
    1515             :                 /* Find the right foot */
    1516           0 :                 upperIdx = add( k, 1 );
    1517           0 :                 WHILE( LT_16( upperIdx, tmp_loop2 ) )
    1518             :                 {
    1519           0 :                     IF( LT_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx + 1] ) )
    1520             :                     {
    1521             :                         /* Side lobes may increase for certain amount */
    1522           0 :                         IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[upperIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[upperIdx + 1] ) )
    1523             :                         {
    1524           0 :                             BREAK;
    1525             :                         }
    1526             :                         /* Check for further decrease after a side lobe increase */
    1527           0 :                         FOR( j = add( upperIdx, 1 ); j < tmp_loop2; j++ )
    1528             :                         {
    1529           0 :                             IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j + 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
    1530             :                             {
    1531           0 :                                 BREAK;
    1532             :                             }
    1533             :                         }
    1534             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
    1535             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
    1536           0 :                         test();
    1537           0 :                         test();
    1538           0 :                         test();
    1539           0 :                         IF( ( EQ_16( element_mode, EVS_MONO ) && GT_32( Mpy_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ||
    1540             :                             ( NE_16( element_mode, EVS_MONO ) && ( GT_64( W_mult_32_32( L_shl( powerSpectrum[upperIdx + 1], 1 ), powerSpectrum[j] ), W_mult_32_32( powerSpectrum[upperIdx], powerSpectrum[upperIdx] ) ) ) ) )
    1541             :                         {
    1542             :                             BREAK;
    1543             :                         }
    1544           0 :                         upperIdx = sub( j, 1 );
    1545             :                     }
    1546           0 :                     upperIdx = add( upperIdx, 1 );
    1547             :                 }
    1548             :                 /* left foot */
    1549           0 :                 lowerIdx = sub( k, 1 );
    1550           0 :                 WHILE( GT_16( lowerIdx, lowerBound ) )
    1551             :                 {
    1552           0 :                     IF( LT_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx - 1] ) )
    1553             :                     {
    1554             :                         /* Side lobes may increase for certain amount */
    1555           0 :                         IF( LT_32( L_shl( Mpy_32_16_1( powerSpectrum[lowerIdx], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ), powerSpectrum[lowerIdx - 1] ) )
    1556             :                         {
    1557           0 :                             BREAK;
    1558             :                         }
    1559             :                         /* Check for further decrease after a side lobe increase */
    1560           0 :                         FOR( j = sub( lowerIdx, 1 ); j > 0; j-- )
    1561             :                         {
    1562           0 :                             IF( LT_32( powerSpectrum[j], L_shl( Mpy_32_16_1( powerSpectrum[j - 1], ALLOWED_SIDE_LOBE_FLUCTUATION ), ALLOWED_SIDE_LOBE_FLUCTUATION_EXP ) ) )
    1563             :                             {
    1564           0 :                                 BREAK;
    1565             :                             }
    1566             :                         }
    1567             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
    1568             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
    1569           0 :                         IF( GT_32( Mpy_32_32( L_shl( powerSpectrum[lowerIdx - 1], 1 ), powerSpectrum[j] ), Mpy_32_32( powerSpectrum[lowerIdx], powerSpectrum[lowerIdx] ) ) )
    1570             :                         {
    1571           0 :                             BREAK;
    1572             :                         }
    1573           0 :                         lowerIdx = add( j, 1 );
    1574             :                     }
    1575           0 :                     lowerIdx = sub( lowerIdx, 1 );
    1576             :                 }
    1577             : 
    1578           0 :                 lowerBound = upperIdx;
    1579           0 :                 move16();
    1580             : 
    1581             :                 /* Check if there is a bigger peak up to the next peak foot */
    1582           0 :                 tmp_loop3 = s_min( upperIdx, tmp_loop1 );
    1583           0 :                 FOR( j = s_max( GROUP_LENGTH / 2, lowerIdx ); j <= tmp_loop3; j++ )
    1584             :                 {
    1585           0 :                     if ( GT_32( powerSpectrum[j], powerSpectrum[k] ) )
    1586             :                     {
    1587             : 
    1588           0 :                         k = j;
    1589           0 :                         move16();
    1590             :                     }
    1591             :                 }
    1592             : 
    1593           0 :                 assert( ( nrOfFIS == 0 ) || ( indexOfTonalPeak[nrOfFIS - 1] < k ) );
    1594             : 
    1595           0 :                 lowerIndex[nrOfFIS] = sub( k, GROUP_LENGTH / 2 );
    1596           0 :                 move16();
    1597             : 
    1598           0 :                 upperIndex[nrOfFIS] = add( k, ( GROUP_LENGTH - GROUP_LENGTH / 2 - 1 ) );
    1599           0 :                 move16();
    1600             : 
    1601           0 :                 test();
    1602           0 :                 IF( ( nrOfFIS > 0 ) && ( LE_16( lowerIndex[nrOfFIS], upperIndex[nrOfFIS - 1] ) ) )
    1603             :                 {
    1604           0 :                     m = shr( add( k, indexOfTonalPeak[nrOfFIS - 1] ), 1 );
    1605           0 :                     upperIndex[nrOfFIS - 1] = m;
    1606           0 :                     move16();
    1607           0 :                     lowerIndex[nrOfFIS] = add( m, 1 );
    1608           0 :                     move16();
    1609             :                 }
    1610             : 
    1611           0 :                 indexOfTonalPeak[nrOfFIS++] = k;
    1612           0 :                 move16();
    1613             : 
    1614           0 :                 IF( EQ_16( nrOfFIS, MAX_NUMBER_OF_IDX ) )
    1615             :                 {
    1616           0 :                     BREAK;
    1617             :                 }
    1618             :                 /* Jump to the next foot of the peak. */
    1619           0 :                 k = upperIdx;
    1620           0 :                 move16();
    1621             :             }
    1622             :         }
    1623           0 :         k = add( k, 1 );
    1624             :     }
    1625             : 
    1626           0 :     *numIndexes = nrOfFIS;
    1627           0 :     move16();
    1628           0 :     return;
    1629             : }

Generated by: LCOV version 1.14