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

Generated by: LCOV version 1.14