LCOV - code coverage report
Current view: top level - lib_enc - tns_base_enc.c (source / functions) Hit Total Coverage
Test: Coverage on main -- short test vectors @ 6c9ddc4024a9c0e1ecb8f643f114a84a0e26ec6b Lines: 119 125 95.2 %
Date: 2025-05-23 08:37:30 Functions: 8 8 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             : #include <assert.h>
      38             : #include <stdint.h>
      39             : #include "options.h"
      40             : #include "wmc_auto.h"
      41             : #include "cnst.h"
      42             : #include "rom_com.h"
      43             : #include "prot.h"
      44             : #include "stat_com.h"
      45             : 
      46             : /*----------------------------------------------------------------------------
      47             :  * Local constants
      48             :  *---------------------------------------------------------------------------*/
      49             : 
      50             : #define HLM_MIN_NRG ( PCM16_TO_FLT_FAC * 2 * NORM_MDCT_FACTOR / ( 640 * 640 ) )
      51             : 
      52             : #define MAX_SUBDIVISIONS 3
      53             : 
      54             : 
      55             : /*----------------------------------------------------------------------------
      56             :  * Local prototypes
      57             :  *---------------------------------------------------------------------------*/
      58             : 
      59             : static void GetFilterParameters( const float rxx[], const int16_t maxOrder, STnsFilter *pTnsFilter );
      60             : 
      61             : static void Parcor2Index( const float parCoeff[], int16_t index[], const int16_t order );
      62             : 
      63             : static void TnsDecision( STnsConfig const *pTnsConfig, TRAN_DET_HANDLE hTranDet, const int16_t isTCX10, const float ltp_gain, STnsData *pTnsData );
      64             : 
      65             : 
      66             : /*---------------------------------------------------------------------*
      67             :  * DetectTnsFilt()
      68             :  *
      69             :  *
      70             :  *---------------------------------------------------------------------*/
      71             : 
      72      161953 : int16_t DetectTnsFilt(
      73             :     const STnsConfig *pTnsConfig, /* i  : TNS Configuration struct     */
      74             :     const float pSpectrum[],      /* i  : MDCT spectrum                */
      75             :     TRAN_DET_HANDLE hTranDet,     /* i  : transient detection handle   */
      76             :     const int16_t isTCX10,        /* i  : TCX10 or TCX20?              */
      77             :     const float ltp_gain,         /* i  : LTP gain                     */
      78             :     STnsData *pTnsData,           /* o  : TNS data struct              */
      79             :     float *predictionGain         /* o  : TNS prediction gain          */
      80             : )
      81             : {
      82      161953 :     ResetTnsData( pTnsData );
      83             : 
      84      161953 :     if ( pTnsConfig->maxOrder <= 0 )
      85             :     {
      86           0 :         return 0;
      87             :     }
      88             : 
      89      161953 :     CalculateTnsFilt( pTnsConfig, pSpectrum, pTnsData, predictionGain );
      90             : 
      91      161953 :     TnsDecision( pTnsConfig, hTranDet, isTCX10, ltp_gain, pTnsData );
      92             : 
      93      161953 :     return ( pTnsData->nFilters > 0 ) ? 1 : 0;
      94             : }
      95             : 
      96             : 
      97             : /*---------------------------------------------------------------------*
      98             :  * EncodeTnsData()
      99             :  *
     100             :  *
     101             :  *---------------------------------------------------------------------*/
     102             : 
     103     1454820 : void EncodeTnsData(
     104             :     STnsConfig const *pTnsConfig, /* i  : TNS Configuration struct          */
     105             :     STnsData const *pTnsData,     /* i  : TNS data struct (quantized param) */
     106             :     int16_t *stream,              /* o  : internal data stream              */
     107             :     int16_t *pnSize,              /* o  : number of written parameters      */
     108             :     int16_t *pnBits               /* o  : number of written bits            */
     109             : )
     110             : {
     111     1454820 :     *pnSize = 0;
     112     1454820 :     *pnBits = 0;
     113             : 
     114     1454820 :     if ( pTnsConfig->nMaxFilters > 1 )
     115             :     {
     116     1287771 :         if ( pTnsConfig->allowTnsOnWhite )
     117             :         {
     118     1171879 :             if ( pTnsConfig->iFilterBorders[0] < 512 )
     119             :             {
     120       43066 :                 GetParameters( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     121             :             }
     122             :             else
     123             :             {
     124     1128813 :                 GetParameters( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     125             :             }
     126             :         }
     127             :         else
     128             :         {
     129      115892 :             if ( pTnsConfig->iFilterBorders[0] < 512 )
     130             :             {
     131        4154 :                 GetParameters( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     132             :             }
     133             :             else
     134             :             {
     135      111738 :                 GetParameters( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     136             :             }
     137             :         }
     138             :     }
     139             :     else
     140             :     {
     141      167049 :         GetParameters( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     142             :     }
     143             : 
     144     1454820 :     return;
     145             : }
     146             : 
     147             : 
     148             : /*---------------------------------------------------------------------*
     149             :  * WriteTnsData()
     150             :  *
     151             :  *
     152             :  *---------------------------------------------------------------------*/
     153             : 
     154      812687 : void WriteTnsData(
     155             :     const STnsConfig *pTnsConfig, /* i  : TNS Configuration struct          */
     156             :     const int16_t *stream,        /* i  : internal data stream              */
     157             :     int16_t *pnSize,              /* o  : number of written parameters      */
     158             :     BSTR_ENC_HANDLE hBstr,        /* o  : bitstream                         */
     159             :     int16_t *pnBits               /* o  : number of written bits            */
     160             : )
     161             : {
     162      812687 :     if ( pTnsConfig->nMaxFilters > 1 )
     163             :     {
     164      706375 :         if ( pTnsConfig->allowTnsOnWhite )
     165             :         {
     166      590483 :             if ( pTnsConfig->iFilterBorders[0] < 512 )
     167             :             {
     168       29131 :                 WriteToBitstream( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, &stream, pnSize, hBstr, pnBits );
     169             :             }
     170             :             else
     171             :             {
     172      561352 :                 WriteToBitstream( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
     173             :             }
     174             :         }
     175             :         else
     176             :         {
     177      115892 :             if ( pTnsConfig->iFilterBorders[0] < 512 )
     178             :             {
     179        4154 :                 WriteToBitstream( &tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, hBstr, pnBits );
     180             :             }
     181             :             else
     182             :             {
     183      111738 :                 WriteToBitstream( &tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
     184             :             }
     185             :         }
     186             :     }
     187             :     else
     188             :     {
     189      106312 :         WriteToBitstream( &tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
     190             :     }
     191             : 
     192      812687 :     return;
     193             : }
     194             : 
     195             : 
     196             : /*********************************************************************************************/
     197             : /*  Definitions of functions used in the mapping between TNS parameters and a bitstream.     */
     198             : /*********************************************************************************************/
     199             : 
     200             : /*---------------------------------------------------------------------*
     201             :  * AutoToParcor()
     202             :  *
     203             :  * Autocorrelation to parcor coefficients
     204             :  *---------------------------------------------------------------------*/
     205             : 
     206     2583512 : static float AutoToParcor(
     207             :     const float input[], /* i  : autocorrelation                   */
     208             :     float parCoeff[],    /* o  : parcor coeffs                     */
     209             :     const int16_t order  /* i  : prediction order                  */
     210             : )
     211             : {
     212             :     int16_t i, j;
     213             :     float tmp, tmp2;
     214             :     float workBuffer[2 * TNS_MAX_FILTER_ORDER];
     215     2583512 :     float *const pWorkBuffer = &workBuffer[order]; /* temp pointer */
     216             : 
     217    23251608 :     for ( i = 0; i < order; i++ )
     218             :     {
     219    20668096 :         workBuffer[i] = input[i];
     220    20668096 :         pWorkBuffer[i] = input[i + 1];
     221             :     }
     222             : 
     223    23251608 :     for ( i = 0; i < order; i++ )
     224             :     {
     225    20668096 :         if ( workBuffer[0] < 1.0f / 65536.0f )
     226             :         {
     227           0 :             tmp = 0;
     228             :         }
     229             :         else
     230             :         {
     231    20668096 :             tmp = -pWorkBuffer[i] / workBuffer[0];
     232             :         }
     233             : 
     234             :         /* compensate for calculation inaccuracies limit reflection coefs to ]-1,1[ */
     235    20668096 :         tmp = min( 0.999f, max( -0.999f, tmp ) );
     236             : 
     237    20668096 :         parCoeff[i] = tmp;
     238   113674528 :         for ( j = i; j < order; j++ )
     239             :         {
     240    93006432 :             tmp2 = pWorkBuffer[j] + tmp * workBuffer[j - i];
     241    93006432 :             workBuffer[j - i] += tmp * pWorkBuffer[j];
     242    93006432 :             pWorkBuffer[j] = tmp2;
     243             :         }
     244             :     }
     245             : 
     246     2583512 :     return ( ( input[0] + 1e-30f ) / ( workBuffer[0] + 1e-30f ) );
     247             : }
     248             : 
     249             : 
     250             : /*---------------------------------------------------------------------*
     251             :  * GetFilterParameters()
     252             :  *
     253             :  * Get TNS filter parameters from autocorrelation
     254             :  *---------------------------------------------------------------------*/
     255             : 
     256     2583512 : static void GetFilterParameters(
     257             :     const float rxx[],      /* i  : auto correlation                  */
     258             :     const int16_t maxOrder, /* i  : max. prediction order             */
     259             :     STnsFilter *pTnsFilter  /* i  : TNS filter coeffs                 */
     260             : )
     261             : {
     262             :     int16_t i;
     263             :     float parCoeff[TNS_MAX_FILTER_ORDER];
     264     2583512 :     const float *values = tnsCoeff4;
     265     2583512 :     int16_t *indexes = pTnsFilter->coefIndex;
     266             : 
     267             :     /* Variable initialization */
     268             :     /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
     269     2583512 :     pTnsFilter->predictionGain = AutoToParcor( rxx, parCoeff, maxOrder );
     270             : 
     271             :     /* non-linear quantization of TNS lattice coefficients with given resolution */
     272     2583512 :     Parcor2Index( parCoeff, indexes, maxOrder );
     273             : 
     274             :     /* reduce filter order by truncating trailing zeros */
     275     2583512 :     i = maxOrder - 1;
     276    14348815 :     while ( ( i >= 0 ) && ( indexes[i] == 0 ) )
     277             :     {
     278    11765303 :         --i;
     279             :         /* Loop condition */
     280             :     }
     281     2583512 :     pTnsFilter->order = i + 1;
     282             : 
     283             :     /* compute avg(coef*coef) */
     284     2583512 :     pTnsFilter->avgSqrCoef = 0;
     285    11486305 :     for ( i = pTnsFilter->order - 1; i >= 0; i-- )
     286             :     {
     287     8902793 :         const float value = values[indexes[i] + INDEX_SHIFT];
     288             : 
     289             :         /* Variable initialization */
     290     8902793 :         pTnsFilter->avgSqrCoef += value * value;
     291             :     }
     292     2583512 :     pTnsFilter->avgSqrCoef /= maxOrder;
     293             : 
     294     2583512 :     return;
     295             : }
     296             : 
     297             : 
     298             : /*---------------------------------------------------------------------*
     299             :  * Parcor2Index()
     300             :  *
     301             :  * Quantization for reflection coefficients
     302             :  *---------------------------------------------------------------------*/
     303             : 
     304     2583512 : static void Parcor2Index(
     305             :     const float parCoeff[], /* i  : parcor coefficients               */
     306             :     int16_t index[],        /* o  : quantized parcor coeffs           */
     307             :     const int16_t order     /* i  : order                             */
     308             : )
     309             : {
     310     2583512 :     const int16_t nValues = 1 << TNS_COEF_RES;
     311     2583512 :     const float *values = tnsCoeff4;
     312             :     int16_t i;
     313             :     int16_t iIndex;
     314             :     float x;
     315             : 
     316    23251608 :     for ( i = 0; i < order; i++ )
     317             :     {
     318    20668096 :         iIndex = 1;
     319    20668096 :         x = parCoeff[i];
     320             :         /* Variable initialization */
     321    20668096 :         assert( ( x >= -1.0f ) && ( x <= 1.0f ) );
     322   186656934 :         while ( ( iIndex < nValues ) && ( x > 0.5f * ( values[iIndex - 1] + values[iIndex] ) ) )
     323             :         {
     324   165988838 :             ++iIndex;
     325             :             /* Loop condition */
     326             :         }
     327    20668096 :         index[i] = ( iIndex - 1 ) - INDEX_SHIFT;
     328             :     }
     329             : 
     330     2583512 :     return;
     331             : }
     332             : 
     333             : 
     334             : /*---------------------------------------------------------------------*
     335             :  * CalculateTnsFilt()
     336             :  *
     337             :  *
     338             :  *---------------------------------------------------------------------*/
     339             : 
     340     1454820 : void CalculateTnsFilt(
     341             :     STnsConfig const *pTnsConfig, /* i  : TNS Configuration struct          */
     342             :     const float pSpectrum[],      /* i  : MDCT spectrum                     */
     343             :     STnsData *pTnsData,           /* o  : TNS data struct                   */
     344             :     float *predictionGain         /* o  : TNS prediction gain               */
     345             : )
     346             : {
     347             :     float norms[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
     348             :     int16_t i, iFilter, idx0, idx1, nSubdivisions, iSubdivisions, spectrumLength;
     349             :     int16_t iStartLine, iEndLine, lag;
     350             :     float fac;
     351             :     float rxx[TNS_MAX_FILTER_ORDER + 1];
     352             :     const float *pWindow;
     353             :     STnsFilter *pFilter;
     354             : 
     355     4364460 :     for ( i = 0; i < TNS_MAX_NUM_OF_FILTERS; i++ )
     356             :     {
     357     2909640 :         set_f( norms[i], 0, MAX_SUBDIVISIONS );
     358             :     }
     359             : 
     360             :     /* Calculate norms for each spectrum part */
     361     4197411 :     for ( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     362             :     {
     363     2742591 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     364     2742591 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     365     2742591 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     366             : 
     367             :         /* Variable initialization */
     368     2742591 :         assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
     369    10746888 :         for ( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
     370             :         {
     371     8004297 :             iStartLine = idx0 + ( idx1 - idx0 ) * iSubdivisions / nSubdivisions;
     372     8004297 :             iEndLine = idx0 + ( idx1 - idx0 ) * ( iSubdivisions + 1 ) / nSubdivisions;
     373             : 
     374             :             /* Variable initialization */
     375     8004297 :             norms[iFilter][iSubdivisions] = sum2_f( pSpectrum + iStartLine, iEndLine - iStartLine );
     376             :         }
     377             :     }
     378             : 
     379             :     /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
     380     4197411 :     for ( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     381             :     {
     382     2742591 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     383     2742591 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     384     2742591 :         spectrumLength = idx1 - idx0;
     385     2742591 :         pFilter = pTnsData->filter + iFilter;
     386     2742591 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     387             : 
     388     2742591 :         set_f( rxx, 0, TNS_MAX_FILTER_ORDER + 1 ); /* WMOPS: This initialization is required */
     389             : 
     390             :         /* Variable initialization */
     391    10374737 :         for ( iSubdivisions = 0; ( iSubdivisions < nSubdivisions ) && ( norms[iFilter][iSubdivisions] > HLM_MIN_NRG ); iSubdivisions++ )
     392             :         {
     393     7632146 :             fac = 1.0f / norms[iFilter][iSubdivisions];
     394     7632146 :             iStartLine = idx0 + spectrumLength * iSubdivisions / nSubdivisions;
     395     7632146 :             iEndLine = idx0 + spectrumLength * ( iSubdivisions + 1 ) / nSubdivisions;
     396     7632146 :             pWindow = tnsAcfWindow;
     397             : 
     398             :             /* For additional loop condition */
     399             :             /* Variable initialization */
     400    68689314 :             for ( lag = 1; lag <= pTnsConfig->maxOrder; lag++ )
     401             :             {
     402    61057168 :                 rxx[lag] += fac * ( *pWindow ) * dotp( pSpectrum + iStartLine, pSpectrum + iStartLine + lag, iEndLine - iStartLine - lag );
     403    61057168 :                 pWindow++;
     404             :             }
     405             :         }
     406             : 
     407     2742591 :         if ( iSubdivisions == nSubdivisions ) /* meaning there is no subdivision with low energy */
     408             :         {
     409     2583512 :             rxx[0] = (float) pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     410     2583512 :             pFilter->spectrumLength = spectrumLength;
     411             :             /* Limit the maximum order to spectrum length/4 */
     412     2583512 :             GetFilterParameters( rxx, min( pTnsConfig->maxOrder, pFilter->spectrumLength / 4 ), pFilter );
     413             :         }
     414             :     }
     415             : 
     416     1454820 :     if ( predictionGain )
     417             :     {
     418         371 :         assert( pTnsConfig->nMaxFilters == 1 );
     419         371 :         *predictionGain = pTnsData->filter->predictionGain;
     420             :     }
     421             : 
     422     1454820 :     return;
     423             : }
     424             : 
     425             : 
     426             : /*---------------------------------------------------------------------*
     427             :  * TnsDecision()
     428             :  *
     429             :  *
     430             :  *---------------------------------------------------------------------*/
     431             : 
     432      161953 : static void TnsDecision(
     433             :     STnsConfig const *pTnsConfig, /* i  : TNS Configuration struct          */
     434             :     TRAN_DET_HANDLE hTranDet,     /* i  : transient detection handle        */
     435             :     const int16_t isTCX10,        /* i  : TCX10 or TCX20?                   */
     436             :     const float ltp_gain,         /* i  : LTP gain                          */
     437             :     STnsData *pTnsData            /* i/o: TNDS data structure               */
     438             : )
     439             : {
     440             :     int16_t iFilter;
     441             :     float maxEnergyChange;
     442             :     STnsFilter *pFilter;
     443             :     const struct TnsParameters *pTnsParameters;
     444             : 
     445             :     /* We check the filter's decisions in the opposite direction */
     446      439798 :     for ( iFilter = pTnsConfig->nMaxFilters - 1; iFilter >= 0; iFilter-- )
     447             :     {
     448      277845 :         pFilter = pTnsData->filter + iFilter;
     449      277845 :         pTnsParameters = pTnsConfig->pTnsParameters + iFilter;
     450             : 
     451             :         /* TNS decision function */
     452      277845 :         if ( ( pFilter->predictionGain > pTnsParameters->minPredictionGain ) || ( pFilter->avgSqrCoef > pTnsParameters->minAvgSqrCoef ) )
     453             :         {
     454       20377 :             if ( pTnsData->nFilters > 0 || isTCX10 || ltp_gain < 0.6f || hTranDet == NULL )
     455             :             {
     456       20377 :                 ++pTnsData->nFilters;
     457             :             }
     458             :             else
     459             :             {
     460           0 :                 maxEnergyChange = GetTCXMaxenergyChange( hTranDet, isTCX10, NSUBBLOCKS, 3 );
     461           0 :                 if ( maxEnergyChange >= pTnsParameters->minEnergyChange )
     462             :                 {
     463           0 :                     ++pTnsData->nFilters;
     464             :                 }
     465             :                 else
     466             :                 {
     467           0 :                     ClearTnsFilterCoefficients( pFilter );
     468             :                 }
     469             :             }
     470             :         }
     471      257468 :         else if ( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */
     472             :         {
     473             :             /* Since TNS filter of order 0 is not allowed we haved to signal in the stream filter of order 1 with the 0th coefficient equal to 0 */
     474        5018 :             ClearTnsFilterCoefficients( pFilter );
     475        5018 :             pFilter->order = 1;
     476        5018 :             ++pTnsData->nFilters;
     477             :         }
     478             :         else
     479             :         {
     480      252450 :             ClearTnsFilterCoefficients( pFilter );
     481             :         }
     482             :     }
     483             : 
     484      161953 :     return;
     485             : }

Generated by: LCOV version 1.14