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 @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 632 661 95.6 %
Date: 2025-05-03 01:55:50 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    26110269 : static Word32 dot( const Word16 *X, const Word16 *Y, Word16 n )
      17             : {
      18             :     Word32 acc;
      19             :     Word16 i;
      20             : 
      21             :     Word64 acc_64;
      22    26110269 :     acc_64 = 0;
      23    26110269 :     move64();
      24  7551217021 :     FOR( i = 0; i < n; i++ )
      25             :     {
      26  7525106752 :         acc_64 = W_mac0_16_16( acc_64, X[i], Y[i] );
      27             :     }
      28    26110269 :     acc = W_sat_l( acc_64 );
      29             : 
      30    26110269 :     return acc;
      31             : }
      32             : 
      33     5156045 : 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     5156045 :     win = E_ROM_inter4_1_fx;
      44     5156045 :     if ( EQ_16( frac_max, 6 ) )
      45      284990 :         win = E_ROM_inter6_1_fx;
      46             : 
      47             : 
      48     5156045 :     s = L_deposit_l( 0 );
      49             : 
      50     5156045 :     c = &win[frac];
      51     5156045 :     s = L_add( s, Mpy_32_16_1( x[0], *c ) );
      52     5156045 :     c += frac_max;
      53     5156045 :     s = L_add( s, Mpy_32_16_1( x[-1], *c ) );
      54     5156045 :     c += frac_max;
      55     5156045 :     s = L_add( s, Mpy_32_16_1( x[-2], *c ) );
      56     5156045 :     c += frac_max;
      57     5156045 :     s = L_add( s, Mpy_32_16_1( x[-3], *c ) );
      58             : 
      59     5156045 :     c = &win[frac_max - frac];
      60     5156045 :     s = L_add( s, Mpy_32_16_1( x[1], *c ) );
      61     5156045 :     c += frac_max;
      62     5156045 :     s = L_add( s, Mpy_32_16_1( x[2], *c ) );
      63     5156045 :     c += frac_max;
      64     5156045 :     s = L_add( s, Mpy_32_16_1( x[3], *c ) );
      65     5156045 :     c += frac_max;
      66     5156045 :     s = L_add( s, Mpy_32_16_1( x[4], *c ) );
      67             : 
      68             : 
      69     5156045 :     return s;
      70             : }
      71             : 
      72        1310 : 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        1310 :     Flag Overflow = 0;
      91        1310 :     move32();
      92             : #endif
      93             : 
      94             : 
      95        1310 :     delta = 16;
      96        1310 :     move16();
      97        1310 :     if ( EQ_16( pitres, 6 ) )
      98             :     {
      99        1050 :         delta = 8;
     100        1050 :         move16();
     101             :     }
     102             : 
     103        1310 :     t0_min = sub( pitch_ol, shr( delta, 1 ) );
     104        1310 :     t0_max = sub( add( t0_min, delta ), 1 );
     105             : 
     106        1310 :     IF( LT_16( t0_min, pitmin ) )
     107             :     {
     108          38 :         t0_min = pitmin;
     109          38 :         move16();
     110          38 :         t0_max = sub( add( t0_min, delta ), 1 );
     111             :     }
     112             : 
     113        1310 :     IF( GT_16( t0_max, pitmax ) )
     114             :     {
     115          17 :         t0_max = pitmax;
     116          17 :         move16();
     117          17 :         t0_min = add( sub( t0_max, delta ), 1 );
     118             :     }
     119             : 
     120        1310 :     t_min = sub( t0_min, L_INTERPOL1 );
     121        1310 :     t_max = add( t0_max, L_INTERPOL1 );
     122             : 
     123             :     /* normalize wsp */
     124        1310 :     assert( len + t_max <= L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1 );
     125        1310 :     s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) );
     126        1310 :     s_wsp = sub( s_wsp, 4 );
     127      540857 :     FOR( t = negate( t_max ); t < len; t++ )
     128             :     {
     129      539547 :         wsp2[t + t_max] = shl( wsp[t], s_wsp );
     130      539547 :         move16();
     131             :     }
     132        1310 :     wsp = wsp2 + t_max;
     133        1310 :     move16();
     134             : 
     135        1310 :     pt_cor = cor;
     136        1310 :     move32();
     137             : 
     138       24350 :     FOR( t = t_min; t <= t_max; t++ )
     139             :     {
     140       23040 :         *pt_cor = dot( wsp, wsp - t, len );
     141       23040 :         move32();
     142       23040 :         pt_cor++;
     143             :     }
     144             : 
     145        1310 :     pt_cor = cor + L_INTERPOL1;
     146        1310 :     cor_max = L_add( *pt_cor++, 0 );
     147        1310 :     t1 = t0_min;
     148        1310 :     move16();
     149        1310 :     move32();
     150             : 
     151       12560 :     FOR( t = t0_min + 1; t <= t0_max; t++ )
     152             :     {
     153       11250 :         IF( GT_32( *pt_cor, cor_max ) )
     154             :         {
     155        4916 :             cor_max = *pt_cor;
     156        4916 :             move32();
     157        4916 :             t1 = t;
     158        4916 :             move16();
     159             :         }
     160       11250 :         pt_cor++;
     161             :     }
     162             : 
     163        1310 :     temp = dot( wsp, wsp, len );
     164        1310 :     s = norm_l( temp );
     165        1310 :     temp_m = extract_h( L_shl( temp, s ) );
     166        1310 :     temp_e = negate( s );
     167             : 
     168        1310 :     temp = dot( wsp - t1, wsp - t1, len );
     169        1310 :     s = norm_l( temp );
     170        1310 :     temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) );
     171        1310 :     temp_e = sub( temp_e, s );
     172             : 
     173        1310 :     temp_m = Sqrt16( temp_m, &temp_e );
     174             : 
     175        1310 :     if ( temp_m == 0 )
     176             :     {
     177           0 :         temp_m = 1;
     178           0 :         move16();
     179             :     }
     180        1310 :     s = sub( norm_l( cor_max ), 1 );
     181        1310 :     temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m );
     182        1310 :     temp_e = sub( negate( s ), temp_e );
     183             : 
     184        1310 :     *norm_corr = shl_o( temp_m, temp_e, &Overflow );
     185             : 
     186        1310 :     IF( GE_16( t1, pitfr1 ) )
     187             :     {
     188         193 :         *pitch_int = t1;
     189         193 :         move16();
     190         193 :         *pitch_fr = 0;
     191         193 :         move16();
     192             : 
     193         193 :         *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ),
     194         193 :                                                             sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) );
     195         193 :         move16();
     196             : 
     197         193 :         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        1117 :     pt_cor = cor + sub( L_INTERPOL1, t0_min );
     207        1117 :     t0 = t1;
     208        1117 :     move16();
     209             : 
     210        1117 :     step = 1;
     211        1117 :     move16();
     212        1117 :     if ( GE_16( t0, pitfr2 ) )
     213             :     {
     214         885 :         step = 2;
     215         885 :         move16();
     216             :     }
     217        1117 :     fraction = step;
     218        1117 :     move16();
     219             : 
     220        1117 :     IF( EQ_16( t0, t0_min ) ) /* Limit case */
     221             :     {
     222         132 :         fraction = 0;
     223         132 :         move16();
     224         132 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     225             :     }
     226             :     ELSE /* Process negative fractions */
     227             :     {
     228         985 :         t0 = sub( t0, 1 );
     229         985 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     230             : 
     231        2172 :         FOR( i = fraction + step; i < pitres; i += step )
     232             :         {
     233        1187 :             temp = interpolate_corr( &pt_cor[t0], i, pitres );
     234             : 
     235        1187 :             IF( GT_32( temp, cor_max ) )
     236             :             {
     237        1155 :                 cor_max = L_add( temp, 0 );
     238        1155 :                 fraction = i;
     239        1155 :                 move16();
     240             :             }
     241             :         }
     242             :     }
     243             : 
     244        1117 :     i = 0;
     245        1117 :     move16();
     246        4687 :     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        1065 :             cor_max = L_add( temp, 0 );
     253        1065 :             fraction = i;
     254        1065 :             move16();
     255        1065 :             t0 = t1;
     256        1065 :             move16();
     257             :         }
     258             :     }
     259             : 
     260        1117 :     *pitch_int = t0;
     261        1117 :     move16();
     262        1117 :     *pitch_fr = fraction;
     263        1117 :     move16();
     264             : 
     265        1117 :     IF( GE_16( t0, pitfr2 ) )
     266             :     {
     267         885 :         *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ),
     268         885 :                                          sub( pitfr2, pitmin ), pitres ) ),
     269         885 :                       shr( fraction, 1 ) );
     270         885 :         move16();
     271             :     }
     272             :     ELSE
     273             :     {
     274         232 :         *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction );
     275         232 :         move16();
     276             :     }
     277             : }
     278             : 
     279     1044001 : 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     1044001 :     Flag Overflow = 0;
     300     1044001 :     move32();
     301             : #endif
     302             : 
     303     1044001 :     delta = 16;
     304     1044001 :     move16();
     305     1044001 :     if ( EQ_16( pitres, 6 ) )
     306             :     {
     307      173912 :         delta = 8;
     308      173912 :         move16();
     309             :     }
     310             : 
     311     1044001 :     t0_min = sub( pitch_ol, shr( delta, 1 ) );
     312     1044001 :     t0_max = sub( add( t0_min, delta ), 1 );
     313             : 
     314     1044001 :     IF( LT_16( t0_min, pitmin ) )
     315             :     {
     316       81186 :         t0_min = pitmin;
     317       81186 :         move16();
     318       81186 :         t0_max = sub( add( t0_min, delta ), 1 );
     319             :     }
     320             : 
     321     1044001 :     IF( GT_16( t0_max, pitmax ) )
     322             :     {
     323       20987 :         t0_max = pitmax;
     324       20987 :         move16();
     325       20987 :         t0_min = add( sub( t0_max, delta ), 1 );
     326             :     }
     327             : 
     328     1044001 :     t_min = sub( t0_min, L_INTERPOL1 );
     329     1044001 :     t_max = add( t0_max, L_INTERPOL1 );
     330             : 
     331             :     /* normalize wsp */
     332     1044001 :     s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) );
     333     1044001 :     s_wsp = sub( s_wsp, 4 );
     334   430004039 :     FOR( t = negate( t_max ); t < len; t++ )
     335             :     {
     336   428960038 :         wsp2[t + t_max] = shl( wsp[t], s_wsp ); // Q(x + s_wsp)
     337   428960038 :         move16();
     338             :     }
     339     1044001 :     wsp = wsp2 + t_max;
     340             : 
     341     1044001 :     pt_cor = cor;
     342             : 
     343    24708729 :     FOR( t = t_min; t <= t_max; t++ )
     344             :     {
     345    23664728 :         *pt_cor = dot( wsp, wsp - t, len ); // 2*(x + s_wsp)
     346    23664728 :         move32();
     347    23664728 :         pt_cor++;
     348             :     }
     349             : 
     350     1044001 :     pt_cor = cor + L_INTERPOL1;
     351     1044001 :     cor_max = L_add( *pt_cor++, 0 );
     352     1044001 :     t1 = t0_min;
     353     1044001 :     move16();
     354             : 
     355    15312720 :     FOR( t = t0_min + 1; t <= t0_max; t++ )
     356             :     {
     357    14268719 :         IF( GT_32( *pt_cor, cor_max ) )
     358             :         {
     359     5475507 :             cor_max = *pt_cor;
     360     5475507 :             move32();
     361     5475507 :             t1 = t;
     362     5475507 :             move16();
     363             :         }
     364    14268719 :         pt_cor++;
     365             :     }
     366             : 
     367     1044001 :     temp = dot( wsp, wsp, len ); // 2*(x + s_wsp)
     368     1044001 :     s = norm_l( temp );
     369     1044001 :     temp_e = negate( s );
     370     1044001 :     temp_m = extract_h( L_shl( temp, s ) ); // Q(2*(x + s_wsp) - temp_e - 16)
     371             : 
     372     1044001 :     temp = dot( wsp - t1, wsp - t1, len ); //  2*(x + s_wsp)
     373     1044001 :     s = norm_l( temp );
     374     1044001 :     temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) ); // //Q = 4*(x + s_wsp) + s - temp_e - 47
     375     1044001 :     temp_e = sub( temp_e, s );
     376             : 
     377     1044001 :     temp_m = Sqrt16( temp_m, &temp_e );
     378             : 
     379     1044001 :     if ( temp_m == 0 )
     380             :     {
     381       18568 :         temp_m = 1;
     382       18568 :         move16();
     383             :     }
     384     1044001 :     s = sub( norm_l( cor_max ), 1 );
     385     1044001 :     temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m );
     386     1044001 :     temp_e = sub( negate( s ), temp_e );
     387             : 
     388     1044001 :     *norm_corr = shl_o( temp_m, temp_e, &Overflow );
     389             : 
     390     1044001 :     test();
     391     1044001 :     IF( check_border_case && EQ_16( t1, t0_min ) )
     392             :     {
     393             :         Word32 tmpCor;
     394      385340 :         FOR( t = t1 - L_INTERPOL1; t < t1; t++ )
     395             :         {
     396      331879 :             tmpCor = dot( wsp, wsp - t, len );
     397      331879 :             IF( GT_32( tmpCor, cor_max ) )
     398             :             {
     399       83549 :                 *border_case = 1;
     400       83549 :                 move16();
     401       83549 :                 break;
     402             :             }
     403             :         }
     404             :     }
     405             : 
     406     1044001 :     IF( GE_16( t1, pitfr1 ) )
     407             :     {
     408      226140 :         *pitch_int = t1;
     409      226140 :         move16();
     410      226140 :         *pitch_fr = 0;
     411      226140 :         move16();
     412             : 
     413      226140 :         *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ),
     414      226140 :                                                             sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) );
     415      226140 :         move16();
     416             : 
     417      226140 :         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      817861 :     pt_cor = cor + sub( L_INTERPOL1, t0_min );
     427      817861 :     t0 = t1;
     428      817861 :     move16();
     429             : 
     430      817861 :     step = 1;
     431      817861 :     move16();
     432      817861 :     if ( GE_16( t0, pitfr2 ) )
     433             :     {
     434      124982 :         step = 2;
     435      124982 :         move16();
     436             :     }
     437      817861 :     fraction = step;
     438      817861 :     move16();
     439             : 
     440      817861 :     IF( EQ_16( t0, t0_min ) ) /* Limit case */
     441             :     {
     442      110364 :         fraction = 0;
     443      110364 :         move16();
     444      110364 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     445             :     }
     446             :     ELSE /* Process negative fractions */
     447             :     {
     448      707497 :         t0 = sub( t0, 1 );
     449      707497 :         cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres );
     450             : 
     451     1958730 :         FOR( i = fraction + step; i < pitres; i += step )
     452             :         {
     453     1251233 :             temp = interpolate_corr( &pt_cor[t0], i, pitres );
     454             : 
     455     1251233 :             IF( GT_32( temp, cor_max ) )
     456             :             {
     457     1171707 :                 cor_max = L_add( temp, 0 );
     458     1171707 :                 fraction = i;
     459     1171707 :                 move16();
     460             :             }
     461             :         }
     462             :     }
     463             : 
     464     3898938 :     FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */
     465             :     {
     466     3081077 :         temp = interpolate_corr( &pt_cor[t1], i, pitres );
     467             : 
     468     3081077 :         IF( GT_32( temp, cor_max ) )
     469             :         {
     470      872959 :             cor_max = L_add( temp, 0 );
     471      872959 :             fraction = i;
     472      872959 :             move16();
     473      872959 :             t0 = t1;
     474      872959 :             move16();
     475             :         }
     476             :     }
     477             : 
     478      817861 :     *pitch_int = t0;
     479      817861 :     move16();
     480      817861 :     *pitch_fr = fraction;
     481      817861 :     move16();
     482             : 
     483      817861 :     IF( GE_16( t0, pitfr2 ) )
     484             :     {
     485      124188 :         *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ),
     486      124188 :                                          sub( pitfr2, pitmin ), pitres ) ),
     487      124188 :                       shr( fraction, 1 ) );
     488      124188 :         move16();
     489             :     }
     490             :     ELSE
     491             :     {
     492      693673 :         *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction );
     493      693673 :         move16();
     494             :     }
     495             : }
     496             : 
     497             : 
     498         933 : 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         933 :     Flag Overflow = 0;
     504         933 :     move32();
     505             : #endif
     506             : 
     507             : 
     508         933 :     s1 = sub( getScaleFactor16( speech, L_frame ), 4 );
     509         933 :     s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 );
     510             : 
     511             :     /* Find gain */
     512         933 :     corr = L_deposit_l( 0 );
     513         933 :     ener = L_deposit_l( 1 );
     514             : 
     515      286501 :     FOR( i = 0; i < L_frame; i++ )
     516             :     {
     517      285568 :         tmp = shl_sat( pred_speech[i], s2 );
     518      285568 :         corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp );
     519      285568 :         ener = L_mac0_sat( ener, tmp, tmp );
     520             :     }
     521             : 
     522         933 :     s1 = sub( 1, add( s1, s2 ) );
     523         933 :     s2 = sub( 1, shl( s2, 1 ) );
     524             : 
     525         933 :     tmp = sub( norm_l( corr ), 1 );
     526         933 :     corr = L_shl( corr, tmp );
     527         933 :     s1 = sub( s1, tmp );
     528             : 
     529         933 :     tmp = norm_l( ener );
     530         933 :     ener = L_shl( ener, tmp );
     531         933 :     s2 = sub( s2, tmp );
     532             : 
     533         933 :     g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) );
     534             :     BASOP_SATURATE_WARNING_OFF_EVS
     535         933 :     g = shl_o( g, sub( s1, s2 ), &Overflow );
     536             :     BASOP_SATURATE_WARNING_ON_EVS
     537             : 
     538             :     /* Quantize gain */
     539         933 :     g = shr( sub_o( g, 0x1000, &Overflow ), 13 );
     540         933 :     g = s_max( g, -1 );
     541             : 
     542         933 :     *gain_index = g;
     543         933 :     move16();
     544             : 
     545             :     /* Dequantize gain */
     546         933 :     *gain = imult1616( add( g, 1 ), 0x1400 );
     547         933 :     move16();
     548         933 : }
     549             : 
     550      859238 : 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      859238 :     Flag Overflow = 0;
     556      859238 :     move32();
     557             : #endif
     558             : 
     559      859238 :     s1 = sub( getScaleFactor16( speech, L_frame ), 4 );
     560      859238 :     s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 );
     561             : 
     562             :     /* Find gain */
     563      859238 :     corr = L_deposit_l( 0 );
     564      859238 :     ener = L_deposit_l( 1 );
     565             : 
     566   265528998 :     FOR( i = 0; i < L_frame; i++ )
     567             :     {
     568   264669760 :         tmp = shl_sat( pred_speech[i], s2 );                  // Qx + s2
     569   264669760 :         corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp ); // 2*Qx + s1 + s2
     570   264669760 :         ener = L_mac0_sat( ener, tmp, tmp );                  // 2*(Qx+s2)
     571             :     }
     572             : 
     573      859238 :     s1 = sub( 1, add( s1, s2 ) );
     574      859238 :     s2 = sub( 1, shl( s2, 1 ) );
     575             : 
     576      859238 :     tmp = sub( norm_l( corr ), 1 );
     577      859238 :     corr = L_shl( corr, tmp );
     578      859238 :     s1 = sub( s1, tmp );
     579             : 
     580      859238 :     tmp = norm_l( ener );
     581      859238 :     ener = L_shl( ener, tmp );
     582      859238 :     s2 = sub( s2, tmp );
     583             : 
     584      859238 :     g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) );
     585             :     BASOP_SATURATE_WARNING_OFF_EVS
     586      859238 :     g = shl_o( g, sub( s1, s2 ), &Overflow ); /*Q15*/
     587             :     BASOP_SATURATE_WARNING_ON_EVS
     588             : 
     589             :     /* Quantize gain */
     590      859238 :     g = shr_sat( sub_sat( g /*Q15*/, 0x1000 ), 13 ); // Q0
     591      859238 :     g = s_max( g, -1 );
     592             : 
     593      859238 :     *gain_index = g;
     594      859238 :     move16();
     595             : 
     596             :     /* Dequantize gain */
     597      859238 :     *gain = imult1616( add( g, 1 ), 0x1400 ); /*Q15*/
     598      859238 :     move16();
     599      859238 : }
     600             : 
     601        1310 : 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        1310 :     Flag Overflow = 0;
     640        1310 :     move32();
     641             : #endif
     642             : 
     643             : 
     644        1310 :     norm_corr = 0;
     645        1310 :     move16();
     646             : 
     647             :     /* Reset memory if past frame is acelp */
     648        1310 :     IF( last_core == ACELP_CORE )
     649             :     {
     650         617 :         *pitch_int_past = L_frame;
     651         617 :         move16();
     652         617 :         *pitch_fr_past = 0;
     653         617 :         move16();
     654         617 :         *gain_past = 0;
     655         617 :         move16();
     656             :     }
     657             : 
     658             :     /* By default, LTP is off */
     659        1310 :     ltp_param[0] = 0;
     660        1310 :     move16();
     661             : 
     662        1310 :     test();
     663        1310 :     IF( tcxltp_on != 0 || SideInfoOnly != 0 )
     664             :     {
     665             :         Word16 nPrevSubblocks;
     666        1310 :         Word8 isTCX10 = 0;
     667             : 
     668        1310 :         if ( EQ_16( tcxMode, TCX_10 ) )
     669             :         {
     670           0 :             isTCX10 = 1;
     671           0 :             move16();
     672             :         }
     673             : 
     674             :         /* Find pitch lag */
     675        1310 :         tcx_ltp_pitch_search( Top, pitch_int, pitch_fr, &ltp_param[1], &norm_corr, L_frame, wsp, pitmin, pitfr1, pitfr2, pitmax, pitres );
     676             : 
     677        1310 :         nPrevSubblocks = extract_h( L_mac( 0x17fff, NSUBBLOCKS, div_s( *pitch_int, L_frame ) ) );
     678        1310 :         nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 );
     679             : 
     680        1310 :         tempFlatness = GetTCXAvgTemporalFlatnessMeasure_fx( pTransientDetection, NSUBBLOCKS, nPrevSubblocks );
     681             : 
     682        1310 :         maxEnergyChange = GetTCXMaxenergyChange_fx( pTransientDetection,
     683             :                                                     (const Word8) isTCX10,
     684             :                                                     NSUBBLOCKS, nPrevSubblocks );
     685             : 
     686             :         /* Switch LTP on */
     687        1310 :         test();
     688        1310 :         test();
     689        1310 :         test();
     690        1310 :         test();
     691        1310 :         test();
     692        1310 :         test();
     693        1310 :         test();
     694        1310 :         test();
     695        1310 :         test();
     696        1310 :         test();
     697        1310 :         test();
     698        1310 :         test();
     699        1310 :         test();
     700        1310 :         test();
     701        1310 :         test();
     702        1310 :         test();
     703             :         BASOP_SATURATE_WARNING_OFF_EVS;
     704        1310 :         if ( (
     705        1310 :                  tcxOnly == 0 &&
     706        2620 :                  EQ_16( tcxMode, TCX_20 ) &&
     707        2317 :                  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         377 :                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         377 :                ) ||
     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         933 :             ltp_param[0] = 1;
     726         933 :             move16();
     727             :         }
     728             :         BASOP_SATURATE_WARNING_ON_EVS;
     729             :     }
     730             : 
     731        1310 :     IF( ltp_param[0] != 0 )
     732             :     {
     733             :         /* Find predicted signal */
     734         933 :         predict_signal( speech, pred_speech, *pitch_int, *pitch_fr, pitres, L_frame );
     735             : 
     736             :         /* Find gain */
     737         933 :         tcx_ltp_find_gain( speech, pred_speech, L_frame, gain, &ltp_param[2] );
     738             : 
     739             :         /* Total number of bits for LTP */
     740         933 :         IF( NE_16( ltp_param[2], -1 ) ) /* gain > 0 */
     741             :         {
     742         933 :             *ltp_bits = 12;
     743         933 :             move16();
     744             :         }
     745             :         ELSE /* gain <= 0 -> turn off LTP */
     746             :         {
     747           0 :             ltp_param[0] = 0;
     748           0 :             move16();
     749             :         }
     750             :     }
     751             : 
     752        1310 :     IF( ltp_param[0] == 0 )
     753             :     {
     754             :         /* No LTP -> set everything to zero */
     755         377 :         *pitch_int = L_frame;
     756         377 :         move16();
     757         377 :         *pitch_fr = 0;
     758         377 :         move16();
     759         377 :         ltp_param[1] = 0;
     760         377 :         move16();
     761         377 :         set16_fx( pred_speech, 0, L_frame );
     762         377 :         *gain = 0;
     763         377 :         move16();
     764         377 :         ltp_param[2] = 0;
     765         377 :         move16();
     766             : 
     767         377 :         *ltp_bits = 0;
     768         377 :         move16();
     769         377 :         test();
     770         377 :         IF( tcxltp_on != 0 || SideInfoOnly != 0 )
     771             :         {
     772         377 :             *ltp_bits = 1;
     773         377 :             move16();
     774             :         }
     775             :     }
     776             : 
     777        1310 :     IF( SideInfoOnly != 0 )
     778             :     {
     779           0 :         *gain = 0;
     780           0 :         move16();
     781             :     }
     782             : 
     783        1310 :     test();
     784        1310 :     IF( *gain_past == 0 && *gain == 0 )
     785             :     {
     786         300 :         Copy( speech, speech_ltp, L_subfr );
     787             :     }
     788        1010 :     ELSE IF( *gain_past == 0 )
     789             :     {
     790         536 :         alpha = 0;
     791         536 :         move16();
     792             : 
     793             :         /* step = 1.f/(float)(L_subfr); */
     794         536 :         step = shl( 2, norm_s( L_subfr ) );
     795         536 :         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       34840 :         FOR( n = 0; n < L_subfr; n++ )
     801             :         {
     802       34304 :             speech_ltp[n] = sub_o( speech[n], mult_ro( *gain, mult_ro( alpha, pred_speech[n], &Overflow ), &Overflow ), &Overflow );
     803       34304 :             move16();
     804             :             BASOP_SATURATE_WARNING_OFF_EVS;
     805       34304 :             alpha = add_o( alpha, step, &Overflow );
     806             :             BASOP_SATURATE_WARNING_ON_EVS;
     807             :         }
     808             :     }
     809             :     ELSE
     810             :     {
     811         474 :         IF( A == NULL )
     812             :         {
     813           0 :             tcx_ltp_get_lpc( speech - L_frame, L_frame, Aest, lpcorder );
     814           0 :             A = Aest;
     815             :         }
     816             : 
     817         474 :         IF( *gain > 0 )
     818             :         {
     819         397 :             predict_signal( speech - lpcorder, buf_zir, *pitch_int, *pitch_fr, pitres, lpcorder );
     820             :         }
     821             :         ELSE
     822             :         {
     823          77 :             set16_fx( buf_zir, 0, lpcorder );
     824             :         }
     825             : 
     826        8058 :         FOR( n = 0; n < lpcorder; n++ )
     827             :         {
     828        7584 :             buf_zir[n] = add_sat( sub_sat( speech_ltp[n - lpcorder], speech[n - lpcorder] ), mult_r( *gain, buf_zir[n] ) );
     829        7584 :             move16();
     830             :         }
     831             : 
     832         474 :         zir = buf_zir + lpcorder;
     833             : 
     834         474 :         set16_fx( zir, 0, L_subfr );
     835             : 
     836         474 :         E_UTIL_synthesis( 0, A, zir, zir, L_subfr, buf_zir, 0, lpcorder );
     837             : 
     838         474 :         alpha = 0x7FFF;
     839         474 :         move16();
     840             :         /* step = 1.f/(float)(L_subfr/2); */
     841         474 :         step = shl( 4, norm_s( L_subfr ) );
     842         474 :         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       15642 :         FOR( n = ( L_subfr >> 1 ); n < L_subfr; n++ )
     848             :         {
     849       15168 :             zir[n] = mult_r( zir[n], alpha );
     850       15168 :             move16();
     851       15168 :             alpha = sub( alpha, step );
     852             :         }
     853             : 
     854       30810 :         FOR( n = 0; n < L_subfr; n++ )
     855             :         {
     856       30336 :             speech_ltp[n] = add_o( sub_o( speech[n], mult_ro( *gain, pred_speech[n], &Overflow ), &Overflow ), zir[n], &Overflow );
     857       30336 :             move16();
     858             :         }
     859             :     }
     860             : 
     861        1310 :     test();
     862        1310 :     IF( SideInfoOnly || *gain == 0 )
     863             :     {
     864       93241 :         FOR( n = L_subfr; n < L_frame; n++ )
     865             :         {
     866       92864 :             speech_ltp[n] = speech[n];
     867       92864 :             move16();
     868             :         }
     869             :     }
     870             :     ELSE
     871             :     {
     872      226789 :         FOR( n = L_subfr; n < L_frame; n++ )
     873             :         {
     874      225856 :             speech_ltp[n] = sub_o( speech[n], mult( *gain, pred_speech[n] ), &Overflow );
     875      225856 :             move16();
     876             :         }
     877             :     }
     878             : 
     879             :     /* Update */
     880        1310 :     *pitch_int_past = *pitch_int;
     881        1310 :     move16();
     882        1310 :     *pitch_fr_past = *pitch_fr;
     883        1310 :     move16();
     884        1310 :     *gain_past = *gain;
     885        1310 :     move16();
     886        1310 :     *norm_corr_past = norm_corr;
     887        1310 :     move16();
     888        1310 : }
     889             : 
     890      859238 : 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      859238 :     Flag Overflow = 0;
     918      859238 :     move32();
     919             : 
     920      859238 :     TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc;
     921             : 
     922      859238 :     tcxOnly = st->tcxonly;
     923      859238 :     move16();
     924      859238 :     L_subfr = L_SUBFR;
     925      859238 :     move16();
     926      859238 :     SideInfoOnly = extract_l( GT_32( st->sr_core, 25600 ) );
     927      859238 :     move16();
     928             : 
     929             :     /* Reset memory if past frame is acelp */
     930      859238 :     IF( st->last_core == ACELP_CORE )
     931             :     {
     932        9217 :         hTcxEnc->tcxltp_pitch_int_past = L_frame;
     933        9217 :         move16();
     934        9217 :         hTcxEnc->tcxltp_pitch_fr_past = 0;
     935        9217 :         move16();
     936        9217 :         hTcxEnc->tcxltp_gain_past = 0;
     937        9217 :         move16();
     938             :     }
     939             : 
     940             :     /* By default, LTP is off */
     941      859238 :     ltp_param[0] = 0;
     942      859238 :     move16();
     943      859238 :     norm_corr_fx = 0;
     944      859238 :     move16();
     945      859238 :     border_case = 0;
     946      859238 :     move16();
     947             : 
     948      859238 :     test();
     949      859238 :     IF( hTcxEnc->tcxltp || SideInfoOnly )
     950             :     {
     951             :         Word16 nPrevSubblocks;
     952      859238 :         Word8 isTCX10 = 0;
     953      859238 :         move16();
     954             : 
     955             :         /* Find pitch lag */
     956      859238 :         IF( EQ_16( st->pit_res_max, 6 ) )
     957             :         {
     958      173912 :             delta = 8;
     959      173912 :             move16();
     960             :         }
     961             :         ELSE
     962             :         {
     963      685326 :             delta = 16;
     964      685326 :             move16();
     965             :         }
     966             : 
     967      859238 :         IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) )
     968             :         {
     969      623459 :             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      438696 :                 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      554289 :                 FOR( i = 0; i < 2; i++ )
     983             :                 {
     984      369526 :                     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      184763 :                 IF( GT_16( norm_corr_2_fx[1], norm_corr_2_fx[0] ) )
     988             :                 {
     989      119537 :                     i = 1;
     990             :                 }
     991             :                 ELSE
     992             :                 {
     993       65226 :                     i = 0;
     994             :                 }
     995      184763 :                 move16();
     996             : 
     997      184763 :                 hTcxEnc->tcxltp_pitch_int = pitch_int_2[i];
     998      184763 :                 move16();
     999      184763 :                 hTcxEnc->tcxltp_pitch_fr = pitch_fr_2[i];
    1000      184763 :                 move16();
    1001      184763 :                 ltp_param[1] = pit_param_2[i];
    1002      184763 :                 move16();
    1003      184763 :                 norm_corr_fx = norm_corr_2_fx[i];
    1004      184763 :                 move16();
    1005             :             }
    1006             :         }
    1007             :         ELSE
    1008             :         {
    1009             :             Word16 tmp;
    1010      235779 :             IF( GT_16( element_mode, EVS_MONO ) )
    1011             :             {
    1012      235779 :                 tmp = 1;
    1013             :             }
    1014             :             ELSE
    1015             :             {
    1016           0 :                 tmp = 0;
    1017             :             }
    1018      235779 :             move16();
    1019      235779 :             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      859238 :         if ( border_case )
    1023             :         {
    1024       79783 :             norm_corr_fx = 0;
    1025       79783 :             move16();
    1026             :         }
    1027             : 
    1028             :         // nPrevSubblocks = ( 1 + min( NSUBBLOCKS, (int16_t) ceil( 0.5f + NSUBBLOCKS * ( 1.0f * ( hTcxEnc->tcxltp_pitch_int ) / L_frame ) ) ) );
    1029      859238 :         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      859238 :         nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 );
    1031             : 
    1032      859238 :         IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) )
    1033             :         {
    1034       14464 :             tempFlatness_fx = extract_l( L_shr( GetTCXAvgTemporalFlatnessMeasure_ivas_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ), 14 ) ); // Q7
    1035       14464 :             maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10,
    1036       14464 :                                                                 NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q3
    1037             :         }
    1038             :         ELSE
    1039             :         {
    1040      844774 :             tempFlatness_fx = extract_l( L_shr( ( GetTCXAvgTemporalFlatnessMeasure_ivas_fx( (const TransientDetection *) st->hTranDet, NSUBBLOCKS, nPrevSubblocks ) ), 14 ) ); // Q7
    1041      844774 :             maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10,
    1042             :                                                                 NSUBBLOCKS, nPrevSubblocks ); // Q3
    1043             :         }
    1044             : 
    1045             :         /* Switch LTP on */
    1046      859238 :         test();
    1047      859238 :         test();
    1048      859238 :         test();
    1049      859238 :         test();
    1050      859238 :         test();
    1051      859238 :         test();
    1052      859238 :         test();
    1053      859238 :         test();
    1054      859238 :         test();
    1055      859238 :         test();
    1056      859238 :         test();
    1057      859238 :         test();
    1058      859238 :         test();
    1059      859238 :         test();
    1060      859238 :         test();
    1061      859238 :         test();
    1062      859238 :         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      519955 :             IF( disable_ltp == 0 )
    1084             :             {
    1085      519915 :                 ltp_param[0] = 1;
    1086      519915 :                 move16();
    1087             :             }
    1088             :         }
    1089             : 
    1090             :         /* hysteresis for stable ltp prediction */
    1091      859238 :         ltp_on = 0;
    1092      859238 :         move16();
    1093             : 
    1094      859238 :         test();
    1095      859238 :         test();
    1096      859238 :         test();
    1097      859238 :         test();
    1098      859238 :         test();
    1099             : 
    1100      859238 :         exponent = 15;
    1101      859238 :         move16();
    1102      859238 :         sqr = Sqrt16( hTcxEnc->tcxltp_on_mem, &exponent );
    1103      859238 :         move16();
    1104      859238 :         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      400012 :             ltp_on = 1;
    1107      400012 :             move16();
    1108             :         }
    1109             : 
    1110      859238 :         test();
    1111      859238 :         IF( EQ_16( tcxOnly, 1 ) && EQ_16( ltp_param[0], 1 ) )
    1112             :         {
    1113             :             /* increase ltp counter */
    1114      459300 :             hTcxEnc->tcxltp_on_mem = s_min( 5, add( hTcxEnc->tcxltp_on_mem, 1 ) );
    1115      459300 :             move16();
    1116             :         }
    1117      399938 :         ELSE IF( EQ_16( ltp_on, 1 ) )
    1118             :         {
    1119             :             /* hysteresis takes effect, decrease counter */
    1120       44936 :             hTcxEnc->tcxltp_on_mem = s_max( 0, sub( hTcxEnc->tcxltp_on_mem, 1 ) );
    1121       44936 :             move16();
    1122       44936 :             ltp_param[0] = ltp_on;
    1123       44936 :             move16();
    1124             :         }
    1125             :         ELSE
    1126             :         {
    1127             :             /* no ltp in this frame, reset counter */
    1128      355002 :             hTcxEnc->tcxltp_on_mem = 0;
    1129      355002 :             move16();
    1130             :         }
    1131             :     }
    1132             : 
    1133             :     /* Find predicted signal */
    1134      859238 :     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      859238 :     tcx_ltp_find_gain_ivas_fx( speech_fx, pred_speech_fx, L_frame, &hTcxEnc->tcxltp_gain, &ltp_param[2] );
    1138             : 
    1139      859238 :     IF( ltp_param[0] )
    1140             :     {
    1141             :         /* Total number of bits for LTP */
    1142      564851 :         IF( add( ltp_param[2], 1 ) ) /* hTcxEnc->tcxltp_gain > 0 */
    1143             :         {
    1144      564781 :             *ltp_bits = 12;
    1145      564781 :             move16();
    1146             :         }
    1147             :         ELSE /* hTcxEnc->tcxltp_gain <= 0 -> turn off LTP */
    1148             :         {
    1149          70 :             ltp_param[0] = 0;
    1150          70 :             move16();
    1151             :         }
    1152             :     }
    1153             : 
    1154      859238 :     IF( !ltp_param[0] )
    1155             :     {
    1156             :         /* No LTP -> set everything to zero */
    1157      294457 :         hTcxEnc->tcxltp_pitch_int = L_frame;
    1158      294457 :         move16();
    1159      294457 :         hTcxEnc->tcxltp_pitch_fr = 0;
    1160      294457 :         move16();
    1161      294457 :         ltp_param[1] = 0;
    1162      294457 :         move16();
    1163      294457 :         set16_fx( pred_speech_fx, 0, L_frame );
    1164      294457 :         hTcxEnc->tcxltp_gain = 0;
    1165      294457 :         move16();
    1166      294457 :         ltp_param[2] = 0;
    1167      294457 :         move16();
    1168             : 
    1169      294457 :         test();
    1170      294457 :         IF( hTcxEnc->tcxltp || SideInfoOnly )
    1171             :         {
    1172      294457 :             *ltp_bits = 1;
    1173      294457 :             move16();
    1174             :         }
    1175             :         ELSE
    1176             :         {
    1177           0 :             *ltp_bits = 0;
    1178           0 :             move16();
    1179             :         }
    1180             :     }
    1181             : 
    1182      859238 :     si_gain_fx = 0;
    1183      859238 :     move16();
    1184             : 
    1185      859238 :     IF( SideInfoOnly )
    1186             :     {
    1187      420681 :         si_gain_fx = hTcxEnc->tcxltp_gain;
    1188      420681 :         move16();
    1189      420681 :         hTcxEnc->tcxltp_gain = 0;
    1190      420681 :         move16();
    1191             :     }
    1192             : 
    1193      859238 :     IF( speech_ltp_fx != NULL )
    1194             :     {
    1195      221315 :         test();
    1196      221315 :         IF( hTcxEnc->tcxltp_gain_past == 0 && hTcxEnc->tcxltp_gain == 0 )
    1197             :         {
    1198      150646 :             Copy( speech_fx, speech_ltp_fx, L_subfr );
    1199             :         }
    1200       70669 :         ELSE IF( hTcxEnc->tcxltp_gain_past == 0 )
    1201             :         {
    1202       11517 :             alpha_fx = 0;
    1203       11517 :             move16();
    1204             : 
    1205       11517 :             step_fx = shl( 2, norm_s( L_subfr ) );
    1206       11517 :             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      748605 :             FOR( n = 0; n < L_subfr; n++ )
    1212             :             {
    1213      737088 :                 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      737088 :                 move16();
    1215      737088 :                 alpha_fx = add_sat( alpha_fx, step_fx );
    1216             :             }
    1217             :         }
    1218             :         ELSE
    1219             :         {
    1220       59152 :             IF( A_fx == NULL )
    1221             :             {
    1222       59152 :                 tcx_ltp_get_lpc( speech_fx - L_frame, L_frame, Aest_fx, M );
    1223       59152 :                 A_fx = Aest_fx;
    1224             :             }
    1225             : 
    1226       59152 :             IF( hTcxEnc->tcxltp_gain > 0 )
    1227             :             {
    1228       50195 :                 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        8957 :                 set16_fx( buf_zir_fx, 0, M );
    1233             :             }
    1234             : 
    1235     1005584 :             FOR( n = 0; n < M; n++ )
    1236             :             {
    1237      946432 :                 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      946432 :                 move16();
    1239             :             }
    1240             : 
    1241       59152 :             zir_fx = buf_zir_fx + M;
    1242       59152 :             set16_fx( zir_fx, 0, L_subfr );
    1243             : 
    1244       59152 :             Syn_filt_s( 0, A_fx, M, zir_fx, zir_fx, L_subfr, buf_zir_fx, 0 );
    1245             : 
    1246       59152 :             alpha_fx = 0x7FFF; // 1.f Q15
    1247       59152 :             move16();
    1248       59152 :             step_fx = shl( 4, norm_s( L_subfr ) );
    1249       59152 :             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     1952016 :             FOR( n = L_subfr >> 1; n < L_subfr; n++ )
    1255             :             {
    1256     1892864 :                 zir_fx[n] = mult_r( zir_fx[n], alpha_fx );
    1257     1892864 :                 move16();
    1258     1892864 :                 alpha_fx = sub( alpha_fx, step_fx );
    1259             :             }
    1260             : 
    1261     3844880 :             FOR( n = 0; n < L_subfr; n++ )
    1262             :             {
    1263     3785728 :                 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     3785728 :                 move16();
    1265             :             }
    1266             :         }
    1267             : 
    1268      221315 :         test();
    1269      221315 :         IF( SideInfoOnly || hTcxEnc->tcxltp_gain == 0 )
    1270             :         {
    1271    71903731 :             FOR( n = L_subfr; n < L_frame; n++ )
    1272             :             {
    1273    71744128 :                 speech_ltp_fx[n] = speech_fx[n];
    1274    71744128 :                 move16();
    1275             :             }
    1276             :         }
    1277             :         ELSE
    1278             :         {
    1279    14893712 :             FOR( n = L_subfr; n < L_frame; n++ )
    1280             :             {
    1281    14832000 :                 speech_ltp_fx[n] = sub_o( speech_fx[n], mult( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ), &Overflow );
    1282    14832000 :                 move16();
    1283             :             }
    1284             :         }
    1285             :     }
    1286             : 
    1287             :     /* Update */
    1288      859238 :     hTcxEnc->tcxltp_pitch_int_past = hTcxEnc->tcxltp_pitch_int;
    1289      859238 :     move16();
    1290      859238 :     hTcxEnc->tcxltp_pitch_fr_past = hTcxEnc->tcxltp_pitch_fr;
    1291      859238 :     move16();
    1292      859238 :     hTcxEnc->tcxltp_gain_past = hTcxEnc->tcxltp_gain;
    1293      859238 :     move16();
    1294             : 
    1295      859238 :     IF( SideInfoOnly )
    1296             :     {
    1297      420681 :         hTcxEnc->tcxltp_gain = si_gain_fx;
    1298      420681 :         move16();
    1299             :     }
    1300             : 
    1301      859238 :     hTcxEnc->tcxltp_norm_corr_past = norm_corr_fx;
    1302      859238 :     move16();
    1303             : 
    1304      859238 :     return;
    1305             : }

Generated by: LCOV version 1.14