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

Generated by: LCOV version 1.14