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

Generated by: LCOV version 1.14