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

Generated by: LCOV version 1.14