LCOV - code coverage report
Current view: top level - lib_dec - TonalComponentDetection.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 277 279 99.3 %
Date: 2025-05-23 08:37:30 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : /*====================================================================================
      34             :     EVS Codec 3GPP TS26.443 Nov 04, 2021. Version 12.14.0 / 13.10.0 / 14.6.0 / 15.4.0 / 16.3.0
      35             :   ====================================================================================*/
      36             : 
      37             : #define _USE_MATH_DEFINES
      38             : 
      39             : #include <assert.h>
      40             : #include <stdint.h>
      41             : #include "options.h"
      42             : #ifdef DEBUGGING
      43             : #include "debug.h"
      44             : #endif
      45             : #include <math.h>
      46             : #include "prot.h"
      47             : #include "cnst.h"
      48             : #include "stat_com.h"
      49             : #include "wmc_auto.h"
      50             : #include "ivas_prot.h"
      51             : 
      52             : 
      53             : /*---------------------------------------------------------------------*
      54             :  * Local function prototypes
      55             :  *---------------------------------------------------------------------*/
      56             : 
      57             : static void findStrongestHarmonics( const uint16_t nSamples, const float *powerSpectrum, const float F0, const uint16_t nTotalHarmonics, uint16_t *pHarmonicIndexes, int16_t *pnHarmonics );
      58             : static void CorrectF0( const uint16_t *pHarmonicIndexes, const uint16_t nHarmonics, float *pF0 );
      59             : static void findCandidates( const uint16_t nSamples, const float *MDCTSpectrum, float *thresholdModificationNew, float floorPowerSpectrum );
      60             : static void RefineThresholdsUsingPitch( const uint16_t nSamples, const uint16_t nSamplesCore, const float *powerSpectrum, const float lastPitchLag, const float currentPitchLag, float *pF0, float *thresholdModification );
      61             : static void findTonalComponents( uint16_t *indexOfTonalPeak, uint16_t *lowerIndex, uint16_t *upperIndex, uint16_t *numIndexes, const uint16_t nSamples, const float *powerSpectrum, const float F0, const float *thresholdModification );
      62             : 
      63             : 
      64             : /*-------------------------------------------------------------------*
      65             :  * DetectTonalComponents()
      66             :  *
      67             :  * Detect tonal components in the lastMDCTSpectrum, use
      68             :  * secondLastPowerSpectrum for the precise location of the peaks and
      69             :  * store them in indexOfTonalPeak.  Updates lowerIndex, upperIndex,
      70             :  * pNumIndexes accordingly.
      71             :  *-------------------------------------------------------------------*/
      72             : 
      73        6066 : void DetectTonalComponents(
      74             :     uint16_t indexOfTonalPeak[],
      75             :     uint16_t lowerIndex[],
      76             :     uint16_t upperIndex[],
      77             :     uint16_t *pNumIndexes,
      78             :     const float lastPitchLag,
      79             :     const float currentPitchLag,
      80             :     const float lastMDCTSpectrum[],
      81             :     const float scaleFactors[],
      82             :     const float secondLastPowerSpectrum[],
      83             :     const uint16_t nSamples,
      84             :     const uint16_t nSamplesCore,
      85             :     float floorPowerSpectrum, /* i  : lower limit for power spectrum bins  */
      86             :     const PsychoacousticParameters *psychParamsCurrent )
      87             : {
      88             :     float F0;
      89             :     float thresholdModification[L_FRAME_MAX];
      90        6066 :     float *pScaledMdctSpectrum = thresholdModification;
      91             :     int16_t nBands;
      92             : 
      93             :     /* Convert from 16 bit to 32 bit */
      94        6066 :     mvr2r( lastMDCTSpectrum, pScaledMdctSpectrum, nSamples );
      95        6066 :     if ( psychParamsCurrent == NULL )
      96             :     {
      97        3135 :         nBands = FDNS_NPTS;
      98        3135 :         mdct_noiseShaping( pScaledMdctSpectrum, nSamplesCore, scaleFactors, nBands );
      99             :     }
     100             :     else
     101             :     {
     102        2931 :         sns_shape_spectrum( pScaledMdctSpectrum, psychParamsCurrent, scaleFactors, nSamplesCore );
     103        2931 :         nBands = psychParamsCurrent->nBands;
     104             :     }
     105             : 
     106        6066 :     v_multc( pScaledMdctSpectrum + nSamplesCore, scaleFactors[nBands - 1], pScaledMdctSpectrum + nSamplesCore, nSamples - nSamplesCore );
     107             : 
     108             :     /* Find peak candidates in the last frame. */
     109        6066 :     findCandidates( nSamples, pScaledMdctSpectrum, thresholdModification, floorPowerSpectrum );
     110             : 
     111             :     /* Refine peak candidates using the pitch information */
     112        6066 :     RefineThresholdsUsingPitch( nSamples, nSamplesCore, secondLastPowerSpectrum, lastPitchLag, currentPitchLag, &F0, thresholdModification );
     113             : 
     114             :     /* Find peaks in the second last frame */
     115        6066 :     findTonalComponents( indexOfTonalPeak, lowerIndex, upperIndex, pNumIndexes, nSamples, secondLastPowerSpectrum, F0, thresholdModification );
     116             : 
     117        6066 :     return;
     118             : }
     119             : 
     120             : 
     121             : /*-------------------------------------------------------------------*
     122             :  * RefineTonalComponents()
     123             :  *
     124             :  *-------------------------------------------------------------------*/
     125             : 
     126             : /* When called, the tonal components are already stored in
     127             :  * indexOfTonalPeak.  Detect tonal components in the lastMDCTSpectrum,
     128             :  * use secondLastPowerSpectrum for the precise location of the peaks and
     129             :  * then keep in indexOfTonalPeak only the tonal components that are
     130             :  * again detected Updates indexOfTonalPeak, lowerIndex, upperIndex,
     131             :  * phaseDiff, phases, pNumIndexes accordingly. */
     132         135 : void RefineTonalComponents(
     133             :     uint16_t indexOfTonalPeak[],
     134             :     uint16_t lowerIndex[],
     135             :     uint16_t upperIndex[],
     136             :     float phaseDiff[],
     137             :     float phases[],
     138             :     uint16_t *pNumIndexes,
     139             :     const float lastPitchLag,
     140             :     const float currentPitchLag,
     141             :     const float lastMDCTSpectrum[],
     142             :     const float scaleFactors[],
     143             :     const float secondLastPowerSpectrum[],
     144             :     const uint16_t nSamples,
     145             :     const uint16_t nSamplesCore,
     146             :     float floorPowerSpectrum, /* i  : lower limit for power spectrum bins  */
     147             :     const PsychoacousticParameters *psychParamsCurrent )
     148             : {
     149             :     uint16_t newIndexOfTonalPeak[MAX_NUMBER_OF_IDX];
     150             :     uint16_t newLowerIndex[MAX_NUMBER_OF_IDX];
     151             :     uint16_t newUpperIndex[MAX_NUMBER_OF_IDX];
     152             :     uint16_t newNumIndexes, nPreservedPeaks;
     153             :     uint16_t iNew, iOld, j;
     154             :     float *pOldPhase, *pNewPhase;
     155             : 
     156         135 :     DetectTonalComponents( newIndexOfTonalPeak, newLowerIndex, newUpperIndex, &newNumIndexes, lastPitchLag, currentPitchLag, lastMDCTSpectrum, scaleFactors, secondLastPowerSpectrum,
     157             :                            nSamples, nSamplesCore, floorPowerSpectrum, psychParamsCurrent );
     158             : 
     159         135 :     nPreservedPeaks = 0;
     160         135 :     iNew = 0;
     161         135 :     pOldPhase = phases;
     162         135 :     pNewPhase = phases;
     163         948 :     for ( iOld = 0; iOld < *pNumIndexes; iOld++ )
     164             :     {
     165             :         /* We don't want that the old peak index is at the border of the new peak region, that is why >= newUpperIndex and > newLowerIndex */
     166        1380 :         while ( ( iNew < newNumIndexes ) && ( indexOfTonalPeak[iOld] >= newUpperIndex[iNew] ) )
     167             :         {
     168         567 :             ++iNew;
     169             :         }
     170             : 
     171         813 :         if ( ( iNew < newNumIndexes ) && ( indexOfTonalPeak[iOld] > newLowerIndex[iNew] ) )
     172             :         {
     173         597 :             newIndexOfTonalPeak[nPreservedPeaks] = indexOfTonalPeak[iOld];
     174         597 :             newLowerIndex[nPreservedPeaks] = lowerIndex[iOld];
     175         597 :             newUpperIndex[nPreservedPeaks] = upperIndex[iOld];
     176         597 :             phaseDiff[nPreservedPeaks] = phaseDiff[iOld];
     177             : 
     178        4776 :             for ( j = lowerIndex[iOld]; j <= upperIndex[iOld]; j++ )
     179             :             {
     180        4179 :                 *pNewPhase++ = *pOldPhase++;
     181             :             }
     182             : 
     183         597 :             ++nPreservedPeaks;
     184             :         }
     185             :         else
     186             :         {
     187         216 :             pOldPhase += upperIndex[iOld] - lowerIndex[iOld] + 1;
     188             :         }
     189             :     }
     190             : 
     191         732 :     for ( iNew = 0; iNew < nPreservedPeaks; iNew++ )
     192             :     {
     193         597 :         indexOfTonalPeak[iNew] = newIndexOfTonalPeak[iNew];
     194         597 :         lowerIndex[iNew] = newLowerIndex[iNew];
     195         597 :         upperIndex[iNew] = newUpperIndex[iNew];
     196             :     }
     197             : 
     198         135 :     *pNumIndexes = nPreservedPeaks;
     199             : 
     200         135 :     return;
     201             : }
     202             : 
     203             : 
     204             : /*-------------------------------------------------------------------*
     205             :  * Local functions
     206             :  *-------------------------------------------------------------------*/
     207             : 
     208        6066 : static void calcPseudoSpec(
     209             :     const float *mdctSpec,
     210             :     const uint16_t nSamples,
     211             :     float floorPowerSpectrum,
     212             :     float *powerSpec )
     213             : {
     214             :     int16_t k;
     215             :     float x;
     216             : 
     217     3019473 :     for ( k = 1; k <= nSamples - 2; k++ )
     218             :     {
     219     3013407 :         x = ( mdctSpec[k + 1] - mdctSpec[k - 1] ); /* An MDST estimate */
     220     3013407 :         x = mdctSpec[k] * mdctSpec[k] + x * x;
     221     3013407 :         powerSpec[k] = max( floorPowerSpectrum, x );
     222             :     }
     223             : 
     224        6066 :     powerSpec[0] = 0.5f * powerSpec[1];
     225        6066 :     powerSpec[nSamples - 1] = 0.5f * powerSpec[nSamples - 2];
     226             : 
     227        6066 :     return;
     228             : }
     229             : 
     230       12132 : static void getEnvelope(
     231             :     const int16_t nSamples,
     232             :     const float *powerSpec,
     233             :     float F0,
     234             :     float *envelope,
     235             :     float *smoothedSpectrum )
     236             : {
     237             :     int16_t nFilterLength, nHalfFilterLength, nSecondHalfFilterLength, n1, n2;
     238             :     int16_t i;
     239             :     double sum; /* double is required to avoid precision problems in the optimized version. */
     240             : 
     241       12132 :     if ( F0 == 0 )
     242             :     {
     243       10698 :         nFilterLength = 15;
     244             :     }
     245        1434 :     else if ( F0 <= 10.0f )
     246             :     {
     247         540 :         nFilterLength = 11;
     248             :     }
     249         894 :     else if ( F0 >= 22.0f )
     250             :     {
     251             :         /* For F0 >= 22 peak is isolated well enough with the filter length of 23.
     252             :            This case is however not triggered due to the limit of pit_min,
     253             :            but the line is left for security reasons. */
     254          21 :         nFilterLength = 23;
     255             :     }
     256             :     else
     257             :     {
     258         873 :         nFilterLength = 1 + 2 * (int16_t) ( F0 / 2 );
     259             :     }
     260             : 
     261       12132 :     nHalfFilterLength = nFilterLength / 2;
     262       12132 :     n1 = nHalfFilterLength + 1;
     263       12132 :     nSecondHalfFilterLength = nFilterLength - nHalfFilterLength;
     264       12132 :     n2 = nSecondHalfFilterLength - 1;
     265             : 
     266       12132 :     assert( ( nFilterLength >= 7 ) && ( nFilterLength <= 23 ) && ( nFilterLength % 2 == 1 ) );
     267             : 
     268       12132 :     sum = 0;
     269       95625 :     for ( i = 0; i < n2; i++ )
     270             :     {
     271       83493 :         sum += LEVEL_ABOVE_ENVELOPE * powerSpec[i];
     272             :     }
     273             : 
     274             :     /* No need for PTR_INIT for powerSpec[i+n2] as we continue from the previous loop */
     275      107757 :     for ( i = 0; i < n1; i++ )
     276             :     {
     277       95625 :         sum += LEVEL_ABOVE_ENVELOPE * powerSpec[i + n2];
     278             :         /* 1/(i+nSecondHalfFilterLength) needs to be stored in a table for each filter length */
     279       95625 :         envelope[i] = (float) sum / ( i + nSecondHalfFilterLength );
     280             :     }
     281       12132 :     sum /= nFilterLength; /* 1/nFilterLength is from a table */
     282             : 
     283             :     /* No need for PTR_INIT for powerSpec[i+n2] as we continue from the previous loop */
     284     5884092 :     for ( i = n1; i < nSamples - n2; i++ )
     285             :     {
     286     5871960 :         sum += LEVEL_ABOVE_ENVELOPE * ( powerSpec[i + n2] - powerSpec[i - n1] ) / nFilterLength; /* LEVEL_ABOVE_ENVELOPE/nFilterLength is from a table */
     287     5871960 :         envelope[i] = (float) sum;
     288             :     }
     289       12132 :     sum *= nFilterLength;
     290             : 
     291             :     /* No need for PTR_INIT for powerSpec[i-n1] as we continue from the previous loop */
     292       95625 :     for ( i = nSamples - n2; i < nSamples; i++ )
     293             :     {
     294       83493 :         sum -= LEVEL_ABOVE_ENVELOPE * powerSpec[i - n1];
     295             :         /* 1/(nSamples-(i-nHalfFilterLength)) needs to be stored in a table for each filter length */
     296       83493 :         envelope[i] = (float) sum / ( nSamples - ( i - nHalfFilterLength ) );
     297             :     }
     298             : 
     299     6038946 :     for ( i = 1; i < nSamples - 1; i++ )
     300             :     {
     301     6026814 :         smoothedSpectrum[i] = 0.75f * powerSpec[i - 1] + powerSpec[i] + 0.75f * powerSpec[i + 1];
     302             :     }
     303             : 
     304       12132 :     smoothedSpectrum[0] = powerSpec[0] + 0.75f * powerSpec[1];
     305       12132 :     smoothedSpectrum[nSamples - 1] = 0.75f * powerSpec[nSamples - 2] + powerSpec[nSamples - 1];
     306             : 
     307       12132 :     return;
     308             : }
     309             : 
     310        6066 : static void GetF0(
     311             :     const uint16_t nSamples,     /* i*/
     312             :     const uint16_t nSamplesCore, /* i*/
     313             :     const float *powerSpectrum,  /* i*/
     314             :     const float pitchLag,        /* i*/
     315             :     float *pOrigF0,              /* i/o*/
     316             :     float *pF0                   /* i/o*/
     317             : )
     318             : {
     319             :     float halfPitchLag;
     320             :     uint16_t rgiStrongHarmonics[MAX_PEAKS_FROM_PITCH];
     321             :     int16_t nTotalHarmonics, nStrongHarmonics;
     322             : 
     323        6066 :     assert( LAST_HARMONIC_POS_TO_CHECK <= nSamplesCore );
     324             : 
     325             :     /* Use only F0 >= 100 Hz */
     326        6066 :     if ( ( pitchLag > 0 ) && ( pitchLag <= 0.5f * nSamplesCore ) )
     327             :     {
     328        1497 :         halfPitchLag = 0.5f * pitchLag;
     329        1497 :         *pF0 = nSamplesCore / halfPitchLag;
     330        1497 :         *pOrigF0 = *pF0;
     331        1497 :         if ( nSamples < 2 * LAST_HARMONIC_POS_TO_CHECK )
     332             :         {
     333         108 :             nTotalHarmonics = (int16_t) ( nSamples / ( *pF0 ) );
     334             :         }
     335             :         else
     336             :         {
     337        1389 :             nTotalHarmonics = (int16_t) ( 2 * LAST_HARMONIC_POS_TO_CHECK / ( *pF0 ) ); /* For correcting F0 we go 2 times the last harmonic position that will be used */
     338             :         }
     339             : 
     340             :         /* Get in rgiStrongHarmonics all i for which i*F0 are the strongest harmonics */
     341        1497 :         findStrongestHarmonics( nSamples, powerSpectrum, *pF0, nTotalHarmonics, rgiStrongHarmonics, &nStrongHarmonics );
     342        1497 :         CorrectF0( rgiStrongHarmonics, nStrongHarmonics, pF0 );
     343             :     }
     344             :     else
     345             :     {
     346        4569 :         *pF0 = 0;
     347        4569 :         *pOrigF0 = 0;
     348             :     }
     349             : 
     350        6066 :     return;
     351             : }
     352             : 
     353        1497 : static void findStrongestHarmonics(
     354             :     const uint16_t nSamples,
     355             :     const float *powerSpectrum,
     356             :     const float F0,
     357             :     const uint16_t nTotalHarmonics,
     358             :     uint16_t *pHarmonicIndexes,
     359             :     int16_t *pnHarmonics )
     360             : {
     361             :     float peaks[MAX_PEAKS_FROM_PITCH], smallestPeak;
     362             :     uint16_t nPeaksToCheck, nPeaks, iSmallestPeak;
     363             :     int16_t i, l, k;
     364             : 
     365        1497 :     nPeaks = 0;
     366        1497 :     iSmallestPeak = 0;
     367        1497 :     smallestPeak = FLT_MAX;
     368        1497 :     nPeaksToCheck = min( nTotalHarmonics, MAX_PEAKS_FROM_PITCH + 1 );
     369             : 
     370       16443 :     for ( i = 1; i < nPeaksToCheck; i++ )
     371             :     {
     372             :         float newPeak;
     373             : 
     374       14946 :         k = (int16_t) ( i * F0 );
     375       14946 :         assert( k > 0 && k < 2 * LAST_HARMONIC_POS_TO_CHECK && k < nSamples );
     376             : 
     377       14946 :         newPeak = powerSpectrum[k];
     378       14946 :         peaks[nPeaks] = newPeak;
     379       14946 :         pHarmonicIndexes[nPeaks] = i;
     380       14946 :         if ( newPeak <= smallestPeak )
     381             :         {
     382        7626 :             iSmallestPeak = nPeaks;
     383        7626 :             smallestPeak = newPeak;
     384             :         }
     385       14946 :         ++nPeaks;
     386             :     }
     387             : 
     388       25413 :     for ( ; i < nTotalHarmonics; i++ )
     389             :     {
     390             :         float newPeak;
     391             : 
     392       23916 :         k = (int16_t) ( i * F0 );
     393       23916 :         assert( k > 0 && k < 2 * LAST_HARMONIC_POS_TO_CHECK && k < nSamples );
     394       23916 :         newPeak = powerSpectrum[k];
     395             : 
     396       23916 :         if ( newPeak > smallestPeak )
     397             :         {
     398        3717 :             peaks[iSmallestPeak] = newPeak;
     399        3717 :             pHarmonicIndexes[iSmallestPeak] = i;
     400        3717 :             smallestPeak = newPeak;
     401       40887 :             for ( l = 0; l < MAX_PEAKS_FROM_PITCH; l++ )
     402             :             {
     403       37170 :                 if ( peaks[l] <= smallestPeak )
     404             :                 {
     405        7578 :                     iSmallestPeak = l;
     406        7578 :                     smallestPeak = peaks[l];
     407             :                 }
     408             :             }
     409             :         }
     410             :     }
     411        1497 :     sort( pHarmonicIndexes, nPeaks );
     412        1497 :     *pnHarmonics = nPeaks;
     413             : 
     414        1497 :     return;
     415             : }
     416             : 
     417             : /* Use new F0, for which harmonics are most common in pHarmonicIndexes */
     418        1497 : static void CorrectF0(
     419             :     const uint16_t *pHarmonicIndexes,
     420             :     const uint16_t nHarmonics,
     421             :     float *pF0 )
     422             : {
     423             :     int16_t i;
     424             :     float F0;
     425             :     uint16_t diff[MAX_PEAKS_FROM_PITCH - 1], sortedDiff[MAX_PEAKS_FROM_PITCH - 1];
     426             :     uint16_t iMostCommonDiff, nMostCommonDiff, nSameDiff, iMult;
     427             : 
     428       14970 :     for ( i = 0; i < MAX_PEAKS_FROM_PITCH - 1; i++ )
     429             :     {
     430       13473 :         diff[i] = 0;
     431       13473 :         sortedDiff[i] = 0;
     432             :     }
     433             : 
     434        1497 :     F0 = *pF0;
     435        1497 :     if ( F0 > 0 && nHarmonics > 0 )
     436             :     {
     437       14946 :         for ( i = 0; i < nHarmonics - 1; i++ )
     438             :         {
     439       13449 :             diff[i] = pHarmonicIndexes[i + 1] - pHarmonicIndexes[i];
     440       13449 :             sortedDiff[i] = diff[i];
     441             :         }
     442        1497 :         sort( sortedDiff, nHarmonics - 1 );
     443        1497 :         iMostCommonDiff = sortedDiff[0];
     444        1497 :         nSameDiff = 1;
     445        1497 :         i = 1;
     446        1497 :         if ( sortedDiff[0] * pHarmonicIndexes[0] == 1 )
     447             :         {
     448             :             /* Find how many distances between peaks have length 1 */
     449       11640 :             for ( ; i < nHarmonics - 1; i++ )
     450             :             {
     451       10344 :                 if ( sortedDiff[i] == 1 )
     452             :                 {
     453        8127 :                     ++nSameDiff;
     454             :                 }
     455             :             }
     456             :         }
     457        1497 :         nMostCommonDiff = nSameDiff;
     458             : 
     459             :         /* 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 */
     460             :         /* Otherwise find the most common distance between peaks */
     461        1497 :         if ( nSameDiff < 3 )
     462             :         {
     463             :             /* Find the most common difference */
     464        2118 :             for ( i = nSameDiff; i < nHarmonics - 1; i++ )
     465             :             {
     466        1878 :                 if ( sortedDiff[i] == sortedDiff[i - 1] )
     467             :                 {
     468        1350 :                     ++nSameDiff;
     469             :                 }
     470             :                 else
     471             :                 {
     472         528 :                     if ( nSameDiff > nMostCommonDiff )
     473             :                     {
     474         240 :                         nMostCommonDiff = nSameDiff;
     475         240 :                         iMostCommonDiff = sortedDiff[i - 1];
     476             :                     }
     477             :                     else
     478             :                     {
     479         288 :                         if ( ( nSameDiff == nMostCommonDiff ) && ( abs( (int16_t) iMostCommonDiff - (int16_t) pHarmonicIndexes[0] ) > abs( (int16_t) sortedDiff[i - 1] - (int16_t) pHarmonicIndexes[0] ) ) )
     480             :                         {
     481          18 :                             nMostCommonDiff = nSameDiff;
     482          18 :                             iMostCommonDiff = sortedDiff[i - 1];
     483             :                         }
     484             :                     }
     485         528 :                     nSameDiff = 1;
     486             :                 }
     487             :             }
     488             : 
     489         240 :             if ( nSameDiff > nMostCommonDiff )
     490             :             {
     491          69 :                 nMostCommonDiff = nSameDiff;
     492          69 :                 iMostCommonDiff = sortedDiff[nHarmonics - 2];
     493             :             }
     494             :         }
     495             : 
     496             :         /* If there are enough peaks at the same distance */
     497        1497 :         if ( nMostCommonDiff >= MAX_PEAKS_FROM_PITCH / 2 )
     498             :         {
     499        1368 :             iMult = 1;
     500        1407 :             for ( i = 0; i < nHarmonics - 1; i++ )
     501             :             {
     502        1407 :                 if ( diff[i] == iMostCommonDiff )
     503             :                 {
     504        1311 :                     iMult = pHarmonicIndexes[i];
     505        1311 :                     break;
     506             :                 }
     507             : 
     508             :                 /* for rare cases of octave mismatch or missing harmonics */
     509          96 :                 if ( ( i < nHarmonics - 2 ) && ( diff[i] == diff[i + 1] ) && ( diff[i] + diff[i + 1] == iMostCommonDiff ) )
     510             :                 {
     511          57 :                     iMult = pHarmonicIndexes[i];
     512          57 :                     break;
     513             :                 }
     514             :             }
     515             : 
     516             :             /* If the real F0 is much higher than the original F0 from the pitch */
     517        1368 :             if ( iMult <= 3 )
     518             :             {
     519             :                 /* Use iMostCommonDiff, because the lowest pHarmonicIndexes[i] (which is equal to iMult) may not correspond to the new F0, but to it's multiple */
     520        1353 :                 F0 = iMostCommonDiff * F0;
     521             :             }
     522             :             else
     523             :             {
     524          15 :                 F0 = 0;
     525             :             }
     526             :         }
     527             :         /* 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 */
     528             :         /* Otherwise don't use F0 */
     529         129 :         else if ( ( iMostCommonDiff > 1 ) || ( nMostCommonDiff < 3 ) )
     530             :         {
     531             :             /* Not enough peaks at the same distance => don't use the pitch. */
     532          48 :             F0 = 0;
     533             :         }
     534        1497 :         *pF0 = F0;
     535             :     }
     536             : 
     537        1497 :     return;
     538             : }
     539             : 
     540       15168 : static void modifyThreshold(
     541             :     const int16_t i,
     542             :     float F0,
     543             :     float threshold,
     544             :     float *thresholdModification )
     545             : {
     546             :     float harmonic, fractional, twoTimesFract;
     547             :     int16_t k;
     548             : 
     549       15168 :     harmonic = i * F0;
     550       15168 :     k = (int16_t) harmonic;
     551       15168 :     fractional = harmonic - k;         /* Fractional part of the i*F0 */
     552       15168 :     twoTimesFract = 2.0f * fractional; /* threshold if the centar of the peek is between k-1 and k, threshold+2 if the centar of the peek is between k and k+1 */
     553       15168 :     thresholdModification[k] = threshold;
     554       15168 :     thresholdModification[k - 1] = threshold + twoTimesFract;
     555       15168 :     thresholdModification[k + 1] = threshold + 2.0f - twoTimesFract;
     556             : 
     557       15168 :     return;
     558             : }
     559             : 
     560        6066 : static void modifyThresholds(
     561             :     float F0,
     562             :     float origF0,
     563             :     float *thresholdModification )
     564             : {
     565             :     int16_t i, nHarmonics;
     566             : 
     567        6066 :     if ( ( F0 == 0 ) && ( origF0 > 0 ) )
     568             :     {
     569          63 :         nHarmonics = min( MAX_PEAKS_FROM_PITCH, (int16_t) ( LAST_HARMONIC_POS_TO_CHECK / origF0 ) );
     570         693 :         for ( i = 1; i <= nHarmonics; i++ )
     571             :         {
     572         630 :             modifyThreshold( i, origF0, 0.7f, thresholdModification );
     573             :         }
     574             :     }
     575        6003 :     else if ( ( F0 > 0 ) && ( origF0 > 0 ) )
     576             :     {
     577        1434 :         nHarmonics = min( MAX_PEAKS_FROM_PITCH, (int16_t) ( LAST_HARMONIC_POS_TO_CHECK / F0 ) );
     578             : 
     579        3003 :         for ( i = (int16_t) ( F0 / origF0 + 0.5f ); i > 0; i-- )
     580             :         {
     581        1569 :             modifyThreshold( i, origF0, 0.35f, thresholdModification );
     582             :         }
     583       14403 :         for ( i = 1; i <= nHarmonics; i++ )
     584             :         {
     585       12969 :             modifyThreshold( i, F0, 0.35f, thresholdModification );
     586             :         }
     587             :     }
     588             : 
     589        6066 :     return;
     590             : }
     591             : 
     592        6066 : static void findCandidates(
     593             :     const uint16_t nSamples,
     594             :     const float *MDCTSpectrum,
     595             :     float *thresholdModificationNew,
     596             :     float floorPowerSpectrum /* i  : lower limit for power spectrum bins  */
     597             : )
     598             : {
     599             :     float powerSpectrum[L_FRAME_MAX];
     600             :     float envelope[L_FRAME_MAX];
     601             :     float smoothedSpectrum[L_FRAME_MAX];
     602             :     uint16_t upperIdx, lowerIdx;
     603             :     int16_t k, j;
     604             : 
     605        6066 :     calcPseudoSpec( MDCTSpectrum, nSamples, floorPowerSpectrum, powerSpectrum );
     606        6066 :     getEnvelope( nSamples, powerSpectrum, 0, envelope, smoothedSpectrum );
     607             : 
     608        6066 :     set_f( thresholdModificationNew, UNREACHABLE_THRESHOLD, nSamples );
     609     2840973 :     for ( k = GROUP_LENGTH / 2; k <= nSamples - ( GROUP_LENGTH - GROUP_LENGTH / 2 ); k++ )
     610             :     {
     611     2834907 :         if ( smoothedSpectrum[k] > envelope[k] )
     612             :         {
     613             :             /* 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. */
     614             :             /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
     615             :             float biggerNeighbor;
     616       27627 :             biggerNeighbor = max( powerSpectrum[k - 1], powerSpectrum[k + 1] );
     617       27627 :             if ( powerSpectrum[k] >= biggerNeighbor )
     618             :             {
     619             :                 /* Find the right foot */
     620      152778 :                 for ( upperIdx = k + 1; upperIdx < nSamples - 1; upperIdx++ )
     621             :                 {
     622      152610 :                     if ( powerSpectrum[upperIdx] < powerSpectrum[upperIdx + 1] )
     623             :                     {
     624             :                         /* Side lobes may increase for certain ammount */
     625       17874 :                         if ( ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[upperIdx] < powerSpectrum[upperIdx + 1] )
     626             :                         {
     627        9051 :                             break;
     628             :                         }
     629             :                         /* Check for further decrease after a side lobe increase */
     630       11124 :                         for ( j = upperIdx + 1; j < nSamples - 1; j++ )
     631             :                         {
     632       11124 :                             if ( powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[j + 1] )
     633             :                             {
     634        8823 :                                 break;
     635             :                             }
     636             :                         }
     637             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
     638             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
     639        8823 :                         if ( 2.0f * powerSpectrum[upperIdx + 1] * powerSpectrum[j] > powerSpectrum[upperIdx] * powerSpectrum[upperIdx] )
     640             :                         {
     641        7191 :                             break;
     642             :                         }
     643        1632 :                         upperIdx = j - 1; /* Reinitialize pointers due to the change of upperIdx */
     644             :                     }
     645             :                 }
     646             :                 /* left foot */
     647      115335 :                 for ( lowerIdx = k - 1; lowerIdx > 0; lowerIdx-- )
     648             :                 {
     649      114993 :                     if ( powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx - 1] )
     650             :                     {
     651             :                         /* Side lobes may increase for certain ammount */
     652       17328 :                         if ( ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx - 1] )
     653             :                         {
     654        9045 :                             break;
     655             :                         }
     656             :                         /* Check for further decrease after a side lobe increase */
     657       10212 :                         for ( j = lowerIdx - 1; j > 0; j-- )
     658             :                         {
     659       10212 :                             if ( powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[j - 1] )
     660             :                             {
     661        8283 :                                 break;
     662             :                             }
     663             :                         }
     664             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
     665             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
     666        8283 :                         if ( 2.0f * powerSpectrum[lowerIdx - 1] * powerSpectrum[j] > powerSpectrum[lowerIdx] * powerSpectrum[lowerIdx] )
     667             :                         {
     668        7023 :                             break;
     669             :                         }
     670        1260 :                         lowerIdx = j + 1; /* Reinitialize pointers due to the change of lowerIdx */
     671             :                     }
     672             :                 }
     673             : 
     674             :                 /* Check if there is a bigger peak up to the next peak foot */
     675      302796 :                 for ( j = max( GROUP_LENGTH / 2, lowerIdx ); j <= min( upperIdx, nSamples - ( GROUP_LENGTH - GROUP_LENGTH / 2 ) ); j++ )
     676             :                 {
     677      286386 :                     if ( powerSpectrum[j] > powerSpectrum[k] )
     678             :                     {
     679         153 :                         k = j; /* PTR_INIT for powerSpectrum[k] */
     680             :                     }
     681             :                 }
     682             : 
     683             :                 /* Modify thresholds for the following frame */
     684       65640 :                 for ( j = k - 1; j < k + 2; j++ )
     685             :                 {
     686       49230 :                     if ( smoothedSpectrum[j] > envelope[j] )
     687             :                     {
     688       32034 :                         thresholdModificationNew[j] = SMALL_THRESHOLD;
     689             :                     }
     690             :                     else
     691             :                     {
     692       17196 :                         thresholdModificationNew[j] = BIG_THRESHOLD;
     693             :                     }
     694             :                 }
     695             :                 /* Jump to the next foot of the peak. */
     696       16410 :                 k = upperIdx; /* Reinitialize pointers due to the change of k */
     697             :             }
     698             :         }
     699             :     }
     700             : 
     701        6066 :     return;
     702             : }
     703             : 
     704        6066 : static void RefineThresholdsUsingPitch(
     705             :     const uint16_t nSamples,
     706             :     const uint16_t nSamplesCore,
     707             :     const float *powerSpectrum,
     708             :     const float lastPitchLag,
     709             :     const float currentPitchLag,
     710             :     float *pF0,
     711             :     float *thresholdModification )
     712             : {
     713             :     int16_t pitchIsStable;
     714             :     float origF0;
     715             : 
     716        6066 :     pitchIsStable = ( fabs( lastPitchLag - currentPitchLag ) < 0.25f );
     717        6066 :     if ( pitchIsStable )
     718             :     {
     719        6066 :         GetF0( nSamples, nSamplesCore, powerSpectrum, lastPitchLag, &origF0, pF0 );
     720             : 
     721        6066 :         modifyThresholds( *pF0, origF0, thresholdModification );
     722             :     }
     723             :     else
     724             :     {
     725           0 :         *pF0 = 0;
     726             :     }
     727             : 
     728        6066 :     return;
     729             : }
     730             : 
     731        6066 : static void findTonalComponents(
     732             :     uint16_t *indexOfTonalPeak,        /* OUT */
     733             :     uint16_t *lowerIndex,              /* OUT */
     734             :     uint16_t *upperIndex,              /* OUT */
     735             :     uint16_t *numIndexes,              /* OUT */
     736             :     const uint16_t nSamples,           /* IN */
     737             :     const float *powerSpectrum,        /* IN */
     738             :     const float F0,                    /* IN */
     739             :     const float *thresholdModification /* IN */
     740             : )
     741             : {
     742             :     float envelope[L_FRAME_MAX];
     743             :     float smoothedSpectrum[L_FRAME_MAX];
     744             : 
     745             :     uint16_t nrOfFIS;
     746             :     uint16_t upperIdx, lowerIdx, lowerBound;
     747             :     int16_t k, j;
     748             : 
     749        6066 :     getEnvelope( nSamples, powerSpectrum, F0, envelope, smoothedSpectrum );
     750        6066 :     nrOfFIS = 0;
     751        6066 :     lowerBound = 0;
     752     2872104 :     for ( k = GROUP_LENGTH / 2; k <= nSamples - ( GROUP_LENGTH - GROUP_LENGTH / 2 ); k++ )
     753             :     {
     754     2866038 :         if ( smoothedSpectrum[k] > envelope[k] * thresholdModification[k] )
     755             :         {
     756             :             /* 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. */
     757             :             /* It removes some true peaks, especially if non weighted sum is used for the smoothed spectrum. */
     758             :             float biggerNeighbor;
     759       18033 :             biggerNeighbor = max( powerSpectrum[k - 1], powerSpectrum[k + 1] );
     760       18033 :             if ( powerSpectrum[k] >= biggerNeighbor )
     761             :             {
     762             :                 /* Find the right foot */
     763      121812 :                 for ( upperIdx = k + 1; upperIdx < nSamples - 1; upperIdx++ )
     764             :                 {
     765      121716 :                     if ( powerSpectrum[upperIdx] < powerSpectrum[upperIdx + 1] )
     766             :                     {
     767             :                         /* Side lobes may increase for certain ammount */
     768       13728 :                         if ( ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[upperIdx] < powerSpectrum[upperIdx + 1] )
     769             :                         {
     770        5655 :                             break;
     771             :                         }
     772             :                         /* Check for further decrease after a side lobe increase */
     773       10215 :                         for ( j = upperIdx + 1; j < nSamples - 1; j++ )
     774             :                         {
     775       10215 :                             if ( powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[j + 1] )
     776             :                             {
     777        8073 :                                 break;
     778             :                             }
     779             :                         }
     780             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
     781             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
     782        8073 :                         if ( 2.0f * powerSpectrum[upperIdx + 1] * powerSpectrum[j] > powerSpectrum[upperIdx] * powerSpectrum[upperIdx] )
     783             :                         {
     784        6813 :                             break;
     785             :                         }
     786        1260 :                         upperIdx = j - 1; /* Reinitialize pointers due to the change of upperIdx */
     787             :                     }
     788             :                 }
     789             :                 /* left foot */
     790       53967 :                 for ( lowerIdx = k - 1; lowerIdx > lowerBound; lowerIdx-- )
     791             :                 {
     792       52149 :                     if ( powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx - 1] )
     793             :                     {
     794             :                         /* Side lobes may increase for certain ammount */
     795       12030 :                         if ( ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[lowerIdx] < powerSpectrum[lowerIdx - 1] )
     796             :                         {
     797        4620 :                             break;
     798             :                         }
     799             :                         /* Check for further decrease after a side lobe increase */
     800        9531 :                         for ( j = lowerIdx - 1; j > 0; j-- )
     801             :                         {
     802        9531 :                             if ( powerSpectrum[j] < ALLOWED_SIDE_LOBE_FLUCTUATION * powerSpectrum[j - 1] )
     803             :                             {
     804        7410 :                                 break;
     805             :                             }
     806             :                         }
     807             :                         /* Side lobe increase must be 2 times smaller than the decrease to the foot */
     808             :                         /* Eq. to 2.0f*powerSpectrum[lowerIdx-1]/powerSpectrum[lowerIdx] > powerSpectrum[lowerIdx]/powerSpectrum[j] */
     809        7410 :                         if ( 2.0f * powerSpectrum[lowerIdx - 1] * powerSpectrum[j] > powerSpectrum[lowerIdx] * powerSpectrum[lowerIdx] )
     810             :                         {
     811        6126 :                             break;
     812             :                         }
     813        1284 :                         lowerIdx = j + 1; /* Reinitialize pointers due to the change of lowerIdx */
     814             :                     }
     815             :                 }
     816       12564 :                 lowerBound = upperIdx;
     817             : 
     818             :                 /* Check if there is a bigger peak up to the next peak foot */
     819      203193 :                 for ( j = max( GROUP_LENGTH / 2, lowerIdx ); j <= min( upperIdx, nSamples - ( GROUP_LENGTH - GROUP_LENGTH / 2 ) ); j++ )
     820             :                 {
     821      190629 :                     if ( powerSpectrum[j] > powerSpectrum[k] )
     822             :                     {
     823           9 :                         k = j; /* PTR_INIT for powerSpectrum[k] */
     824             :                     }
     825             :                 }
     826             : 
     827       12564 :                 assert( ( nrOfFIS == 0 ) || ( indexOfTonalPeak[nrOfFIS - 1] < k ) );
     828       12564 :                 lowerIndex[nrOfFIS] = k - GROUP_LENGTH / 2;
     829       12564 :                 upperIndex[nrOfFIS] = k + ( GROUP_LENGTH - GROUP_LENGTH / 2 - 1 );
     830       12564 :                 if ( ( nrOfFIS > 0 ) && ( lowerIndex[nrOfFIS] <= upperIndex[nrOfFIS - 1] ) )
     831             :                 {
     832          84 :                     int16_t m = ( k + indexOfTonalPeak[nrOfFIS - 1] ) / 2;
     833          84 :                     upperIndex[nrOfFIS - 1] = m;
     834          84 :                     lowerIndex[nrOfFIS] = m + 1;
     835             :                 }
     836       12564 :                 indexOfTonalPeak[nrOfFIS++] = k;
     837       12564 :                 if ( nrOfFIS == MAX_NUMBER_OF_IDX )
     838             :                 {
     839           0 :                     break;
     840             :                 }
     841             :                 /* Jump to the next foot of the peak. */
     842       12564 :                 k = upperIdx; /* Reinitialize pointers due to the change of k */
     843             :             }
     844             :         }
     845             :     }
     846        6066 :     *numIndexes = nrOfFIS;
     847             : 
     848        6066 :     return;
     849             : }

Generated by: LCOV version 1.14