LCOV - code coverage report
Current view: top level - lib_enc - tns_base_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ e95243e9e67ddeb69dddf129509de1b3d95b402e Lines: 377 399 94.5 %
Date: 2025-09-14 03:13:15 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : 
       6             : #include "cnst.h"
       7             : #include "stl.h"
       8             : //#include "prot_fx.h"
       9             : #include "basop_util.h"
      10             : #include "stl.h"
      11             : #include <memory.h>
      12             : #include <assert.h>
      13             : #include "rom_com_fx.h"
      14             : #include "rom_com.h"
      15             : #include "prot_fx.h"     /* Function prototypes                    */
      16             : #include "prot_fx_enc.h" /* Function prototypes                    */
      17             : 
      18             : #define HLM_MIN_NRG_FX 858993459 // ( 32768.0f * 2 * NORM_MDCT_FACTOR / ( 640 * 640 ) ) in Q26
      19             : 
      20             : /** Get TNS filter parameters from autocorrelation.
      21             :  *
      22             :  * @param rxx Autocorrelation function/coefficients.
      23             :  * @param maxOrder Maximum filter order/number of coefficients.
      24             :  * @param pTnsFilter Pointer to the output filter.
      25             :  */
      26             : static void GetFilterParameters( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter );
      27             : 
      28             : static void GetFilterParameters_ivas( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter );
      29             : 
      30             : /** Quantization for reflection coefficients.
      31             :  *
      32             :  * @param parCoeff input reflection coefficients.
      33             :  * @param index output quantized values.
      34             :  * @param order number of coefficients/values.
      35             :  */
      36             : static void Parcor2Index( Word16 const parCoeff[], Word16 index[], Word16 order );
      37             : 
      38             : /** Linear prediction analysis/synthesis filter definition.
      39             :  * @param order filter order.
      40             :  * @param parCoeff filter (PARCOR) coefficients.
      41             :  * @param state state of the filter. Must be at least of 'order' size.
      42             :  * @param x the current input value.
      43             :  * @return the output of the filter.
      44             :  */
      45             : typedef Word32 ( *TLinearPredictionFilter )( Word16 order, Word16 const parCoeff[], Word32 *state, Word32 x );
      46             : 
      47             : 
      48             : /********************************/
      49             : /*      Interface functions     */
      50             : /********************************/
      51             : 
      52             : #define MAX_SUBDIVISIONS 3
      53             : 
      54         372 : Word16 DetectTnsFilt_fx( STnsConfig const *pTnsConfig,
      55             :                          Word32 const pSpectrum[],
      56             :                          STnsData *pTnsData,
      57             :                          Word16 *predictionGain )
      58             : {
      59             :     Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
      60             :     Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */
      61             :     Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
      62         372 :     Word16 iFilter = 0;
      63         372 :     move16();
      64             : 
      65         372 :     ResetTnsData( pTnsData );
      66             : 
      67         372 :     IF( pTnsConfig->maxOrder <= 0 )
      68             :     {
      69           0 :         return 0;
      70             :     }
      71             : 
      72             :     /* Calculate norms for each spectrum part */
      73         744 :     FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
      74             :     {
      75             :         Word16 idx0;
      76             :         Word16 idx1;
      77             :         Word16 nSubdivisions;
      78             :         Word16 iSubdivisions;
      79             : #ifndef ISSUE_1867_replace_overflow_libenc
      80             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      81             :         Flag Overflow = 0;
      82             :         move32();
      83             : #endif
      84             : #endif
      85             : 
      86         372 :         move16();
      87         372 :         move16();
      88         372 :         move16();
      89         372 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
      90         372 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
      91         372 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
      92             : 
      93         372 :         assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
      94             : 
      95        1488 :         FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
      96             :         {
      97             :             Word16 iStartLine;
      98             :             Word16 iEndLine;
      99             :             Word16 tmp, headroom, shift;
     100             :             Word32 L_tmp, tmp32;
     101             : 
     102             :             /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
     103             :                iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
     104        1116 :             assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
     105             : 
     106        1116 :             tmp = sub( idx1, idx0 );
     107        1116 :             iStartLine = imult1616( tmp, iSubdivisions );
     108        1116 :             iEndLine = add( iStartLine, tmp );
     109             : 
     110        1116 :             IF( EQ_16( nSubdivisions, 3 ) )
     111             :             {
     112        1116 :                 iStartLine = mult( iStartLine, 0x2AAB );
     113             :             }
     114        1116 :             iStartLine = add( iStartLine, idx0 );
     115             : 
     116        1116 :             IF( EQ_16( nSubdivisions, 3 ) )
     117             :             {
     118        1116 :                 iEndLine = mult( iEndLine, 0x2AAB );
     119             :             }
     120        1116 :             iEndLine = add( iEndLine, idx0 );
     121             : 
     122             :             /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/
     123        1116 :             headroom = getScaleFactor32( &pSpectrum[iStartLine], sub( iEndLine, iStartLine ) );
     124             : 
     125             :             /* Calculate norm of spectrum band */
     126        1116 :             L_tmp = Norm32Norm( pSpectrum + iStartLine, headroom, sub( iEndLine, iStartLine ), &shift );
     127             : 
     128             :             /* Check threshold HLM_MIN_NRG */
     129             :             BASOP_SATURATE_WARNING_OFF_EVS;
     130             : #ifdef ISSUE_1867_replace_overflow_libenc
     131        1116 :             tmp32 = L_sub( L_shl_sat( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ) ), 3277l /*HLM_MIN_NRG Q7*/ );
     132             : #else
     133             :             tmp32 = L_sub( L_shl_o( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ), &Overflow ), 3277l /*HLM_MIN_NRG Q7*/ );
     134             : #endif
     135             :             BASOP_SATURATE_WARNING_ON_EVS;
     136             : 
     137             :             /* get pre-shift for autocorrelation */
     138        1116 :             tmp = sub( shift, norm_l( L_tmp ) ); /* exponent for normalized L_tmp */
     139        1116 :             tmp = shr( sub( 1, tmp ), 1 );       /* pre-shift to apply before autocorrelation */
     140        1116 :             shifts[iFilter][iSubdivisions] = s_min( tmp, headroom );
     141        1116 :             move16();
     142             : 
     143             :             /* calc normalization factor */
     144        1116 :             facs[iFilter][iSubdivisions] = 0;
     145        1116 :             move16();
     146        1116 :             facs_e[iFilter][iSubdivisions] = 0;
     147        1116 :             move16();
     148             : 
     149        1116 :             if ( tmp32 > 0 )
     150             :             {
     151        1116 :                 facs[iFilter][iSubdivisions] = 0x7FFF;
     152        1116 :                 move16(); /* normalization not needed for one subdivision */
     153             :             }
     154             : 
     155        1116 :             test();
     156        1116 :             IF( ( tmp32 > 0 ) && ( GT_16( nSubdivisions, 1 ) ) )
     157             :             {
     158        1116 :                 move16();
     159        1116 :                 facs_e[iFilter][iSubdivisions] = shl( sub( tmp, shifts[iFilter][iSubdivisions] ), 1 );
     160             : 
     161        1116 :                 tmp = sub( 1, shl( tmp, 1 ) );                 /* exponent of autocorrelation */
     162        1116 :                 L_tmp = L_shl_sat( L_tmp, sub( shift, tmp ) ); /* shift L_tmp to that exponent */
     163             : 
     164             :                 /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */
     165        1116 :                 move16();
     166        1116 :                 facs[iFilter][iSubdivisions] = div_s( 0x2000, round_fx_sat( L_tmp ) ); /* L_tmp is >= 0x2000000 */
     167             :             }
     168             :         }
     169             :     }
     170             :     /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
     171         744 :     FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     172             :     {
     173             : #define RXX_E ( 3 )
     174             :         Word32 rxx[TNS_MAX_FILTER_ORDER + 1];
     175             :         Word16 idx0;
     176             :         Word16 idx1;
     177             :         Word16 spectrumLength;
     178             :         STnsFilter *pFilter;
     179             :         Word16 nSubdivisions;
     180             :         Word16 iSubdivisions;
     181             :         Word16 tmpbuf[325];
     182             : 
     183         372 :         set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 );
     184             : 
     185         372 :         move16();
     186         372 :         move16();
     187         372 :         move16();
     188         372 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     189         372 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     190         372 :         spectrumLength = sub( idx1, idx0 );
     191         372 :         pFilter = pTnsData->filter + iFilter;
     192         372 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     193             : 
     194        1488 :         FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
     195             :         {
     196             :             Word16 iStartLine, n, i;
     197             :             Word16 iEndLine;
     198             :             const Word16 *pWindow;
     199             :             Word16 lag, shift;
     200             :             Word32 L_tmp;
     201             : 
     202        1116 :             IF( facs[iFilter][iSubdivisions] == 0 )
     203             :             {
     204           0 :                 BREAK;
     205             :             }
     206             : 
     207             : 
     208             :             /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
     209             :                iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
     210        1116 :             assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
     211             : 
     212        1116 :             iStartLine = imult1616( spectrumLength, iSubdivisions );
     213        1116 :             iEndLine = add( iStartLine, spectrumLength );
     214             : 
     215        1116 :             IF( EQ_16( nSubdivisions, 3 ) )
     216             :             {
     217        1116 :                 iStartLine = mult( iStartLine, 0x2AAB );
     218             :             }
     219        1116 :             iStartLine = add( iStartLine, idx0 );
     220             : 
     221        1116 :             IF( EQ_16( nSubdivisions, 3 ) )
     222             :             {
     223        1116 :                 iEndLine = mult( iEndLine, 0x2AAB );
     224             :             }
     225        1116 :             iEndLine = add( iEndLine, idx0 );
     226             : 
     227             : 
     228        1116 :             move16();
     229        1116 :             shift = shifts[iFilter][iSubdivisions];
     230             : 
     231        1116 :             move16();
     232        1116 :             pWindow = tnsAcfWindow_fx;
     233             : 
     234        1116 :             n = sub( iEndLine, iStartLine );
     235        1116 :             assert( n < (Word16) ( sizeof( tmpbuf ) / sizeof( Word16 ) ) );
     236      233810 :             FOR( i = 0; i < n; i++ )
     237             :             {
     238      232694 :                 tmpbuf[i] = round_fx_sat( L_shl( pSpectrum[iStartLine + i], shift ) );
     239      232694 :                 move16();
     240             :             }
     241             : 
     242       11160 :             FOR( lag = 0; lag <= pTnsConfig->maxOrder; lag++ )
     243             :             {
     244       10044 :                 n = sub( sub( iEndLine, lag ), iStartLine );
     245             : 
     246       10044 :                 L_tmp = L_deposit_l( 0 );
     247     2064114 :                 FOR( i = 0; i < n; i++ )
     248             :                 {
     249     2054070 :                     L_tmp = L_mac0_sat( L_tmp, tmpbuf[i], tmpbuf[i + lag] );
     250             :                 }
     251             : 
     252       10044 :                 IF( lag != 0 )
     253        8928 :                 L_tmp = Mpy_32_16_1( L_tmp, *pWindow++ );
     254             : 
     255       10044 :                 L_tmp = Mpy_32_16_1( L_tmp, facs[iFilter][iSubdivisions] );
     256       10044 :                 L_tmp = L_shl( L_tmp, facs_e[iFilter][iSubdivisions] );
     257             : 
     258       10044 :                 rxx[lag] = L_add( rxx[lag], L_tmp );
     259       10044 :                 move32();
     260             :             }
     261             :         }
     262             : 
     263         372 :         IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */
     264             :         {
     265         372 :             pFilter->spectrumLength = spectrumLength;
     266         372 :             move16();
     267             :             /* Limit the maximum order to spectrum length/4 */
     268         372 :             GetFilterParameters( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter );
     269             :         }
     270             :     }
     271             : 
     272         372 :     if ( predictionGain )
     273             :     {
     274         372 :         assert( pTnsConfig->nMaxFilters == 1 );
     275         372 :         move16();
     276         372 :         *predictionGain = pTnsData->filter->predictionGain;
     277             :     }
     278             : 
     279             :     /* We check the filter's decisions in the opposite direction */
     280         744 :     FOR( iFilter = sub( pTnsConfig->nMaxFilters, 1 ); iFilter >= 0; iFilter-- )
     281             :     {
     282             :         STnsFilter *pFilter;
     283             :         struct TnsParameters const *pTnsParameters;
     284             : 
     285         372 :         move16();
     286         372 :         move16();
     287         372 :         pFilter = pTnsData->filter + iFilter;
     288         372 :         pTnsParameters = pTnsConfig->pTnsParameters + iFilter;
     289             : 
     290         372 :         IF( s_or( (Word16) GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ),
     291             :                   sub( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) > 0 ) )
     292             :         {
     293           4 :             move16();
     294           4 :             pTnsData->nFilters = add( pTnsData->nFilters, 1 );
     295             :         }
     296         368 :         ELSE IF( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */
     297             :         {
     298             :             /* 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 */
     299           0 :             ClearTnsFilterCoefficients( pFilter );
     300           0 :             move16();
     301           0 :             move16();
     302           0 :             pFilter->order = 1;
     303           0 :             pTnsData->nFilters = add( pTnsData->nFilters, 1 );
     304             :         }
     305             :         ELSE
     306             :         {
     307         368 :             ClearTnsFilterCoefficients( pFilter );
     308             :         }
     309             :     }
     310             : 
     311             : 
     312         372 :     return ( pTnsData->nFilters > 0 );
     313             : }
     314             : 
     315     1297542 : void CalculateTnsFilt_fx(
     316             :     STnsConfig const *pTnsConfig, /* i  : TNS Configuration struct          */
     317             :     const Word32 pSpectrum[],     /* i  : MDCT spectrum                     */
     318             :     const Word16 pSpectrum_e,
     319             :     STnsData *pTnsData /* o  : TNS data struct                   */
     320             : )
     321             : {
     322             :     Word32 norms[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
     323             :     Word16 norms_exp[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
     324             :     Word16 i, iFilter, idx0, idx1, nSubdivisions, iSubdivisions, spectrumLength;
     325             :     Word16 iStartLine, iEndLine, lag;
     326             :     Word16 fac, fac_e, exp;
     327             :     Word32 rxx[TNS_MAX_FILTER_ORDER + 1];
     328             :     Word64 W_tmp;
     329             :     const Word16 *pWindow;
     330             :     STnsFilter *pFilter;
     331             : 
     332     3892626 :     FOR( i = 0; i < TNS_MAX_NUM_OF_FILTERS; i++ )
     333             :     {
     334     2595084 :         set32_fx( norms[i], 0, MAX_SUBDIVISIONS );
     335             :     }
     336             : 
     337             :     /* Calculate norms for each spectrum part */
     338     3771649 :     FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     339             :     {
     340     2474107 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     341     2474107 :         move16();
     342     2474107 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     343     2474107 :         move16();
     344     2474107 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     345     2474107 :         move16();
     346             : 
     347             :         /* Variable initialization */
     348     2474107 :         assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
     349     9896428 :         FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
     350             :         {
     351     7422321 :             iStartLine = add( idx0, idiv1616U( i_mult( sub( idx1, idx0 ), iSubdivisions ), nSubdivisions ) );
     352     7422321 :             iEndLine = add( idx0, idiv1616U( i_mult( sub( idx1, idx0 ), add( iSubdivisions, 1 ) ), nSubdivisions ) );
     353             : 
     354             :             /* Variable initialization */
     355     7422321 :             norms_exp[iFilter][iSubdivisions] = pSpectrum_e;
     356     7422321 :             move16();
     357     7422321 :             norms[iFilter][iSubdivisions] = sum2_32_exp_fx( pSpectrum + iStartLine, sub( iEndLine, iStartLine ), &norms_exp[iFilter][iSubdivisions], 8 ); // norms_exp[iFilter][iSubdivisions]
     358     7422321 :             move32();
     359             :         }
     360             :     }
     361             : 
     362             :     /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
     363     3771649 :     FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     364             :     {
     365     2474107 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     366     2474107 :         move16();
     367     2474107 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     368     2474107 :         move16();
     369     2474107 :         spectrumLength = sub( idx1, idx0 );
     370     2474107 :         pFilter = pTnsData->filter + iFilter;
     371     2474107 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     372     2474107 :         move16();
     373             : 
     374     2474107 :         set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 ); /* WMOPS: This initialization is required */
     375             : 
     376             :         /* Variable initialization */
     377     2474107 :         test();
     378     9539460 :         FOR( iSubdivisions = 0; ( iSubdivisions < nSubdivisions ) && ( L_shr_sat( norms[iFilter][iSubdivisions], sub( 6, norms_exp[iFilter][iSubdivisions] ) ) > HLM_MIN_NRG_FX ); iSubdivisions++ )
     379             :         {
     380     7065353 :             test();
     381     7065353 :             fac = BASOP_Util_Divide3232_Scale( 1, norms[iFilter][iSubdivisions], &fac_e );
     382     7065353 :             fac_e = add( sub( Q31, norms_exp[iFilter][iSubdivisions] ), fac_e );
     383     7065353 :             iStartLine = add( idx0, idiv1616U( i_mult( spectrumLength, iSubdivisions ), nSubdivisions ) );
     384     7065353 :             iEndLine = add( idx0, idiv1616U( i_mult( spectrumLength, add( iSubdivisions, 1 ) ), nSubdivisions ) );
     385     7065353 :             pWindow = tnsAcfWindow_fx; // Q15
     386             : 
     387             :             /* For additional loop condition */
     388             :             /* Variable initialization */
     389    63588177 :             FOR( lag = 1; lag <= pTnsConfig->maxOrder; lag++ )
     390             :             {
     391    56522824 :                 W_tmp = 0;
     392    56522824 :                 move64();
     393  6810898796 :                 FOR( i = 0; i < iEndLine - iStartLine - lag; i++ )
     394             :                 {
     395  6754375972 :                     W_tmp = W_mac_32_32( W_tmp, pSpectrum[iStartLine + i], pSpectrum[iStartLine + lag + i] );
     396             :                 }
     397    56522824 :                 exp = W_norm( W_tmp );
     398    56522824 :                 W_tmp = W_shl( W_tmp, exp );
     399    56522824 :                 exp = sub( shl( pSpectrum_e, 1 ), exp );
     400    56522824 :                 W_tmp = W_mult_32_32( L_mult( fac, ( *pWindow ) ), W_extract_h( W_tmp ) );                // exp + fac_e
     401    56522824 :                 rxx[lag] = L_add( rxx[lag], W_extract_h( W_shl( W_tmp, sub( add( fac_e, exp ), 2 ) ) ) ); // Q29
     402    56522824 :                 move32();
     403    56522824 :                 pWindow++;
     404             :             }
     405             :         }
     406             : 
     407     2474107 :         IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */
     408             :         {
     409             :             // To be checked
     410     2326203 :             rxx[0] = L_shl( pTnsConfig->pTnsParameters[iFilter].nSubdivisions, Q29 ); // Q29
     411     2326203 :             move32();
     412     2326203 :             pFilter->spectrumLength = spectrumLength;
     413     2326203 :             move16();
     414             :             /* Limit the maximum order to spectrum length/4 */
     415     2326203 :             GetFilterParameters_ivas( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter );
     416             :         }
     417             :     }
     418             : 
     419     1297542 :     return;
     420             : }
     421             : 
     422      161621 : Word16 DetectTnsFilt_ivas_fx( STnsConfig const *pTnsConfig, /* i  : TNS Configuration struct             */
     423             :                               Word32 const pSpectrum[],     /* i  : MDCT spectrum                           Q=Qx */
     424             :                               STnsData *pTnsData,           /* o  : TNS data struct                                      */
     425             :                               TRAN_DET_HANDLE hTranDet,     /* i  : transient detection handle           */
     426             :                               Word8 isTCX10,                /* i  : TCX10 or TCX20?                                      */
     427             :                               Word16 ltp_gain,              /* i  : LTP gain                                    Q=15 */
     428             :                               Word16 *predictionGain        /* o  : TNS prediction gain                 Q=7      */
     429             : )
     430             : {
     431             :     Word16 facs[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
     432             :     Word16 facs_e[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS]; /* exponents of facs[][] */
     433             :     Word16 shifts[TNS_MAX_NUM_OF_FILTERS][MAX_SUBDIVISIONS];
     434      161621 :     Word16 iFilter = 0;
     435      161621 :     move16();
     436      161621 :     ResetTnsData( pTnsData );
     437             : 
     438      161621 :     IF( pTnsConfig->maxOrder <= 0 )
     439             :     {
     440           0 :         return 0;
     441             :     }
     442             : 
     443             :     /* Calculate norms for each spectrum part */
     444      439084 :     FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     445             :     {
     446             :         Word16 idx0;
     447             :         Word16 idx1;
     448             :         Word16 nSubdivisions;
     449             :         Word16 iSubdivisions;
     450             : #ifndef ISSUE_1867_replace_overflow_libenc
     451             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     452             :         Flag Overflow = 0;
     453             :         move32();
     454             : #endif
     455             : #endif
     456             : 
     457      277463 :         move16();
     458      277463 :         move16();
     459      277463 :         move16();
     460      277463 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     461      277463 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     462      277463 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     463             : 
     464      277463 :         assert( pTnsConfig->pTnsParameters[iFilter].nSubdivisions <= MAX_SUBDIVISIONS );
     465             : 
     466      886404 :         FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
     467             :         {
     468             :             Word16 iStartLine;
     469             :             Word16 iEndLine;
     470             :             Word16 tmp, headroom, shift;
     471             :             Word32 L_tmp, tmp32;
     472             : 
     473             :             /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
     474             :                iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
     475      608941 :             assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
     476             : 
     477      608941 :             tmp = sub( idx1, idx0 );
     478      608941 :             iStartLine = imult1616( tmp, iSubdivisions );
     479      608941 :             iEndLine = add( iStartLine, tmp );
     480             : 
     481      608941 :             IF( EQ_16( nSubdivisions, 3 ) )
     482             :             {
     483      497217 :                 iStartLine = mult( iStartLine, 0x2AAB );
     484             :             }
     485      608941 :             iStartLine = add( iStartLine, idx0 );
     486             : 
     487      608941 :             IF( EQ_16( nSubdivisions, 3 ) )
     488             :             {
     489      497217 :                 iEndLine = mult( iEndLine, 0x2AAB );
     490             :             }
     491      608941 :             iEndLine = add( iEndLine, idx0 );
     492             : 
     493             :             /*norms[iFilter][iSubdivisions] = norm2FLOAT(pSpectrum+iStartLine, iEndLine-iStartLine);*/
     494      608941 :             headroom = getScaleFactor32( &pSpectrum[iStartLine], sub( iEndLine, iStartLine ) );
     495             : 
     496             :             /* Calculate norm of spectrum band */
     497      608941 :             L_tmp = Norm32Norm( pSpectrum + iStartLine, headroom, sub( iEndLine, iStartLine ), &shift );
     498             : 
     499             :             /* Check threshold HLM_MIN_NRG */
     500             :             BASOP_SATURATE_WARNING_OFF_EVS;
     501             : #ifdef ISSUE_1867_replace_overflow_libenc
     502      608941 :             tmp32 = L_sub( L_shl_sat( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ) ), 3277l /*HLM_MIN_NRG Q7*/ );
     503             : #else
     504             :             tmp32 = L_sub( L_shl_o( L_tmp, s_min( 31, sub( shift, 24 - 31 * 2 ) ), &Overflow ), 3277l /*HLM_MIN_NRG Q7*/ );
     505             : #endif
     506             :             BASOP_SATURATE_WARNING_ON_EVS;
     507             : 
     508             :             /* get pre-shift for autocorrelation */
     509      608941 :             tmp = sub( shift, norm_l( L_tmp ) ); /* exponent for normalized L_tmp */
     510      608941 :             tmp = shr( sub( 1, tmp ), 1 );       /* pre-shift to apply before autocorrelation */
     511      608941 :             shifts[iFilter][iSubdivisions] = s_min( tmp, headroom );
     512      608941 :             move16();
     513             : 
     514             :             /* calc normalization factor */
     515      608941 :             facs[iFilter][iSubdivisions] = 0;
     516      608941 :             move16();
     517      608941 :             facs_e[iFilter][iSubdivisions] = 0;
     518      608941 :             move16();
     519             : 
     520      608941 :             if ( tmp32 > 0 )
     521             :             {
     522      608908 :                 facs[iFilter][iSubdivisions] = 0x7FFF;
     523      608908 :                 move16(); /* normalization not needed for one subdivision */
     524             :             }
     525             : 
     526      608941 :             test();
     527      608941 :             IF( ( tmp32 > 0 ) && ( GT_16( nSubdivisions, 1 ) ) )
     528             :             {
     529      497184 :                 move16();
     530      497184 :                 facs_e[iFilter][iSubdivisions] = shl( sub( tmp, shifts[iFilter][iSubdivisions] ), 1 );
     531             : 
     532      497184 :                 tmp = sub( 1, shl( tmp, 1 ) );                 /* exponent of autocorrelation */
     533      497184 :                 L_tmp = L_shl_sat( L_tmp, sub( shift, tmp ) ); /* shift L_tmp to that exponent */
     534             : 
     535             :                 /* calc factor (with 2 bits headroom for sum of 3 subdivisions) */
     536      497184 :                 move16();
     537      497184 :                 facs[iFilter][iSubdivisions] = div_s( 0x2000, round_fx_sat( L_tmp ) ); /* L_tmp is >= 0x2000000 */
     538             :             }
     539             :         }
     540             :     }
     541             :     /* Calculate normalized autocorrelation for spectrum subdivision and get TNS filter parameters based on it */
     542      439084 :     FOR( iFilter = 0; iFilter < pTnsConfig->nMaxFilters; iFilter++ )
     543             :     {
     544             : #define RXX_E ( 3 )
     545             :         Word32 rxx[TNS_MAX_FILTER_ORDER + 1];
     546             :         Word16 idx0;
     547             :         Word16 idx1;
     548             :         Word16 spectrumLength;
     549             :         STnsFilter *pFilter;
     550             :         Word16 nSubdivisions;
     551             :         Word16 iSubdivisions;
     552             :         Word16 tmpbuf[325];
     553             : 
     554      277463 :         set32_fx( rxx, 0, TNS_MAX_FILTER_ORDER + 1 );
     555             : 
     556      277463 :         move16();
     557      277463 :         move16();
     558      277463 :         move16();
     559      277463 :         idx0 = pTnsConfig->iFilterBorders[iFilter + 1];
     560      277463 :         idx1 = pTnsConfig->iFilterBorders[iFilter];
     561      277463 :         spectrumLength = sub( idx1, idx0 );
     562      277463 :         pFilter = pTnsData->filter + iFilter;
     563      277463 :         nSubdivisions = pTnsConfig->pTnsParameters[iFilter].nSubdivisions;
     564             : 
     565      886371 :         FOR( iSubdivisions = 0; iSubdivisions < nSubdivisions; iSubdivisions++ )
     566             :         {
     567             :             Word16 iStartLine, n, i;
     568             :             Word16 iEndLine;
     569             :             const Word16 *pWindow;
     570             :             Word16 lag, shift;
     571             :             Word32 L_tmp;
     572             : 
     573      608919 :             IF( facs[iFilter][iSubdivisions] == 0 )
     574             :             {
     575          11 :                 BREAK;
     576             :             }
     577             : 
     578             : 
     579             :             /* iStartLine = idx0 + (idx1-idx0)*iSubdivisions/nSubdivisions;
     580             :                iEndLine = idx0 + (idx1-idx0)*(iSubdivisions+1)/nSubdivisions; */
     581      608908 :             assert( ( nSubdivisions == 1 ) || ( nSubdivisions == 3 ) );
     582             : 
     583      608908 :             iStartLine = imult1616( spectrumLength, iSubdivisions );
     584      608908 :             iEndLine = add( iStartLine, spectrumLength );
     585             : 
     586      608908 :             IF( EQ_16( nSubdivisions, 3 ) )
     587             :             {
     588      497184 :                 iStartLine = mult( iStartLine, 0x2AAB );
     589             :             }
     590      608908 :             iStartLine = add( iStartLine, idx0 );
     591             : 
     592      608908 :             IF( EQ_16( nSubdivisions, 3 ) )
     593             :             {
     594      497184 :                 iEndLine = mult( iEndLine, 0x2AAB );
     595             :             }
     596      608908 :             iEndLine = add( iEndLine, idx0 );
     597             : 
     598             : 
     599      608908 :             move16();
     600      608908 :             shift = shifts[iFilter][iSubdivisions];
     601             : 
     602      608908 :             move16();
     603      608908 :             pWindow = tnsAcfWindow_fx;
     604             : 
     605      608908 :             n = sub( iEndLine, iStartLine );
     606      608908 :             assert( n <= (Word16) ( sizeof( tmpbuf ) / sizeof( Word16 ) ) );
     607   121783112 :             FOR( i = 0; i < n; i++ )
     608             :             {
     609   121174204 :                 tmpbuf[i] = round_fx_sat( L_shl( pSpectrum[iStartLine + i], shift ) ); // using round_fx_sat to address corner case
     610   121174204 :                 move16();
     611             :             }
     612             : 
     613     6089080 :             FOR( lag = 0; lag <= pTnsConfig->maxOrder; lag++ )
     614             :             {
     615     5480172 :                 n = sub( sub( iEndLine, lag ), iStartLine );
     616             : 
     617     5480172 :                 L_tmp = L_deposit_l( 0 );
     618  1074127320 :                 FOR( i = 0; i < n; i++ )
     619             :                 {
     620  1068647148 :                     L_tmp = L_mac0_sat( L_tmp, tmpbuf[i], tmpbuf[i + lag] );
     621             :                 }
     622             : 
     623     5480172 :                 IF( lag != 0 )
     624             :                 {
     625     4871264 :                     L_tmp = Mpy_32_16_1( L_tmp, *pWindow++ );
     626             :                 }
     627             : 
     628     5480172 :                 L_tmp = Mpy_32_16_1( L_tmp, facs[iFilter][iSubdivisions] );
     629     5480172 :                 L_tmp = L_shl( L_tmp, facs_e[iFilter][iSubdivisions] );
     630             : 
     631     5480172 :                 rxx[lag] = L_add( rxx[lag], L_tmp );
     632     5480172 :                 move32();
     633             :             }
     634             :         }
     635             : 
     636      277463 :         IF( EQ_16( iSubdivisions, nSubdivisions ) ) /* meaning there is no subdivision with low energy */
     637             :         {
     638      277452 :             pFilter->spectrumLength = spectrumLength;
     639      277452 :             move16();
     640             :             /* Limit the maximum order to spectrum length/4 */
     641      277452 :             GetFilterParameters( rxx, s_min( pTnsConfig->maxOrder, shr( pFilter->spectrumLength, 2 ) ), pFilter );
     642             :         }
     643             :     }
     644             : 
     645      161621 :     IF( predictionGain )
     646             :     {
     647           0 :         assert( pTnsConfig->nMaxFilters == 1 );
     648           0 :         move16();
     649           0 :         *predictionGain = pTnsData->filter->predictionGain;
     650             :     }
     651             : 
     652             :     /* We check the filter's decisions in the opposite direction */
     653      439084 :     FOR( iFilter = ( pTnsConfig->nMaxFilters - 1 ); iFilter >= 0; iFilter-- )
     654             :     {
     655             :         STnsFilter *pFilter;
     656             :         struct TnsParameters const *pTnsParameters;
     657             :         Word16 maxEnergyChange;
     658      277463 :         move16();
     659      277463 :         move16();
     660      277463 :         pFilter = pTnsData->filter + iFilter;
     661      277463 :         pTnsParameters = pTnsConfig->pTnsParameters + iFilter;
     662             : 
     663      277463 :         IF( s_or( (Word16) GT_16( pFilter->predictionGain, pTnsParameters->minPredictionGain ),
     664             :                   sub( pFilter->avgSqrCoef, pTnsParameters->minAvgSqrCoef ) > 0 ) )
     665             :         {
     666             :             // pTnsData->nFilters > 0 || isTCX10 || ltp_gain < 0.6f || hTranDet == NULL
     667             :             // .6f = 19660, Q=15
     668       20521 :             test();
     669       20521 :             test();
     670       20521 :             test();
     671       20521 :             IF( pTnsData->nFilters > 0 || isTCX10 || LT_16( ltp_gain, 19660 ) || hTranDet == NULL )
     672             :             {
     673       20521 :                 pTnsData->nFilters = add( pTnsData->nFilters, 1 );
     674       20521 :                 move16();
     675             :             }
     676             :             ELSE
     677             :             {
     678           0 :                 maxEnergyChange = GetTCXMaxenergyChange_ivas_fx( hTranDet, isTCX10, NSUBBLOCKS, 3 );
     679           0 :                 IF( sub( maxEnergyChange, shl( pTnsParameters->minEnergyChange, Q3 - Q7 ) ) >= 0 )
     680             :                 {
     681             : 
     682           0 :                     pTnsData->nFilters = add( pTnsData->nFilters, 1 );
     683           0 :                     move16();
     684             :                 }
     685             :                 ELSE
     686             :                 {
     687           0 :                     ClearTnsFilterCoefficients( pFilter );
     688             :                 }
     689             :             }
     690             :         }
     691      256942 :         ELSE IF( pTnsData->nFilters > 0 ) /* If a previous filter is turned on */
     692             :         {
     693             :             /* 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 */
     694        4828 :             ClearTnsFilterCoefficients( pFilter );
     695        4828 :             move16();
     696        4828 :             move16();
     697        4828 :             pFilter->order = 1;
     698        4828 :             pTnsData->nFilters = add( pTnsData->nFilters, 1 );
     699             :         }
     700             :         ELSE
     701             :         {
     702      252114 :             ClearTnsFilterCoefficients( pFilter );
     703             :         }
     704             :     }
     705             : 
     706      161621 :     return ( pTnsData->nFilters > 0 );
     707             : }
     708             : 
     709      161993 : Word16 EncodeTnsData_fx( STnsConfig const *pTnsConfig, STnsData const *pTnsData, Word16 *stream, Word16 *pnSize, Word16 *pnBits )
     710             : {
     711             : 
     712      161993 :     move16();
     713      161993 :     move16();
     714      161993 :     *pnSize = 0;
     715      161993 :     *pnBits = 0;
     716             : 
     717      161993 :     IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
     718             :     {
     719             : 
     720      115842 :         IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
     721             :         {
     722        4118 :             GetParameters( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     723             :         }
     724             :         ELSE
     725             :         {
     726      111724 :             GetParameters( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     727             :         }
     728             :     }
     729             :     ELSE
     730             :     {
     731       46151 :         GetParameters( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     732             :     }
     733             : 
     734      161993 :     return TNS_NO_ERROR;
     735             : }
     736             : 
     737     1297542 : void EncodeTnsData_ivas_fx(
     738             :     STnsConfig const *pTnsConfig, /* i  : TNS Configuration struct          */
     739             :     STnsData const *pTnsData,     /* i  : TNS data struct (quantized param) */
     740             :     Word16 *stream,               /* o  : internal data stream              Q0*/
     741             :     Word16 *pnSize,               /* o  : number of written parameters      Q0*/
     742             :     Word16 *pnBits                /* o  : number of written bits            Q0*/
     743             : )
     744             : {
     745     1297542 :     *pnSize = 0;
     746     1297542 :     move16();
     747     1297542 :     move16();
     748     1297542 :     *pnBits = 0;
     749             : 
     750     1297542 :     IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
     751             :     {
     752     1176565 :         IF( pTnsConfig->allowTnsOnWhite )
     753             :         {
     754     1176565 :             IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
     755             :             {
     756       42973 :                 GetParameters_fx( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     757             :             }
     758             :             ELSE
     759             :             {
     760     1133592 :                 GetParameters_fx( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     761             :             }
     762             :         }
     763             :         ELSE
     764             :         {
     765           0 :             IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
     766             :             {
     767           0 :                 GetParameters_fx( &tnsEnabledSWBTCX10BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     768             :             }
     769             :             ELSE
     770             :             {
     771           0 :                 GetParameters_fx( &tnsEnabledSWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     772             :             }
     773             :         }
     774             :     }
     775             :     ELSE
     776             :     {
     777      120977 :         GetParameters_fx( &tnsEnabledWBTCX20BitMap, 1, pTnsData, &stream, pnSize, pnBits );
     778             :     }
     779             : 
     780     1297542 :     return;
     781             : }
     782             : 
     783         372 : Word16 WriteTnsData_fx( STnsConfig const *pTnsConfig, Word16 const *stream, Word16 *pnSize, Encoder_State *st, Word16 *pnBits )
     784             : {
     785             : 
     786         372 :     IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
     787             :     {
     788             : 
     789           0 :         IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
     790             :         {
     791           0 :             WriteToBitstream_fx( &tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, st->hBstr, pnBits );
     792             :         }
     793             :         ELSE
     794             :         {
     795           0 :             WriteToBitstream_fx( &tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, st->hBstr, pnBits );
     796             :         }
     797             :     }
     798             :     ELSE
     799             :     {
     800         372 :         WriteToBitstream_fx( &tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, st->hBstr, pnBits );
     801             :     }
     802             : 
     803             : 
     804         372 :     return TNS_NO_ERROR;
     805             : }
     806      814662 : Word16 WriteTnsData_ivas_fx( STnsConfig const *pTnsConfig, Word16 const *stream, Word16 *pnSize, BSTR_ENC_HANDLE hBstr, Word16 *pnBits )
     807             : {
     808      814662 :     IF( GT_16( pTnsConfig->nMaxFilters, 1 ) )
     809             :     {
     810      708631 :         IF( pTnsConfig->allowTnsOnWhite )
     811             :         {
     812      592789 :             IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
     813             :             {
     814       29092 :                 WriteToBitstream_ivas_fx( &tnsEnabledOnWhiteSWBTCX10BitMap, 1, &stream, pnSize, hBstr, pnBits );
     815             :             }
     816             :             ELSE
     817             :             {
     818      563697 :                 WriteToBitstream_ivas_fx( &tnsEnabledOnWhiteSWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
     819             :             }
     820             :         }
     821             :         ELSE
     822             :         {
     823      115842 :             IF( LT_16( pTnsConfig->iFilterBorders[0], 512 ) )
     824             :             {
     825        4118 :                 WriteToBitstream_ivas_fx( &tnsEnabledSWBTCX10BitMap, 1, &stream, pnSize, hBstr, pnBits );
     826             :             }
     827             :             ELSE
     828             :             {
     829      111724 :                 WriteToBitstream_ivas_fx( &tnsEnabledSWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
     830             :             }
     831             :         }
     832             :     }
     833             :     ELSE
     834             :     {
     835      106031 :         WriteToBitstream_ivas_fx( &tnsEnabledWBTCX20BitMap, 1, &stream, pnSize, hBstr, pnBits );
     836             :     }
     837             : 
     838      814662 :     return TNS_NO_ERROR;
     839             : }
     840             : /*********************************************************************************************/
     841             : /*  Definitions of functions used in the mapping between TNS parameters and a bitstream.     */
     842             : /*********************************************************************************************/
     843             : 
     844             : /* Helper functions for Hufmann table coding */
     845             : 
     846             : /********************************/
     847             : /*      Private functions       */
     848             : /********************************/
     849     2326203 : static void GetFilterParameters_ivas( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter )
     850             : {
     851             :     Word16 i;
     852             :     Word16 parCoeff[TNS_MAX_FILTER_ORDER + 1];
     853             :     Word32 rxx_0;
     854             :     Word32 L_tmp;
     855             : #if TNS_COEF_RES == 5
     856             :     Word16 const *values = tnsCoeff5;
     857             : #elif TNS_COEF_RES == 4
     858     2326203 :     Word16 const *values = tnsCoeff4;
     859             : #elif TNS_COEF_RES == 3
     860             :     Word16 const *values = tnsCoeff3;
     861             : #endif
     862     2326203 :     Word16 *indexes = pTnsFilter->coefIndex;
     863             : 
     864     2326203 :     rxx_0 = rxx[0];
     865     2326203 :     move32();
     866             :     /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
     867     2326203 :     L_tmp = E_LPC_schur_ivas( rxx, parCoeff, maxOrder );
     868             :     BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, this value is compared against a threshold. */
     869     2326203 :         Word16 temp_e = 0;
     870     2326203 :     move16();
     871     2326203 :     Word16 temp = BASOP_Util_Divide3232_Scale( rxx_0, L_tmp, &temp_e );
     872     2326203 :     pTnsFilter->predictionGain32 = L_deposit_h( temp );
     873     2326203 :     move32();
     874     2326203 :     pTnsFilter->predictionGain_e = temp_e;
     875     2326203 :     move16();
     876     2326203 :     pTnsFilter->predictionGain = shl_sat( temp, sub( temp_e, PRED_GAIN_E ) ); // Q7
     877     2326203 :     move16();
     878             :     BASOP_SATURATE_WARNING_ON_EVS
     879             :     /* non-linear quantization of TNS lattice coefficients with given resolution */
     880     2326203 :     Parcor2Index( parCoeff, indexes, maxOrder );
     881             : 
     882             :     /* reduce filter order by truncating trailing zeros */
     883     2326203 :     i = sub( maxOrder, 1 );
     884             : 
     885     2326203 :     test();
     886    12988778 :     WHILE( ( i >= 0 ) && ( indexes[i] == 0 ) )
     887             :     {
     888    10662575 :         i = sub( i, 1 );
     889             :     }
     890             : 
     891             : 
     892     2326203 :     pTnsFilter->order = add( i, 1 );
     893     2326203 :     move16();
     894             : 
     895             :     /* compute avg(coef*coef) */
     896     2326203 :     L_tmp = L_deposit_l( 0 );
     897             : 
     898    10273252 :     FOR( i = pTnsFilter->order - 1; i >= 0; i-- )
     899             :     {
     900             :         Word16 value;
     901             : 
     902     7947049 :         value = shr( values[indexes[i] + INDEX_SHIFT], 1 );
     903             : 
     904     7947049 :         L_tmp = L_mac0( L_tmp, value, value );
     905             :     }
     906             : 
     907     2326203 :     pTnsFilter->avgSqrCoef = round_fx( L_tmp );
     908     2326203 :     move16();
     909             :     /* assert(maxOrder == 8);
     910             :      pTnsFilter->avgSqrCoef = shr(pTnsFilter->avgSqrCoef, 3); */
     911     2326203 : }
     912      277824 : static void GetFilterParameters( Word32 rxx[], Word16 maxOrder, STnsFilter *pTnsFilter )
     913             : {
     914             :     Word16 i;
     915             :     Word16 parCoeff[TNS_MAX_FILTER_ORDER];
     916             :     Word32 epsP[TNS_MAX_FILTER_ORDER + 1], L_tmp;
     917             : #if TNS_COEF_RES == 5
     918             :     Word16 const *values = tnsCoeff5;
     919             : #elif TNS_COEF_RES == 4
     920      277824 :     Word16 const *values = tnsCoeff4;
     921             : #elif TNS_COEF_RES == 3
     922             :     Word16 const *values = tnsCoeff3;
     923             : #endif
     924      277824 :     Word16 *indexes = pTnsFilter->coefIndex;
     925             : 
     926             : 
     927             :     /* compute TNS filter in lattice (ParCor) form with LeRoux-Gueguen algorithm */
     928      277824 :     L_tmp = E_LPC_schur( rxx, parCoeff, epsP, maxOrder );
     929             :     BASOP_SATURATE_WARNING_OFF_EVS /* Allow saturation, this value is compared against a threshold. */
     930      277824 :         pTnsFilter->predictionGain = divide3232( L_shr( epsP[0], PRED_GAIN_E ), L_tmp );
     931             :     BASOP_SATURATE_WARNING_ON_EVS
     932             :     /* non-linear quantization of TNS lattice coefficients with given resolution */
     933      277824 :     Parcor2Index( parCoeff, indexes, maxOrder );
     934             : 
     935             :     /* reduce filter order by truncating trailing zeros */
     936      277824 :     i = sub( maxOrder, 1 );
     937             : 
     938      277824 :     test();
     939     1490290 :     WHILE( ( i >= 0 ) && ( indexes[i] == 0 ) )
     940             :     {
     941     1212466 :         test();
     942     1212466 :         i = sub( i, 1 );
     943             :     }
     944             : 
     945      277824 :     move16();
     946      277824 :     pTnsFilter->order = add( i, 1 );
     947             : 
     948             :     /* compute avg(coef*coef) */
     949      277824 :     L_tmp = L_deposit_l( 0 );
     950             : 
     951     1287950 :     FOR( i = pTnsFilter->order - 1; i >= 0; i-- )
     952             :     {
     953             :         Word16 value;
     954             : 
     955     1010126 :         value = shr( values[indexes[i] + INDEX_SHIFT], 1 );
     956             : 
     957     1010126 :         L_tmp = L_mac0( L_tmp, value, value );
     958             :     }
     959      277824 :     move16();
     960      277824 :     pTnsFilter->avgSqrCoef = round_fx( L_tmp );
     961             : 
     962             :     /* assert(maxOrder == 8);
     963             :      pTnsFilter->avgSqrCoef = shr(pTnsFilter->avgSqrCoef, 3); */
     964      277824 : }
     965             : 
     966     2604027 : static void Parcor2Index( const Word16 parCoeff[] /*Q15*/, Word16 index[], Word16 order )
     967             : {
     968             :     Word16 nValues;
     969             :     Word16 const *values;
     970             :     Word16 i;
     971             :     Word16 iIndex;
     972             :     Word16 x;
     973             : 
     974             : 
     975     2604027 :     move16();
     976     2604027 :     nValues = 1 << TNS_COEF_RES;
     977             : #if TNS_COEF_RES == 5
     978             :     values = tnsCoeff5;
     979             : #elif TNS_COEF_RES == 4
     980     2604027 :     values = tnsCoeff4;
     981             : #elif TNS_COEF_RES == 3
     982             :     values = tnsCoeff3;
     983             : #endif
     984             : 
     985    23436243 :     FOR( i = 0; i < order; i++ )
     986             :     {
     987    20832216 :         move16();
     988    20832216 :         move16();
     989    20832216 :         iIndex = 1;
     990    20832216 :         x = parCoeff[i];
     991             : 
     992             :         /* parCoeff is in the range of -1.0 ... 1.0 by definition */
     993             :         /* assert((x >= FL2WORD16(-1.0f)) && (x <= FL2WORD16(1.0f))); */
     994             : 
     995    20832216 :         test();
     996   188137347 :         WHILE( ( iIndex < nValues ) && ( x > add( shr( values[iIndex - 1], 1 ), shr( values[iIndex], 1 ) ) ) )
     997             :         {
     998   167305131 :             test();
     999   167305131 :             iIndex = add( iIndex, 1 );
    1000             :         }
    1001    20832216 :         index[i] = sub( iIndex, 1 + INDEX_SHIFT );
    1002    20832216 :         move16();
    1003             :     }
    1004     2604027 : }

Generated by: LCOV version 1.14