LCOV - code coverage report
Current view: top level - lib_enc - tcx_ltp_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 574a190e3c6896c6c4ed10d7f23649709a0c4347 Lines: 632 661 95.6 %
Date: 2025-06-27 02:59:36 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <assert.h>
       6             : #include "options.h"
       7             : //#include "prot_fx.h"
       8             : #include "stl.h"
       9             : #include "cnst.h"
      10             : #include "basop_util.h"
      11             : #include "rom_com_fx.h"
      12             : #include "rom_com.h"
      13             : #include "prot_fx.h"     /* Function prototypes                    */
      14             : #include "prot_fx_enc.h" /* Function prototypes                    */
      15             : 
      16    26133256 : static Word32 dot( const Word16 *X, const Word16 *Y, Word16 n )
      17             : {
      18             :     Word32 acc;
      19             :     Word16 i;
      20             : 
      21             :     Word64 acc_64;
      22    26133256 :     acc_64 = 0;
      23    26133256 :     move64();
      24  7557591048 :     FOR( i = 0; i < n; i++ )
      25             :     {
      26  7531457792 :         acc_64 = W_mac0_16_16( acc_64, X[i], Y[i] );
      27             :     }
      28    26133256 :     acc = W_sat_l( acc_64 );
      29             : 
      30    26133256 :     return acc;
      31             : }
      32             : 
      33     5161747 : static Word32 interpolate_corr(                       /* o  : interpolated value   */
      34             :                                 const Word32 *x,      /* i  : input vector         */
      35             :                                 const Word16 frac,    /* i  : fraction of lag      */
      36             :                                 const Word16 frac_max /* i  : max fraction         */
      37             : )
      38             : {
      39             :     Word32 s;
      40             :     const Word16 *c, *win;
      41             : 
      42             : 
      43     5161747 :     win = E_ROM_inter4_1_fx;
      44     5161747 :     if ( EQ_16( frac_max, 6 ) )
      45      286725 :         win = E_ROM_inter6_1_fx;
      46             : 
      47             : 
      48     5161747 :     s = L_deposit_l( 0 );
      49             : 
      50     5161747 :     c = &win[frac];
      51     5161747 :     s = L_add( s, Mpy_32_16_1( x[0], *c ) );
      52     5161747 :     c += frac_max;
      53     5161747 :     s = L_add( s, Mpy_32_16_1( x[-1], *c ) );
      54     5161747 :     c += frac_max;
      55     5161747 :     s = L_add( s, Mpy_32_16_1( x[-2], *c ) );
      56     5161747 :     c += frac_max;
      57     5161747 :     s = L_add( s, Mpy_32_16_1( x[-3], *c ) );
      58             : 
      59     5161747 :     c = &win[frac_max - frac];
      60     5161747 :     s = L_add( s, Mpy_32_16_1( x[1], *c ) );
      61     5161747 :     c += frac_max;
      62     5161747 :     s = L_add( s, Mpy_32_16_1( x[2], *c ) );
      63     5161747 :     c += frac_max;
      64     5161747 :     s = L_add( s, Mpy_32_16_1( x[3], *c ) );
      65     5161747 :     c += frac_max;
      66     5161747 :     s = L_add( s, Mpy_32_16_1( x[4], *c ) );
      67             : 
      68             : 
      69     5161747 :     return s;
      70             : }
      71             : 
      72        1311 : static void tcx_ltp_pitch_search(
      73             :     Word16 pitch_ol,
      74             :     Word16 *pitch_int,
      75             :     Word16 *pitch_fr,
      76             :     Word16 *index,
      77             :     Word16 *norm_corr,
      78             :     const Word16 len,
      79             :     Word16 *wsp,
      80             :     Word16 pitmin,
      81             :     Word16 pitfr1,
      82             :     Word16 pitfr2,
      83             :     Word16 pitmax,
      84             :     Word16 pitres )
      85             : {
      86             :     Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp;
      87             :     Word32 cor_max, cor[256], *pt_cor, temp;
      88             :     Word16 wsp2[L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1];
      89             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      90        1311 :     Flag Overflow = 0;
      91        1311 :     move32();
      92             : #endif
      93             : 
      94             : 
      95        1311 :     delta = 16;
      96        1311 :     move16();
      97        1311 :     if ( EQ_16( pitres, 6 ) )
      98             :     {
      99        1050 :         delta = 8;
     100        1050 :         move16();
     101             :     }
     102             : 
     103        1311 :     t0_min = sub( pitch_ol, shr( delta, 1 ) );
     104        1311 :     t0_max = sub( add( t0_min, delta ), 1 );
     105             : 
     106        1311 :     IF( LT_16( t0_min, pitmin ) )
     107             :     {
     108          42 :         t0_min = pitmin;
     109          42 :         move16();
     110          42 :         t0_max = sub( add( t0_min, delta ), 1 );
     111             :     }
     112             : 
     113        1311 :     IF( GT_16( t0_max, pitmax ) )
     114             :     {
     115          18 :         t0_max = pitmax;
     116          18 :         move16();
     117          18 :         t0_min = add( sub( t0_max, delta ), 1 );
     118             :     }
     119             : 
     120        1311 :     t_min = sub( t0_min, L_INTERPOL1 );
     121        1311 :     t_max = add( t0_max, L_INTERPOL1 );
     122             : 
     123             :     /* normalize wsp */
     124        1311 :     assert( len + t_max <= L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1 );
     125        1311 :     s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) );
     126        1311 :     s_wsp = sub( s_wsp, 4 );
     127      541543 :     FOR( t = negate( t_max ); t < len; t++ )
     128             :     {
     129      540232 :         wsp2[t + t_max] = shl( wsp[t], s_wsp );
     130      540232 :         move16();
     131             :     }
     132        1311 :     wsp = wsp2 + t_max;
     133        1311 :     move16();
     134             : 
     135        1311 :     pt_cor = cor;
     136        1311 :     move32();
     137             : 
     138       24375 :     FOR( t = t_min; t <= t_max; t++ )
     139             :     {
     140       23064 :         *pt_cor = dot( wsp, wsp - t, len );
     141       23064 :         move32();
     142       23064 :         pt_cor++;
     143             :     }
     144             : 
     145        1311 :     pt_cor = cor + L_INTERPOL1;
     146        1311 :     cor_max = L_add( *pt_cor++, 0 );
     147        1311 :     t1 = t0_min;
     148        1311 :     move16();
     149        1311 :     move32();
     150             : 
     151       12576 :     FOR( t = t0_min + 1; t <= t0_max; t++ )
     152             :     {
     153       11265 :         IF( GT_32( *pt_cor, cor_max ) )
     154             :         {
     155        4932 :             cor_max = *pt_cor;
     156        4932 :             move32();
     157        4932 :             t1 = t;
     158        4932 :             move16();
     159             :         }
     160       11265 :         pt_cor++;
     161             :     }
     162             : 
     163        1311 :     temp = dot( wsp, wsp, len );
     164        1311 :     s = norm_l( temp );
     165        1311 :     temp_m = extract_h( L_shl( temp, s ) );
     166        1311 :     temp_e = negate( s );
     167             : 
     168        1311 :     temp = dot( wsp - t1, wsp - t1, len );
     169        1311 :     s = norm_l( temp );
     170        1311 :     temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) );
     171        1311 :     temp_e = sub( temp_e, s );
     172             : 
     173        1311 :     temp_m = Sqrt16( temp_m, &temp_e );
     174             : 
     175        1311 :     if ( temp_m == 0 )
     176             :     {
     177           0 :         temp_m = 1;
     178           0 :         move16();
     179             :     }
     180        1311 :     s = sub( norm_l( cor_max ), 1 );
     181        1311 :     temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m );
     182        1311 :     temp_e = sub( negate( s ), temp_e );
     183             : 
     184        1311 :     *norm_corr = shl_o( temp_m, temp_e, &Overflow );
     185             : 
     186        1311 :     IF( GE_16( t1, pitfr1 ) )
     187             :     {
     188         192 :         *pitch_int = t1;
     189         192 :         move16();
     190         192 :         *pitch_fr = 0;
     191         192 :         move16();
     192             : 
     193         192 :         *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ),
     194         192 :                                                             sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) );
     195         192 :         move16();
     196             : 
     197         192 :         return;
     198             :     }
     199             : 
     200             :     /*------------------------------------------------------------------*
     201             :      * Search fractional pitch with 1/4 subsample resolution.
     202             :      * search the fractions around t0 and choose the one which maximizes
     203             :      * the interpolated normalized correlation.
     204             :      *-----------------------------------------------------------------*/
     205             : 
     206        1119 :     pt_cor = cor + sub( L_INTERPOL1, t0_min );
     207        1119 :     t0 = t1;
     208        1119 :     move16();
     209             : 
     210        1119 :     step = 1;
     211        1119 :     move16();
     212        1119 :     if ( GE_16( t0, pitfr2 ) )
     213             :     {
     214         892 :         step = 2;
     215         892 :         move16();
     216             :     }
     217        1119 :     fraction = step;
     218        1119 :     move16();
     219             : 
     220        1119 :     IF( EQ_16( t0, t0_min ) ) /* Limit case */
     221             :     {
     222         118 :         fraction = 0;
     223         118 :         move16();
     224         118 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     225             :     }
     226             :     ELSE /* Process negative fractions */
     227             :     {
     228        1001 :         t0 = sub( t0, 1 );
     229        1001 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     230             : 
     231        2198 :         FOR( i = fraction + step; i < pitres; i += step )
     232             :         {
     233        1197 :             temp = interpolate_corr( &pt_cor[t0], i, pitres );
     234             : 
     235        1197 :             IF( GT_32( temp, cor_max ) )
     236             :             {
     237        1164 :                 cor_max = L_add( temp, 0 );
     238        1164 :                 fraction = i;
     239        1164 :                 move16();
     240             :             }
     241             :         }
     242             :     }
     243             : 
     244        1119 :     i = 0;
     245        1119 :     move16();
     246        4689 :     FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */
     247             :     {
     248        3570 :         temp = interpolate_corr( &pt_cor[t1], i, pitres );
     249             : 
     250        3570 :         IF( GT_32( temp, cor_max ) )
     251             :         {
     252        1090 :             cor_max = L_add( temp, 0 );
     253        1090 :             fraction = i;
     254        1090 :             move16();
     255        1090 :             t0 = t1;
     256        1090 :             move16();
     257             :         }
     258             :     }
     259             : 
     260        1119 :     *pitch_int = t0;
     261        1119 :     move16();
     262        1119 :     *pitch_fr = fraction;
     263        1119 :     move16();
     264             : 
     265        1119 :     IF( GE_16( t0, pitfr2 ) )
     266             :     {
     267         892 :         *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ),
     268         892 :                                          sub( pitfr2, pitmin ), pitres ) ),
     269         892 :                       shr( fraction, 1 ) );
     270         892 :         move16();
     271             :     }
     272             :     ELSE
     273             :     {
     274         227 :         *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction );
     275         227 :         move16();
     276             :     }
     277             : }
     278             : 
     279     1044982 : static void tcx_ltp_pitch_search_ivas_fx(
     280             :     const Word16 pitch_ol,
     281             :     Word16 *pitch_int,
     282             :     Word16 *pitch_fr,
     283             :     Word16 *index,
     284             :     Word16 *norm_corr,
     285             :     const Word16 len,
     286             :     const Word16 *wsp, // Qx
     287             :     const Word16 pitmin,
     288             :     const Word16 pitfr1,
     289             :     const Word16 pitfr2,
     290             :     const Word16 pitmax,
     291             :     const Word16 pitres,
     292             :     const Word16 check_border_case,
     293             :     Word16 *border_case )
     294             : {
     295             :     Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp;
     296             :     Word32 cor_max, cor[256], *pt_cor, temp;
     297             :     Word16 wsp2[L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1];
     298             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     299     1044982 :     Flag Overflow = 0;
     300     1044982 :     move32();
     301             : #endif
     302             : 
     303     1044982 :     delta = 16;
     304     1044982 :     move16();
     305     1044982 :     if ( EQ_16( pitres, 6 ) )
     306             :     {
     307      174363 :         delta = 8;
     308      174363 :         move16();
     309             :     }
     310             : 
     311     1044982 :     t0_min = sub( pitch_ol, shr( delta, 1 ) );
     312     1044982 :     t0_max = sub( add( t0_min, delta ), 1 );
     313             : 
     314     1044982 :     IF( LT_16( t0_min, pitmin ) )
     315             :     {
     316       81760 :         t0_min = pitmin;
     317       81760 :         move16();
     318       81760 :         t0_max = sub( add( t0_min, delta ), 1 );
     319             :     }
     320             : 
     321     1044982 :     IF( GT_16( t0_max, pitmax ) )
     322             :     {
     323       21057 :         t0_max = pitmax;
     324       21057 :         move16();
     325       21057 :         t0_min = add( sub( t0_max, delta ), 1 );
     326             :     }
     327             : 
     328     1044982 :     t_min = sub( t0_min, L_INTERPOL1 );
     329     1044982 :     t_max = add( t0_max, L_INTERPOL1 );
     330             : 
     331             :     /* normalize wsp */
     332     1044982 :     s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) );
     333     1044982 :     s_wsp = sub( s_wsp, 4 );
     334   430341927 :     FOR( t = negate( t_max ); t < len; t++ )
     335             :     {
     336   429296945 :         wsp2[t + t_max] = shl( wsp[t], s_wsp ); // Q(x + s_wsp)
     337   429296945 :         move16();
     338             :     }
     339     1044982 :     wsp = wsp2 + t_max;
     340             : 
     341     1044982 :     pt_cor = cor;
     342             : 
     343    24729646 :     FOR( t = t_min; t <= t_max; t++ )
     344             :     {
     345    23684664 :         *pt_cor = dot( wsp, wsp - t, len ); // 2*(x + s_wsp)
     346    23684664 :         move32();
     347    23684664 :         pt_cor++;
     348             :     }
     349             : 
     350     1044982 :     pt_cor = cor + L_INTERPOL1;
     351     1044982 :     cor_max = L_add( *pt_cor++, 0 );
     352     1044982 :     t1 = t0_min;
     353     1044982 :     move16();
     354             : 
     355    15324808 :     FOR( t = t0_min + 1; t <= t0_max; t++ )
     356             :     {
     357    14279826 :         IF( GT_32( *pt_cor, cor_max ) )
     358             :         {
     359     5478926 :             cor_max = *pt_cor;
     360     5478926 :             move32();
     361     5478926 :             t1 = t;
     362     5478926 :             move16();
     363             :         }
     364    14279826 :         pt_cor++;
     365             :     }
     366             : 
     367     1044982 :     temp = dot( wsp, wsp, len ); // 2*(x + s_wsp)
     368     1044982 :     s = norm_l( temp );
     369     1044982 :     temp_e = negate( s );
     370     1044982 :     temp_m = extract_h( L_shl( temp, s ) ); // Q(2*(x + s_wsp) - temp_e - 16)
     371             : 
     372     1044982 :     temp = dot( wsp - t1, wsp - t1, len ); //  2*(x + s_wsp)
     373     1044982 :     s = norm_l( temp );
     374     1044982 :     temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) ); // //Q = 4*(x + s_wsp) + s - temp_e - 47
     375     1044982 :     temp_e = sub( temp_e, s );
     376             : 
     377     1044982 :     temp_m = Sqrt16( temp_m, &temp_e );
     378             : 
     379     1044982 :     if ( temp_m == 0 )
     380             :     {
     381       18699 :         temp_m = 1;
     382       18699 :         move16();
     383             :     }
     384     1044982 :     s = sub( norm_l( cor_max ), 1 );
     385     1044982 :     temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m );
     386     1044982 :     temp_e = sub( negate( s ), temp_e );
     387             : 
     388     1044982 :     *norm_corr = shl_o( temp_m, temp_e, &Overflow );
     389             : 
     390     1044982 :     test();
     391     1044982 :     IF( check_border_case && EQ_16( t1, t0_min ) )
     392             :     {
     393             :         Word32 tmpCor;
     394      386703 :         FOR( t = t1 - L_INTERPOL1; t < t1; t++ )
     395             :         {
     396      332942 :             tmpCor = dot( wsp, wsp - t, len );
     397      332942 :             IF( GT_32( tmpCor, cor_max ) )
     398             :             {
     399       83357 :                 *border_case = 1;
     400       83357 :                 move16();
     401       83357 :                 break;
     402             :             }
     403             :         }
     404             :     }
     405             : 
     406     1044982 :     IF( GE_16( t1, pitfr1 ) )
     407             :     {
     408      226393 :         *pitch_int = t1;
     409      226393 :         move16();
     410      226393 :         *pitch_fr = 0;
     411      226393 :         move16();
     412             : 
     413      226393 :         *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ),
     414      226393 :                                                             sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) );
     415      226393 :         move16();
     416             : 
     417      226393 :         return;
     418             :     }
     419             : 
     420             :     /*------------------------------------------------------------------*
     421             :      * Search fractional pitch with 1/4 subsample resolution.
     422             :      * search the fractions around t0 and choose the one which maximizes
     423             :      * the interpolated normalized correlation.
     424             :      *-----------------------------------------------------------------*/
     425             : 
     426      818589 :     pt_cor = cor + sub( L_INTERPOL1, t0_min );
     427      818589 :     t0 = t1;
     428      818589 :     move16();
     429             : 
     430      818589 :     step = 1;
     431      818589 :     move16();
     432      818589 :     if ( GE_16( t0, pitfr2 ) )
     433             :     {
     434      124915 :         step = 2;
     435      124915 :         move16();
     436             :     }
     437      818589 :     fraction = step;
     438      818589 :     move16();
     439             : 
     440      818589 :     IF( EQ_16( t0, t0_min ) ) /* Limit case */
     441             :     {
     442      110350 :         fraction = 0;
     443      110350 :         move16();
     444      110350 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     445             :     }
     446             :     ELSE /* Process negative fractions */
     447             :     {
     448      708239 :         t0 = sub( t0, 1 );
     449      708239 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     450             : 
     451     1961043 :         FOR( i = fraction + step; i < pitres; i += step )
     452             :         {
     453     1252804 :             temp = interpolate_corr( &pt_cor[t0], i, pitres );
     454             : 
     455     1252804 :             IF( GT_32( temp, cor_max ) )
     456             :             {
     457     1172838 :                 cor_max = L_add( temp, 0 );
     458     1172838 :                 fraction = i;
     459     1172838 :                 move16();
     460             :             }
     461             :         }
     462             :     }
     463             : 
     464     3903057 :     FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */
     465             :     {
     466     3084468 :         temp = interpolate_corr( &pt_cor[t1], i, pitres );
     467             : 
     468     3084468 :         IF( GT_32( temp, cor_max ) )
     469             :         {
     470      874363 :             cor_max = L_add( temp, 0 );
     471      874363 :             fraction = i;
     472      874363 :             move16();
     473      874363 :             t0 = t1;
     474      874363 :             move16();
     475             :         }
     476             :     }
     477             : 
     478      818589 :     *pitch_int = t0;
     479      818589 :     move16();
     480      818589 :     *pitch_fr = fraction;
     481      818589 :     move16();
     482             : 
     483      818589 :     IF( GE_16( t0, pitfr2 ) )
     484             :     {
     485      124116 :         *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ),
     486      124116 :                                          sub( pitfr2, pitmin ), pitres ) ),
     487      124116 :                       shr( fraction, 1 ) );
     488      124116 :         move16();
     489             :     }
     490             :     ELSE
     491             :     {
     492      694473 :         *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction );
     493      694473 :         move16();
     494             :     }
     495             : }
     496             : 
     497             : 
     498         941 : static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_frame, Word16 *gain, Word16 *gain_index )
     499             : {
     500             :     Word32 corr, ener;
     501             :     Word16 i, g, s1, s2, tmp;
     502             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     503         941 :     Flag Overflow = 0;
     504         941 :     move32();
     505             : #endif
     506             : 
     507             : 
     508         941 :     s1 = sub( getScaleFactor16( speech, L_frame ), 4 );
     509         941 :     s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 );
     510             : 
     511             :     /* Find gain */
     512         941 :     corr = L_deposit_l( 0 );
     513         941 :     ener = L_deposit_l( 1 );
     514             : 
     515      289069 :     FOR( i = 0; i < L_frame; i++ )
     516             :     {
     517      288128 :         tmp = shl_sat( pred_speech[i], s2 );
     518      288128 :         corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp );
     519      288128 :         ener = L_mac0_sat( ener, tmp, tmp );
     520             :     }
     521             : 
     522         941 :     s1 = sub( 1, add( s1, s2 ) );
     523         941 :     s2 = sub( 1, shl( s2, 1 ) );
     524             : 
     525         941 :     tmp = sub( norm_l( corr ), 1 );
     526         941 :     corr = L_shl( corr, tmp );
     527         941 :     s1 = sub( s1, tmp );
     528             : 
     529         941 :     tmp = norm_l( ener );
     530         941 :     ener = L_shl( ener, tmp );
     531         941 :     s2 = sub( s2, tmp );
     532             : 
     533         941 :     g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) );
     534             :     BASOP_SATURATE_WARNING_OFF_EVS
     535         941 :     g = shl_o( g, sub( s1, s2 ), &Overflow );
     536             :     BASOP_SATURATE_WARNING_ON_EVS
     537             : 
     538             :     /* Quantize gain */
     539         941 :     g = shr( sub_o( g, 0x1000, &Overflow ), 13 );
     540         941 :     g = s_max( g, -1 );
     541             : 
     542         941 :     *gain_index = g;
     543         941 :     move16();
     544             : 
     545             :     /* Dequantize gain */
     546         941 :     *gain = imult1616( add( g, 1 ), 0x1400 );
     547         941 :     move16();
     548         941 : }
     549             : 
     550      860630 : static void tcx_ltp_find_gain_ivas_fx( Word16 *speech /*Qx*/, Word16 *pred_speech /*Qx*/, Word16 L_frame, Word16 *gain, Word16 *gain_index )
     551             : {
     552             :     Word32 corr, ener;
     553             :     Word16 i, g, s1, s2, tmp;
     554             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     555      860630 :     Flag Overflow = 0;
     556      860630 :     move32();
     557             : #endif
     558             : 
     559      860630 :     s1 = sub( getScaleFactor16( speech, L_frame ), 4 );
     560      860630 :     s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 );
     561             : 
     562             :     /* Find gain */
     563      860630 :     corr = L_deposit_l( 0 );
     564      860630 :     ener = L_deposit_l( 1 );
     565             : 
     566   265913174 :     FOR( i = 0; i < L_frame; i++ )
     567             :     {
     568   265052544 :         tmp = shl_sat( pred_speech[i], s2 );                  // Qx + s2
     569   265052544 :         corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp ); // 2*Qx + s1 + s2
     570   265052544 :         ener = L_mac0_sat( ener, tmp, tmp );                  // 2*(Qx+s2)
     571             :     }
     572             : 
     573      860630 :     s1 = sub( 1, add( s1, s2 ) );
     574      860630 :     s2 = sub( 1, shl( s2, 1 ) );
     575             : 
     576      860630 :     tmp = sub( norm_l( corr ), 1 );
     577      860630 :     corr = L_shl( corr, tmp );
     578      860630 :     s1 = sub( s1, tmp );
     579             : 
     580      860630 :     tmp = norm_l( ener );
     581      860630 :     ener = L_shl( ener, tmp );
     582      860630 :     s2 = sub( s2, tmp );
     583             : 
     584      860630 :     g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) );
     585             :     BASOP_SATURATE_WARNING_OFF_EVS
     586      860630 :     g = shl_o( g, sub( s1, s2 ), &Overflow ); /*Q15*/
     587             :     BASOP_SATURATE_WARNING_ON_EVS
     588             : 
     589             :     /* Quantize gain */
     590      860630 :     g = shr_sat( sub_sat( g /*Q15*/, 0x1000 ), 13 ); // Q0
     591      860630 :     g = s_max( g, -1 );
     592             : 
     593      860630 :     *gain_index = g;
     594      860630 :     move16();
     595             : 
     596             :     /* Dequantize gain */
     597      860630 :     *gain = imult1616( add( g, 1 ), 0x1400 ); /*Q15*/
     598      860630 :     move16();
     599      860630 : }
     600             : 
     601        1311 : void tcx_ltp_encode_fx( Word16 tcxltp_on,
     602             :                         Word8 tcxOnly,
     603             :                         Word16 tcxMode,
     604             :                         Word16 L_frame,
     605             :                         Word16 L_subfr,
     606             :                         Word16 *speech,
     607             :                         Word16 *speech_ltp,
     608             :                         Word16 *wsp,
     609             :                         Word16 Top,
     610             :                         Word16 *ltp_param,
     611             :                         Word16 *ltp_bits,
     612             :                         Word16 *pitch_int,
     613             :                         Word16 *pitch_fr,
     614             :                         Word16 *gain,
     615             :                         Word16 *pitch_int_past,
     616             :                         Word16 *pitch_fr_past,
     617             :                         Word16 *gain_past,
     618             :                         Word16 *norm_corr_past,
     619             :                         Word16 last_core,
     620             :                         Word16 pitmin,
     621             :                         Word16 pitfr1,
     622             :                         Word16 pitfr2,
     623             :                         Word16 pitmax,
     624             :                         Word16 pitres,
     625             :                         struct TransientDetection const *pTransientDetection,
     626             :                         Word8 SideInfoOnly,
     627             :                         Word16 *A,
     628             :                         Word16 lpcorder )
     629             : {
     630             :     Word16 n;
     631             :     Word16 norm_corr;
     632             :     Word16 pred_speech[L_FRAME32k];
     633             :     Word16 tempFlatness;
     634             :     Word16 maxEnergyChange;
     635             :     Word16 buf_zir[M + L_SUBFR], *zir;
     636             :     Word16 Aest[M + 1];
     637             :     Word16 alpha, step;
     638             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     639        1311 :     Flag Overflow = 0;
     640        1311 :     move32();
     641             : #endif
     642             : 
     643             : 
     644        1311 :     norm_corr = 0;
     645        1311 :     move16();
     646             : 
     647             :     /* Reset memory if past frame is acelp */
     648        1311 :     IF( last_core == ACELP_CORE )
     649             :     {
     650         623 :         *pitch_int_past = L_frame;
     651         623 :         move16();
     652         623 :         *pitch_fr_past = 0;
     653         623 :         move16();
     654         623 :         *gain_past = 0;
     655         623 :         move16();
     656             :     }
     657             : 
     658             :     /* By default, LTP is off */
     659        1311 :     ltp_param[0] = 0;
     660        1311 :     move16();
     661             : 
     662        1311 :     test();
     663        1311 :     IF( tcxltp_on != 0 || SideInfoOnly != 0 )
     664             :     {
     665             :         Word16 nPrevSubblocks;
     666        1311 :         Word8 isTCX10 = 0;
     667             : 
     668        1311 :         if ( EQ_16( tcxMode, TCX_10 ) )
     669             :         {
     670           0 :             isTCX10 = 1;
     671           0 :             move16();
     672             :         }
     673             : 
     674             :         /* Find pitch lag */
     675        1311 :         tcx_ltp_pitch_search( Top, pitch_int, pitch_fr, &ltp_param[1], &norm_corr, L_frame, wsp, pitmin, pitfr1, pitfr2, pitmax, pitres );
     676             : 
     677        1311 :         nPrevSubblocks = extract_h( L_mac( 0x17fff, NSUBBLOCKS, div_s( *pitch_int, L_frame ) ) );
     678        1311 :         nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 );
     679             : 
     680        1311 :         tempFlatness = GetTCXAvgTemporalFlatnessMeasure_fx( pTransientDetection, NSUBBLOCKS, nPrevSubblocks );
     681             : 
     682        1311 :         maxEnergyChange = GetTCXMaxenergyChange_fx( pTransientDetection,
     683             :                                                     (const Word8) isTCX10,
     684             :                                                     NSUBBLOCKS, nPrevSubblocks );
     685             : 
     686             :         /* Switch LTP on */
     687        1311 :         test();
     688        1311 :         test();
     689        1311 :         test();
     690        1311 :         test();
     691        1311 :         test();
     692        1311 :         test();
     693        1311 :         test();
     694        1311 :         test();
     695        1311 :         test();
     696        1311 :         test();
     697        1311 :         test();
     698        1311 :         test();
     699        1311 :         test();
     700        1311 :         test();
     701        1311 :         test();
     702        1311 :         test();
     703             :         BASOP_SATURATE_WARNING_OFF_EVS;
     704        1311 :         if ( (
     705        1311 :                  tcxOnly == 0 &&
     706        2622 :                  EQ_16( tcxMode, TCX_20 ) &&
     707        2325 :                  GT_16( mult( norm_corr, *norm_corr_past ), 0x2000 ) &&
     708        1384 :                  LT_16( tempFlatness, 448 /*3.5f Q7*/ ) ) ||
     709           0 :              ( tcxOnly != 0 &&
     710           0 :                EQ_16( tcxMode, TCX_10 ) &&
     711           0 :                GT_16( s_max( norm_corr, *norm_corr_past ), 0x4000 ) &&
     712         370 :                LT_16( maxEnergyChange, 448 /*3.5f Q7*/ ) ) ||
     713             :              ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */
     714           0 :                tcxOnly != 0 &&
     715           0 :                GT_16( norm_corr, 14418 /*0.44f Q15*/ ) &&
     716           0 :                L_msu( L_mult( L_frame, sub( 19661 /*1.2f Q14*/, shr( norm_corr, 1 ) ) ), *pitch_int, 1 << 14 ) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */
     717         370 :                ) ||
     718           0 :              ( tcxOnly != 0 &&
     719           0 :                EQ_16( tcxMode, TCX_20 ) &&
     720           0 :                GT_16( norm_corr, 14418 /*0.44f Q15*/ ) &&
     721           0 :                ( LT_16( tempFlatness, 768 /*6.0f Q7*/ ) ||
     722           0 :                  ( LT_16( tempFlatness, 896 /*7.0f Q7*/ ) &&
     723           0 :                    LT_16( maxEnergyChange, 2816 /*22.0f Q7*/ ) ) ) ) )
     724             :         {
     725         941 :             ltp_param[0] = 1;
     726         941 :             move16();
     727             :         }
     728             :         BASOP_SATURATE_WARNING_ON_EVS;
     729             :     }
     730             : 
     731        1311 :     IF( ltp_param[0] != 0 )
     732             :     {
     733             :         /* Find predicted signal */
     734         941 :         predict_signal( speech, pred_speech, *pitch_int, *pitch_fr, pitres, L_frame );
     735             : 
     736             :         /* Find gain */
     737         941 :         tcx_ltp_find_gain( speech, pred_speech, L_frame, gain, &ltp_param[2] );
     738             : 
     739             :         /* Total number of bits for LTP */
     740         941 :         IF( NE_16( ltp_param[2], -1 ) ) /* gain > 0 */
     741             :         {
     742         941 :             *ltp_bits = 12;
     743         941 :             move16();
     744             :         }
     745             :         ELSE /* gain <= 0 -> turn off LTP */
     746             :         {
     747           0 :             ltp_param[0] = 0;
     748           0 :             move16();
     749             :         }
     750             :     }
     751             : 
     752        1311 :     IF( ltp_param[0] == 0 )
     753             :     {
     754             :         /* No LTP -> set everything to zero */
     755         370 :         *pitch_int = L_frame;
     756         370 :         move16();
     757         370 :         *pitch_fr = 0;
     758         370 :         move16();
     759         370 :         ltp_param[1] = 0;
     760         370 :         move16();
     761         370 :         set16_fx( pred_speech, 0, L_frame );
     762         370 :         *gain = 0;
     763         370 :         move16();
     764         370 :         ltp_param[2] = 0;
     765         370 :         move16();
     766             : 
     767         370 :         *ltp_bits = 0;
     768         370 :         move16();
     769         370 :         test();
     770         370 :         IF( tcxltp_on != 0 || SideInfoOnly != 0 )
     771             :         {
     772         370 :             *ltp_bits = 1;
     773         370 :             move16();
     774             :         }
     775             :     }
     776             : 
     777        1311 :     IF( SideInfoOnly != 0 )
     778             :     {
     779           0 :         *gain = 0;
     780           0 :         move16();
     781             :     }
     782             : 
     783        1311 :     test();
     784        1311 :     IF( *gain_past == 0 && *gain == 0 )
     785             :     {
     786         295 :         Copy( speech, speech_ltp, L_subfr );
     787             :     }
     788        1016 :     ELSE IF( *gain_past == 0 )
     789             :     {
     790         530 :         alpha = 0;
     791         530 :         move16();
     792             : 
     793             :         /* step = 1.f/(float)(L_subfr); */
     794         530 :         step = shl( 2, norm_s( L_subfr ) );
     795         530 :         IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
     796             :         {
     797           0 :             step = mult_r( step, 26214 /*64.f/80.f Q15*/ );
     798             :         }
     799             : 
     800       34450 :         FOR( n = 0; n < L_subfr; n++ )
     801             :         {
     802       33920 :             speech_ltp[n] = sub_o( speech[n], mult_ro( *gain, mult_ro( alpha, pred_speech[n], &Overflow ), &Overflow ), &Overflow );
     803       33920 :             move16();
     804             :             BASOP_SATURATE_WARNING_OFF_EVS;
     805       33920 :             alpha = add_o( alpha, step, &Overflow );
     806             :             BASOP_SATURATE_WARNING_ON_EVS;
     807             :         }
     808             :     }
     809             :     ELSE
     810             :     {
     811         486 :         IF( A == NULL )
     812             :         {
     813           0 :             tcx_ltp_get_lpc( speech - L_frame, L_frame, Aest, lpcorder );
     814           0 :             A = Aest;
     815             :         }
     816             : 
     817         486 :         IF( *gain > 0 )
     818             :         {
     819         411 :             predict_signal( speech - lpcorder, buf_zir, *pitch_int, *pitch_fr, pitres, lpcorder );
     820             :         }
     821             :         ELSE
     822             :         {
     823          75 :             set16_fx( buf_zir, 0, lpcorder );
     824             :         }
     825             : 
     826        8262 :         FOR( n = 0; n < lpcorder; n++ )
     827             :         {
     828        7776 :             buf_zir[n] = add_sat( sub_sat( speech_ltp[n - lpcorder], speech[n - lpcorder] ), mult_r( *gain, buf_zir[n] ) );
     829        7776 :             move16();
     830             :         }
     831             : 
     832         486 :         zir = buf_zir + lpcorder;
     833             : 
     834         486 :         set16_fx( zir, 0, L_subfr );
     835             : 
     836         486 :         E_UTIL_synthesis( 0, A, zir, zir, L_subfr, buf_zir, 0, lpcorder );
     837             : 
     838         486 :         alpha = 0x7FFF;
     839         486 :         move16();
     840             :         /* step = 1.f/(float)(L_subfr/2); */
     841         486 :         step = shl( 4, norm_s( L_subfr ) );
     842         486 :         IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
     843             :         {
     844           0 :             step = mult_r( step, 26214 /*64.f/80.f Q15*/ );
     845             :         }
     846             : 
     847       16038 :         FOR( n = ( L_subfr >> 1 ); n < L_subfr; n++ )
     848             :         {
     849       15552 :             zir[n] = mult_r( zir[n], alpha );
     850       15552 :             move16();
     851       15552 :             alpha = sub( alpha, step );
     852             :         }
     853             : 
     854       31590 :         FOR( n = 0; n < L_subfr; n++ )
     855             :         {
     856       31104 :             speech_ltp[n] = add_o( sub_o( speech[n], mult_ro( *gain, pred_speech[n], &Overflow ), &Overflow ), zir[n], &Overflow );
     857       31104 :             move16();
     858             :         }
     859             :     }
     860             : 
     861        1311 :     test();
     862        1311 :     IF( SideInfoOnly || *gain == 0 )
     863             :     {
     864       91378 :         FOR( n = L_subfr; n < L_frame; n++ )
     865             :         {
     866       91008 :             speech_ltp[n] = speech[n];
     867       91008 :             move16();
     868             :         }
     869             :     }
     870             :     ELSE
     871             :     {
     872      228845 :         FOR( n = L_subfr; n < L_frame; n++ )
     873             :         {
     874      227904 :             speech_ltp[n] = sub_o( speech[n], mult( *gain, pred_speech[n] ), &Overflow );
     875      227904 :             move16();
     876             :         }
     877             :     }
     878             : 
     879             :     /* Update */
     880        1311 :     *pitch_int_past = *pitch_int;
     881        1311 :     move16();
     882        1311 :     *pitch_fr_past = *pitch_fr;
     883        1311 :     move16();
     884        1311 :     *gain_past = *gain;
     885        1311 :     move16();
     886        1311 :     *norm_corr_past = norm_corr;
     887        1311 :     move16();
     888        1311 : }
     889             : 
     890      860630 : void tcx_ltp_encode_ivas_fx(
     891             :     Encoder_State *st,
     892             :     const Word16 tcxMode,
     893             :     const Word16 L_frame,
     894             :     Word16 *speech_fx,
     895             :     Word16 *speech_ltp_fx,
     896             :     const Word16 *wsp_fx,
     897             :     const Word16 Top[],
     898             :     Word16 *ltp_param,
     899             :     Word16 *ltp_bits,
     900             :     Word16 *A_fx,
     901             :     const Word16 disable_ltp,
     902             :     const Word16 element_mode )
     903             : {
     904             :     Word16 i, n;
     905             :     Word16 ltp_on, tcxOnly, L_subfr, SideInfoOnly, delta;
     906             :     Word16 si_gain_fx;        // Q15
     907             :     Word16 alpha_fx, step_fx; // Q15
     908             :     Word16 norm_corr_fx;      // Q15
     909             :     Word16 border_case;
     910             :     Word16 tempFlatness_fx;                           // Q7
     911             :     Word16 maxEnergyChange_fx;                        // Q3
     912             :     Word16 pred_speech_fx[L_FRAME_PLUS];              // Qspeech
     913             :     Word16 buf_zir_fx[M + L_FRAME_PLUS / 4], *zir_fx; // Qspeech
     914             :     Word16 Aest_fx[M + 1];
     915             :     Word16 exponent;
     916             :     Word16 sqr;
     917      860630 :     Flag Overflow = 0;
     918      860630 :     move32();
     919             : 
     920      860630 :     TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
     921             : 
     922      860630 :     tcxOnly = st->tcxonly;
     923      860630 :     move16();
     924      860630 :     L_subfr = L_SUBFR;
     925      860630 :     move16();
     926      860630 :     SideInfoOnly = extract_l( GT_32( st->sr_core, 25600 ) );
     927      860630 :     move16();
     928             : 
     929             :     /* Reset memory if past frame is acelp */
     930      860630 :     IF( st->last_core == ACELP_CORE )
     931             :     {
     932        9189 :         hTcxEnc->tcxltp_pitch_int_past = L_frame;
     933        9189 :         move16();
     934        9189 :         hTcxEnc->tcxltp_pitch_fr_past = 0;
     935        9189 :         move16();
     936        9189 :         hTcxEnc->tcxltp_gain_past = 0;
     937        9189 :         move16();
     938             :     }
     939             : 
     940             :     /* By default, LTP is off */
     941      860630 :     ltp_param[0] = 0;
     942      860630 :     move16();
     943      860630 :     norm_corr_fx = 0;
     944      860630 :     move16();
     945      860630 :     border_case = 0;
     946      860630 :     move16();
     947             : 
     948      860630 :     test();
     949      860630 :     IF( hTcxEnc->tcxltp || SideInfoOnly )
     950             :     {
     951             :         Word16 nPrevSubblocks;
     952      860630 :         Word8 isTCX10 = 0;
     953      860630 :         move16();
     954             : 
     955             :         /* Find pitch lag */
     956      860630 :         IF( EQ_16( st->pit_res_max, 6 ) )
     957             :         {
     958      174363 :             delta = 8;
     959      174363 :             move16();
     960             :         }
     961             :         ELSE
     962             :         {
     963      686267 :             delta = 16;
     964      686267 :             move16();
     965             :         }
     966             : 
     967      860630 :         IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
     968             :         {
     969      624343 :             IF( LT_16( abs_s( sub( Top[0], Top[1] ) ), shr( delta, 1 ) ) )
     970             :             {
     971             :                 /* estimates are close enough and stable, take the artihmetic mean as estimate */
     972      439991 :                 tcx_ltp_pitch_search_ivas_fx( shr( add( Top[0], Top[1] ), 1 ), &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, &ltp_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case );
     973             :             }
     974             :             ELSE
     975             :             {
     976             :                 /* pitch jumps between half frames, calc ltp for both estimates, choose the better one */
     977             :                 Word16 pitch_int_2[2];
     978             :                 Word16 pitch_fr_2[2];
     979             :                 Word16 norm_corr_2_fx[2];
     980             :                 Word16 pit_param_2[2];
     981             : 
     982      553056 :                 FOR( i = 0; i < 2; i++ )
     983             :                 {
     984      368704 :                     tcx_ltp_pitch_search_ivas_fx( Top[i], &pitch_int_2[i], &pitch_fr_2[i], &pit_param_2[i], &norm_corr_2_fx[i], L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case );
     985             :                 }
     986             : 
     987      184352 :                 IF( GT_16( norm_corr_2_fx[1], norm_corr_2_fx[0] ) )
     988             :                 {
     989      119091 :                     i = 1;
     990             :                 }
     991             :                 ELSE
     992             :                 {
     993       65261 :                     i = 0;
     994             :                 }
     995      184352 :                 move16();
     996             : 
     997      184352 :                 hTcxEnc->tcxltp_pitch_int = pitch_int_2[i];
     998      184352 :                 move16();
     999      184352 :                 hTcxEnc->tcxltp_pitch_fr = pitch_fr_2[i];
    1000      184352 :                 move16();
    1001      184352 :                 ltp_param[1] = pit_param_2[i];
    1002      184352 :                 move16();
    1003      184352 :                 norm_corr_fx = norm_corr_2_fx[i];
    1004      184352 :                 move16();
    1005             :             }
    1006             :         }
    1007             :         ELSE
    1008             :         {
    1009             :             Word16 tmp;
    1010      236287 :             IF( GT_16( element_mode, EVS_MONO ) )
    1011             :             {
    1012      236287 :                 tmp = 1;
    1013             :             }
    1014             :             ELSE
    1015             :             {
    1016           0 :                 tmp = 0;
    1017             :             }
    1018      236287 :             move16();
    1019      236287 :             tcx_ltp_pitch_search_ivas_fx( Top[1], &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, &ltp_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, tmp, &border_case );
    1020             :         }
    1021             : 
    1022      860630 :         if ( border_case )
    1023             :         {
    1024       79595 :             norm_corr_fx = 0;
    1025       79595 :             move16();
    1026             :         }
    1027             : 
    1028             :         // nPrevSubblocks = ( 1 + min( NSUBBLOCKS, (int16_t) ceil( 0.5f + NSUBBLOCKS * ( 1.0f * ( hTcxEnc->tcxltp_pitch_int ) / L_frame ) ) ) );
    1029      860630 :         nPrevSubblocks = extract_h( L_add( L_mac( 32768, NSUBBLOCKS, div_s( hTcxEnc->tcxltp_pitch_int, L_frame ) ), 65535 ) ); // 0.5f Q16 //65535( 1.Q16 - 1) added to get the ceil
    1030      860630 :         nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 );
    1031             : 
    1032      860630 :         IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) )
    1033             :         {
    1034       14304 :             tempFlatness_fx = extract_l( L_shr( GetTCXAvgTemporalFlatnessMeasure_ivas_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ), 14 ) ); // Q7
    1035       14304 :             maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10,
    1036       14304 :                                                                 NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q3
    1037             :         }
    1038             :         ELSE
    1039             :         {
    1040      846326 :             tempFlatness_fx = extract_l( L_shr( ( GetTCXAvgTemporalFlatnessMeasure_ivas_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS, nPrevSubblocks ) ), 14 ) ); // Q7
    1041      846326 :             maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10,
    1042             :                                                                 NSUBBLOCKS, nPrevSubblocks ); // Q3
    1043             :         }
    1044             : 
    1045             :         /* Switch LTP on */
    1046      860630 :         test();
    1047      860630 :         test();
    1048      860630 :         test();
    1049      860630 :         test();
    1050      860630 :         test();
    1051      860630 :         test();
    1052      860630 :         test();
    1053      860630 :         test();
    1054      860630 :         test();
    1055      860630 :         test();
    1056      860630 :         test();
    1057      860630 :         test();
    1058      860630 :         test();
    1059      860630 :         test();
    1060      860630 :         test();
    1061      860630 :         test();
    1062      860630 :         IF( (
    1063             :                 ( tcxOnly == 0 ) &&
    1064             :                 EQ_16( tcxMode, TCX_20 ) &&
    1065             :                 GT_16( mult( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x2000 ) && /*mult returns Q15*/
    1066             :                 LT_16( tempFlatness_fx, 448 /*3.5f Q7*/ ) ) ||
    1067             :             ( EQ_16( tcxOnly, 1 ) &&
    1068             :               EQ_16( tcxMode, TCX_10 ) &&
    1069             :               GT_16( s_max( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x4000 ) &&
    1070             :               LT_16( maxEnergyChange_fx, 28 /*3.5f Q3*/ ) ) ||
    1071             :             ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */
    1072             :               EQ_16( tcxOnly, 1 ) &&
    1073             :               GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) &&
    1074             :               L_msu( L_mult( L_frame, sub( 19661 /*1.2f Q14*/, shr( norm_corr_fx, 1 ) ) ), hTcxEnc->tcxltp_pitch_int, 1 << 14 ) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */
    1075             :               ) ||
    1076             :             ( EQ_16( tcxOnly, 1 ) &&
    1077             :               EQ_16( tcxMode, TCX_20 ) &&
    1078             :               GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) &&
    1079             :               ( LT_16( tempFlatness_fx, 768 /*6.0f Q7*/ ) ||
    1080             :                 ( LT_16( tempFlatness_fx, 896 /*7.0f Q7*/ ) &&
    1081             :                   LT_16( maxEnergyChange_fx, 176 /*22.0f Q3*/ ) ) ) ) )
    1082             :         {
    1083      520698 :             IF( disable_ltp == 0 )
    1084             :             {
    1085      520655 :                 ltp_param[0] = 1;
    1086      520655 :                 move16();
    1087             :             }
    1088             :         }
    1089             : 
    1090             :         /* hysteresis for stable ltp prediction */
    1091      860630 :         ltp_on = 0;
    1092      860630 :         move16();
    1093             : 
    1094      860630 :         test();
    1095      860630 :         test();
    1096      860630 :         test();
    1097      860630 :         test();
    1098      860630 :         test();
    1099             : 
    1100      860630 :         exponent = 15;
    1101      860630 :         move16();
    1102      860630 :         sqr = Sqrt16( hTcxEnc->tcxltp_on_mem, &exponent );
    1103      860630 :         move16();
    1104      860630 :         IF( ( EQ_16( tcxOnly, 1 ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) && ( GT_16( ( mult( sqr, mult( ( norm_corr_fx ), 29492 ) ) ), shr( 14419, exponent ) ) && ( LT_16( tempFlatness_fx, 768 ) || ( LT_16( tempFlatness_fx, 896 ) && LT_16( maxEnergyChange_fx, 176 ) ) ) ) ) ) // 0.9f Q15, 6.0f Q7, 7.0f Q7, 22.0f Q3
    1105             :         {
    1106      400321 :             ltp_on = 1;
    1107      400321 :             move16();
    1108             :         }
    1109             : 
    1110      860630 :         test();
    1111      860630 :         IF( EQ_16( tcxOnly, 1 ) && EQ_16( ltp_param[0], 1 ) )
    1112             :         {
    1113             :             /* increase ltp counter */
    1114      459651 :             hTcxEnc->tcxltp_on_mem = s_min( 5, add( hTcxEnc->tcxltp_on_mem, 1 ) );
    1115      459651 :             move16();
    1116             :         }
    1117      400979 :         ELSE IF( EQ_16( ltp_on, 1 ) )
    1118             :         {
    1119             :             /* hysteresis takes effect, decrease counter */
    1120       44902 :             hTcxEnc->tcxltp_on_mem = s_max( 0, sub( hTcxEnc->tcxltp_on_mem, 1 ) );
    1121       44902 :             move16();
    1122       44902 :             ltp_param[0] = ltp_on;
    1123       44902 :             move16();
    1124             :         }
    1125             :         ELSE
    1126             :         {
    1127             :             /* no ltp in this frame, reset counter */
    1128      356077 :             hTcxEnc->tcxltp_on_mem = 0;
    1129      356077 :             move16();
    1130             :         }
    1131             :     }
    1132             : 
    1133             :     /* Find predicted signal */
    1134      860630 :     predict_signal( speech_fx, pred_speech_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, L_frame );
    1135             : 
    1136             :     /* Find gain */
    1137      860630 :     tcx_ltp_find_gain_ivas_fx( speech_fx, pred_speech_fx, L_frame, &hTcxEnc->tcxltp_gain, &ltp_param[2] );
    1138             : 
    1139      860630 :     IF( ltp_param[0] )
    1140             :     {
    1141             :         /* Total number of bits for LTP */
    1142      565557 :         IF( add( ltp_param[2], 1 ) ) /* hTcxEnc->tcxltp_gain > 0 */
    1143             :         {
    1144      565481 :             *ltp_bits = 12;
    1145      565481 :             move16();
    1146             :         }
    1147             :         ELSE /* hTcxEnc->tcxltp_gain <= 0 -> turn off LTP */
    1148             :         {
    1149          76 :             ltp_param[0] = 0;
    1150          76 :             move16();
    1151             :         }
    1152             :     }
    1153             : 
    1154      860630 :     IF( !ltp_param[0] )
    1155             :     {
    1156             :         /* No LTP -> set everything to zero */
    1157      295149 :         hTcxEnc->tcxltp_pitch_int = L_frame;
    1158      295149 :         move16();
    1159      295149 :         hTcxEnc->tcxltp_pitch_fr = 0;
    1160      295149 :         move16();
    1161      295149 :         ltp_param[1] = 0;
    1162      295149 :         move16();
    1163      295149 :         set16_fx( pred_speech_fx, 0, L_frame );
    1164      295149 :         hTcxEnc->tcxltp_gain = 0;
    1165      295149 :         move16();
    1166      295149 :         ltp_param[2] = 0;
    1167      295149 :         move16();
    1168             : 
    1169      295149 :         test();
    1170      295149 :         IF( hTcxEnc->tcxltp || SideInfoOnly )
    1171             :         {
    1172      295149 :             *ltp_bits = 1;
    1173      295149 :             move16();
    1174             :         }
    1175             :         ELSE
    1176             :         {
    1177           0 :             *ltp_bits = 0;
    1178           0 :             move16();
    1179             :         }
    1180             :     }
    1181             : 
    1182      860630 :     si_gain_fx = 0;
    1183      860630 :     move16();
    1184             : 
    1185      860630 :     IF( SideInfoOnly )
    1186             :     {
    1187      420679 :         si_gain_fx = hTcxEnc->tcxltp_gain;
    1188      420679 :         move16();
    1189      420679 :         hTcxEnc->tcxltp_gain = 0;
    1190      420679 :         move16();
    1191             :     }
    1192             : 
    1193      860630 :     IF( speech_ltp_fx != NULL )
    1194             :     {
    1195      221983 :         test();
    1196      221983 :         IF( hTcxEnc->tcxltp_gain_past == 0 && hTcxEnc->tcxltp_gain == 0 )
    1197             :         {
    1198      150850 :             Copy( speech_fx, speech_ltp_fx, L_subfr );
    1199             :         }
    1200       71133 :         ELSE IF( hTcxEnc->tcxltp_gain_past == 0 )
    1201             :         {
    1202       11571 :             alpha_fx = 0;
    1203       11571 :             move16();
    1204             : 
    1205       11571 :             step_fx = shl( 2, norm_s( L_subfr ) );
    1206       11571 :             IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
    1207             :             {
    1208           0 :                 step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ );
    1209             :             }
    1210             : 
    1211      752115 :             FOR( n = 0; n < L_subfr; n++ )
    1212             :             {
    1213      740544 :                 speech_ltp_fx[n] = sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, mult_ro( alpha_fx, pred_speech_fx[n], &Overflow ), &Overflow ), &Overflow );
    1214      740544 :                 move16();
    1215      740544 :                 alpha_fx = add_sat( alpha_fx, step_fx );
    1216             :             }
    1217             :         }
    1218             :         ELSE
    1219             :         {
    1220       59562 :             IF( A_fx == NULL )
    1221             :             {
    1222       59562 :                 tcx_ltp_get_lpc( speech_fx - L_frame, L_frame, Aest_fx, M );
    1223       59562 :                 A_fx = Aest_fx;
    1224             :             }
    1225             : 
    1226       59562 :             IF( hTcxEnc->tcxltp_gain > 0 )
    1227             :             {
    1228       50554 :                 predict_signal( speech_fx - M, buf_zir_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, M );
    1229             :             }
    1230             :             ELSE
    1231             :             {
    1232        9008 :                 set16_fx( buf_zir_fx, 0, M );
    1233             :             }
    1234             : 
    1235     1012554 :             FOR( n = 0; n < M; n++ )
    1236             :             {
    1237      952992 :                 buf_zir_fx[n] = add_sat( sub_sat( speech_ltp_fx[n - M], speech_fx[n - M] ), mult_r( hTcxEnc->tcxltp_gain, buf_zir_fx[n] ) );
    1238      952992 :                 move16();
    1239             :             }
    1240             : 
    1241       59562 :             zir_fx = buf_zir_fx + M;
    1242       59562 :             set16_fx( zir_fx, 0, L_subfr );
    1243             : 
    1244       59562 :             Syn_filt_s( 0, A_fx, M, zir_fx, zir_fx, L_subfr, buf_zir_fx, 0 );
    1245             : 
    1246       59562 :             alpha_fx = 0x7FFF; // 1.f Q15
    1247       59562 :             move16();
    1248       59562 :             step_fx = shl( 4, norm_s( L_subfr ) );
    1249       59562 :             IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 )
    1250             :             {
    1251           0 :                 step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ );
    1252             :             }
    1253             : 
    1254     1965546 :             FOR( n = L_subfr >> 1; n < L_subfr; n++ )
    1255             :             {
    1256     1905984 :                 zir_fx[n] = mult_r( zir_fx[n], alpha_fx );
    1257     1905984 :                 move16();
    1258     1905984 :                 alpha_fx = sub( alpha_fx, step_fx );
    1259             :             }
    1260             : 
    1261     3871530 :             FOR( n = 0; n < L_subfr; n++ )
    1262             :             {
    1263     3811968 :                 speech_ltp_fx[n] = add_o( sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, pred_speech_fx[n], &Overflow ), &Overflow ), zir_fx[n], &Overflow );
    1264     3811968 :                 move16();
    1265             :             }
    1266             :         }
    1267             : 
    1268      221983 :         test();
    1269      221983 :         IF( SideInfoOnly || hTcxEnc->tcxltp_gain == 0 )
    1270             :         {
    1271    71967858 :             FOR( n = L_subfr; n < L_frame; n++ )
    1272             :             {
    1273    71808000 :                 speech_ltp_fx[n] = speech_fx[n];
    1274    71808000 :                 move16();
    1275             :             }
    1276             :         }
    1277             :         ELSE
    1278             :         {
    1279    14992813 :             FOR( n = L_subfr; n < L_frame; n++ )
    1280             :             {
    1281    14930688 :                 speech_ltp_fx[n] = sub_o( speech_fx[n], mult( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ), &Overflow );
    1282    14930688 :                 move16();
    1283             :             }
    1284             :         }
    1285             :     }
    1286             : 
    1287             :     /* Update */
    1288      860630 :     hTcxEnc->tcxltp_pitch_int_past = hTcxEnc->tcxltp_pitch_int;
    1289      860630 :     move16();
    1290      860630 :     hTcxEnc->tcxltp_pitch_fr_past = hTcxEnc->tcxltp_pitch_fr;
    1291      860630 :     move16();
    1292      860630 :     hTcxEnc->tcxltp_gain_past = hTcxEnc->tcxltp_gain;
    1293      860630 :     move16();
    1294             : 
    1295      860630 :     IF( SideInfoOnly )
    1296             :     {
    1297      420679 :         hTcxEnc->tcxltp_gain = si_gain_fx;
    1298      420679 :         move16();
    1299             :     }
    1300             : 
    1301      860630 :     hTcxEnc->tcxltp_norm_corr_past = norm_corr_fx;
    1302      860630 :     move16();
    1303             : 
    1304      860630 :     return;
    1305             : }

Generated by: LCOV version 1.14