LCOV - code coverage report
Current view: top level - lib_enc - lp_exc_e_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ b9bfbe380d1c207f5198ba67a82398b3d313550e Lines: 155 170 91.2 %
Date: 2025-11-14 01:07:58 Functions: 3 3 100.0 %

          Line data    Source code
       1             : /*====================================================================================
       2             :     EVS Codec 3GPP TS26.452 Aug 12, 2021. Version 16.3.0
       3             :   ====================================================================================*/
       4             : 
       5             : #include <stdint.h>
       6             : #include "options.h" /* Compilation switches                   */
       7             : #include "cnst.h"    /* Common constants                       */
       8             : #include "basop_util.h"
       9             : #include "prot_fx.h"     /* Function prototypes                    */
      10             : #include "prot_fx_enc.h" /* Function prototypes                    */
      11             : 
      12             : /*-------------------------------------------------------------------*
      13             :  * Local constants
      14             :  *-------------------------------------------------------------------*/
      15             : 
      16             : #define GAIN_PIT_MAX 19661
      17             : 
      18             : 
      19             : /*-------------------------------------------------------------------*
      20             :  * Local function prototypes
      21             :  *-------------------------------------------------------------------*/
      22             : 
      23             : static Word16 adpt_enr_fx( const Word16 codec_mode, const Word16 *exc, const Word16 *h1, Word16 *y1, const Word16 L_subfr, Word16 *gain, Word16 *g_corr, const Word16 clip_gain, const Word16 *xn, Word16 *xn2, Word16 *exp_ener, Word16 use_prev_sf_pit_gain );
      24             : 
      25             : /*-------------------------------------------------------------------*
      26             :  * function lp_filt_exc_enc_fx()
      27             :  *
      28             :  * Low-pass filtering of the adaptive excitation
      29             :  * Innovation target construction
      30             :  * Gain quantization limitation
      31             :  *-------------------------------------------------------------------*/
      32             : 
      33      727882 : Word16 lp_filt_exc_enc_fx(
      34             :     const Word16 codec_mode, /* i  : MODE1 or MODE2                                  Q0 */
      35             :     const Word16 coder_type, /* i  : coding type                                     Q0 */
      36             :     const Word16 i_subfr,    /* i  : subframe index                                  Q0 */
      37             :     Word16 *exc,             /* i/o: pointer to excitation signal frame              Q_new */
      38             :     const Word16 *h1,        /* i  : weighted filter input response                  Q(14+shift) */
      39             :     const Word16 *xn,        /* i  : target vector                                   Q_new-1+shift */
      40             :     Word16 *y1,              /* o  : zero-memory filtered adaptive excitation        Q_new-1+shift */
      41             :     Word16 *xn2,             /* o  : target vector for innovation search             Q_new-1+shift */
      42             :     const Word16 L_subfr,    /* i  : length of vectors for gain quantization         Q0 */
      43             :     const Word16 L_frame,    /* i  : frame size                                      Q0 */
      44             :     Word16 *g_corr,          /* o  : ACELP correlation values                        mant/exp */
      45             :     const Word16 clip_gain,  /* i  : adaptive gain clipping flag                     Q0 */
      46             :     Word16 *gain_pit,        /* o  : adaptive excitation gain                        Q14 */
      47             :     Word16 *lp_flag          /* i/o: mode selection                                  Q0 */
      48             : )
      49             : {
      50             :     Word16 gain1, gain2, g_corr2[4], exc_tmp[5 * L_SUBFR], xn2_tmp[5 * L_SUBFR];
      51             :     Word16 y1_tmp[5 * L_SUBFR];
      52             :     Word16 select, i, exp_ener, exp_ener1;
      53             :     Word16 wtmp, wtmp1;
      54             :     Word32 Ltmp;
      55             : 
      56      727882 :     Word16 use_prev_sf_pit_gain = 0; // Q0
      57      727882 :     move16();
      58             : 
      59      727882 :     gain1 = 0;
      60      727882 :     move16();
      61      727882 :     gain2 = 0;
      62      727882 :     move16();
      63             : 
      64             :     /*----------------------------------------------------------------*
      65             :      * Find the target energy if the adaptive exc. is not filtered
      66             :      *----------------------------------------------------------------*/
      67      727882 :     test();
      68      727882 :     IF( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, 100 ) )
      69             :     {
      70           0 :         use_prev_sf_pit_gain = 1; // Q0
      71           0 :         move16();
      72             :     }
      73      727882 :     exp_ener = 0;
      74      727882 :     move16();
      75      727882 :     wtmp = 0;
      76      727882 :     move16();
      77      727882 :     test();
      78      727882 :     IF( EQ_16( *lp_flag, FULL_BAND ) || EQ_16( *lp_flag, NORMAL_OPERATION ) )
      79             :     {
      80      683264 :         wtmp = adpt_enr_fx( codec_mode, &exc[i_subfr], h1, y1, L_subfr, &gain1, g_corr, clip_gain, xn, xn2, &exp_ener, use_prev_sf_pit_gain ); // exp_ener
      81      683264 :         move16();
      82             :     }
      83             : 
      84             :     /*----------------------------------------------------------------*
      85             :      * Filter the adaptive excitation
      86             :      * Find the target energy if the adapt. exc. is filtered
      87             :      *----------------------------------------------------------------*/
      88             : 
      89      727882 :     exp_ener1 = 0;
      90      727882 :     move16();
      91      727882 :     wtmp1 = 0;
      92      727882 :     move16();
      93      727882 :     test();
      94      727882 :     IF( ( ( *lp_flag == LOW_PASS ) ) || ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) )
      95             :     {
      96      657282 :         test();
      97      657282 :         IF( EQ_16( codec_mode, MODE2 ) && EQ_16( L_frame, L_FRAME16k ) )
      98             :         {
      99           0 :             FOR( i = 0; i < L_subfr; i++ )
     100             :             {
     101           0 :                 Ltmp = L_mult( 6881, exc[i - 1 + i_subfr] ); /* constants in Q15 */
     102           0 :                 Ltmp = L_mac( Ltmp, 19005, exc[i + i_subfr] );
     103           0 :                 Ltmp = L_mac( Ltmp, 6881, exc[i + 1 + i_subfr] );
     104           0 :                 exc_tmp[i] = round_fx( Ltmp );
     105           0 :                 move16();
     106             :             }
     107             :         }
     108             :         ELSE
     109             :         {
     110    42723330 :             FOR( i = 0; i < L_subfr; i++ )
     111             :             {
     112    42066048 :                 Ltmp = L_mult( 5898, exc[i - 1 + i_subfr] ); /* constants in Q15 */
     113    42066048 :                 Ltmp = L_mac( Ltmp, 20972, exc[i + i_subfr] );
     114    42066048 :                 Ltmp = L_mac( Ltmp, 5898, exc[i + 1 + i_subfr] );
     115    42066048 :                 exc_tmp[i] = round_fx( Ltmp );
     116    42066048 :                 move16();
     117             :             }
     118             :         }
     119             : 
     120      657282 :         wtmp1 = adpt_enr_fx( codec_mode, exc_tmp, h1, y1_tmp, L_subfr, &gain2, g_corr2, clip_gain, xn, xn2_tmp, &exp_ener1, use_prev_sf_pit_gain ); // exp_ener1
     121             :     }
     122             : 
     123      727882 :     if ( LT_16( exp_ener, exp_ener1 ) )
     124             :     {
     125       52845 :         wtmp = shr( wtmp, 1 ); // exp_ener + 1
     126             :     }
     127             : 
     128      727882 :     if ( GT_16( exp_ener, exp_ener1 ) )
     129             :     {
     130       93382 :         wtmp1 = shr( wtmp1, 1 ); // exp_ener1 + 1
     131             :     }
     132             : 
     133             :     /*-----------------------------------------------------------------*
     134             :      * use the best prediction (minimize quadratic error)
     135             :      *-----------------------------------------------------------------*/
     136             : 
     137      727882 :     test();
     138      727882 :     test();
     139      727882 :     IF( ( ( LT_16( wtmp1, wtmp ) ) && ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) ) || ( ( *lp_flag == LOW_PASS ) ) )
     140             :     {
     141             :         /* use the LP filter for pitch excitation prediction */
     142      445835 :         select = LOW_PASS;
     143      445835 :         move16();
     144      445835 :         Copy( exc_tmp, &exc[i_subfr], L_subfr ); // Q_new
     145      445835 :         Copy( y1_tmp, y1, L_subfr );             // Q_new-1+shift
     146      445835 :         Copy( xn2_tmp, xn2, L_subfr );           // Q_new-1+shift
     147             : 
     148      445835 :         IF( use_prev_sf_pit_gain == 0 )
     149             :         {
     150      445835 :             *gain_pit = gain2; // Q14
     151      445835 :             move16();
     152      445835 :             g_corr[0] = g_corr2[0];
     153      445835 :             move16();
     154      445835 :             g_corr[1] = g_corr2[1];
     155      445835 :             move16();
     156      445835 :             g_corr[2] = g_corr2[2];
     157      445835 :             move16();
     158      445835 :             g_corr[3] = g_corr2[3];
     159      445835 :             move16();
     160             :         }
     161             :     }
     162             :     ELSE
     163             :     {
     164             :         /* no LP filter used for pitch excitation prediction */
     165      282047 :         select = FULL_BAND;
     166      282047 :         move16();
     167      282047 :         IF( use_prev_sf_pit_gain == 0 )
     168             :         {
     169      282047 :             *gain_pit = gain1; // Q14
     170      282047 :             move16();
     171             :         }
     172             :     }
     173             : 
     174      727882 :     return select;
     175             : }
     176             : 
     177             : /*-------------------------------------------------------------------*
     178             :  * adpt_enr_fx()
     179             :  *
     180             :  * Find  adaptive excitation energy
     181             :  * This serves to decide about the filtering of the adaptive excitation
     182             :  *-------------------------------------------------------------------*/
     183             : 
     184             : /* o  : adaptive excitation energy             mant     */
     185     1340546 : static Word16 adpt_enr_fx(
     186             :     const Word16 codec_mode,    /* i  : MODE1 or MODE2                                  */
     187             :     const Word16 *exc,          /* i  : excitation vector                      Q_new    */
     188             :     const Word16 *h1,           /* i  : impuls response                        Q15      */
     189             :     Word16 *y1,                 /* o  : zero-memory filtered adpt. excitation  12 bits  */
     190             :     const Word16 L_subfr,       /* i  : vector length                                   */
     191             :     Word16 *gain,               /* o  : subframe adaptive gain                 Q14      */
     192             :     Word16 *g_corr,             /* o  : correlations for adptive gain          mant/exp */
     193             :     const Word16 clip_gain,     /* i  : adaptive gain clipping flag            Q0       */
     194             :     const Word16 *xn,           /* i  : adaptive codebook target               12 bits Q_new-1+shift*/
     195             :     Word16 *xn2,                /* o  : algebraic codebook target              12 bits Q_new-1+shift*/
     196             :     Word16 *exp_ener,           /* o  : adaptive excitation energy             exp      */
     197             :     Word16 use_prev_sf_pit_gain /* i : flag to use prev sf pitch gain or not            */
     198             : )
     199             : {
     200             :     Word16 ener, i;
     201             :     Word16 exc_tmp[L_FRAME16k], xn_tmp[L_FRAME16k];
     202             :     Word32 Ltmp;
     203     1340546 :     Flag Overflow = 0;
     204             : 
     205     1340546 :     Overflow = 0;
     206     1340546 :     move16();
     207     1340546 :     Overflow =
     208     1340546 :         conv_fx( exc, h1, y1, L_subfr );
     209             : 
     210     1340546 :     IF( use_prev_sf_pit_gain == 0 )
     211             :     {
     212     1340546 :         *gain = corr_xy1_fx( xn, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
     213     1340546 :         move16();
     214             : 
     215     1340546 :         test();
     216     1340546 :         IF( GT_16( L_subfr, L_SUBFR ) && Overflow )
     217             :         {
     218      436908 :             FOR( i = 0; i < L_subfr; i++ )
     219             :             {
     220      435328 :                 exc_tmp[i] = mult( exc[i], 8192 /*0.25.Q15*/ ); // Q_new
     221      435328 :                 move16();
     222      435328 :                 xn_tmp[i] = mult( xn[i], 8192 /*0.25.Q15*/ ); // Q_new
     223      435328 :                 move16();
     224             :             }
     225        1580 :             Overflow = 0;
     226             : 
     227        1580 :             conv_fx( exc_tmp, h1, y1, L_subfr );
     228        1580 :             *gain = corr_xy1_fx( xn_tmp, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
     229        1580 :             move16();
     230             :         }
     231             : 
     232             :         /* clip gain, if necessary to avoid problems at decoder */
     233     1340546 :         test();
     234     1340546 :         if ( EQ_16( clip_gain, 1 ) && GT_16( *gain, 15565 ) ) /* constant in Q14 */
     235             :         {
     236       13318 :             *gain = 15565; // 0.95.Q14
     237       13318 :             move16();
     238             :         }
     239             : 
     240     1340546 :         test();
     241     1340546 :         IF( EQ_16( clip_gain, 2 ) && GT_16( *gain, 10650 ) ) // 0.65.Q14
     242             :         {
     243        4468 :             *gain = 10650; // 0.65.Q14
     244        4468 :             move16();
     245             :         }
     246             :     }
     247             : 
     248             :     /* find energy of new target xn2[] */
     249     1340546 :     updt_tar_fx( xn, xn2, y1, *gain, L_subfr );
     250             : 
     251     1340546 :     IF( GT_16( L_subfr, L_SUBFR ) )
     252             :     {
     253             :         /* could possibly happen in GSC */
     254       16340 :         Ltmp = Calc_Energy_Autoscaled( xn2, 0, L_subfr, exp_ener );
     255       16340 :         i = norm_l( Ltmp );
     256       16340 :         ener = extract_h( L_shl( Ltmp, i ) ); // exp_ener
     257       16340 :         i = sub( 31, i );
     258       16340 :         *exp_ener = sub( i, *exp_ener );
     259       16340 :         move16();
     260             :     }
     261             :     ELSE
     262             :     {
     263     1324206 :         ener = extract_h( Dot_product12( xn2, xn2, L_SUBFR, exp_ener ) ); // Q15
     264             :     }
     265             : 
     266     1340546 :     return ener;
     267             : }
     268             : 
     269             : /*-------------------------------------------------------------------*
     270             :  * corr_xy1()
     271             :  *
     272             :  * Find the correlations between the target xn[] and the filtered adaptive
     273             :  * codebook excitation y1[]. ( <y1,y1>  and -2<xn,y1> )
     274             :  *-------------------------------------------------------------------*/
     275             : 
     276             : /* o  : pitch gain  (0..GAIN_PIT_MAX) */
     277     1450516 : Word16 corr_xy1_fx(
     278             :     const Word16 xn_1[],    /* i  : target signal                         Q_new*/
     279             :     const Word16 y1_1[],    /* i  : filtered adaptive codebook excitation 12 bits*/
     280             :     Word16 g_corr[],        /* o  : correlations <y1,y1>  and -2<xn,y1>   mant/exp*/
     281             :     const Word16 L_subfr,   /* i  : vector length                         */
     282             :     const Word16 norm_flag, /* i  : flag for constraining pitch contribution */
     283             :     Flag *Overflow_out      /* o :  propagating the Overflow flag to upper level */
     284             : )
     285             : {
     286             :     Word16 i;
     287             :     Word16 tmp, xx, xy, yy, exp_xy, exp_xx, exp_yy, exp_div, gain, gain_p_snr;
     288             :     Word32 Ltmp1, Ltmp2;
     289             :     Word16 xn[L_FRAME16k], y1[L_FRAME16k];
     290     1450516 :     Flag Overflow = 0;
     291             : 
     292             :     /*----------------------------------------------------------------*
     293             :      * Find the ACELP correlations and the pitch gain
     294             :      *----------------------------------------------------------------*/
     295             : 
     296             :     /* Compute scalar product <y1[],y1[]> */
     297     1450516 :     Copy( xn_1, xn, L_subfr ); // Q_new
     298     1450516 :     Copy( y1_1, y1, L_subfr );
     299     1450516 :     Overflow = 0;
     300     1450516 :     move16();
     301     1450516 :     Ltmp1 = Dot_product12_o( y1, y1, L_subfr, &exp_yy, &Overflow );
     302     1450516 :     *Overflow_out |= Overflow;
     303     1450516 :     move16();
     304     1450516 :     IF( Overflow )
     305             :     {
     306     1350958 :         FOR( i = 0; i < L_subfr; i++ )
     307             :         {
     308     1334976 :             xn[i] = mult_r( xn_1[i], 4096 /*0.125.Q15*/ ); // Q-new
     309     1334976 :             move16();
     310     1334976 :             y1[i] = mult_r( y1_1[i], 4096 /*0.125.Q15*/ );
     311     1334976 :             move16();
     312             :         }
     313             : 
     314       15982 :         Ltmp1 = Dot_product12( y1, y1, L_subfr, &exp_yy );
     315       15982 :         exp_yy = add( exp_yy, 6 );
     316       15982 :         yy = extract_h( Ltmp1 );
     317             : 
     318             :         /* Compute scalar product <xn[],y1[]> */
     319       15982 :         Ltmp2 = Dot_product12( xn, y1, L_subfr, &exp_xy );
     320       15982 :         xy = extract_h( Ltmp2 );
     321       15982 :         exp_xy = add( exp_xy, 6 );
     322             : 
     323       15982 :         g_corr[0] = yy;
     324       15982 :         move16();
     325       15982 :         g_corr[1] = exp_yy;
     326       15982 :         move16();
     327             :         /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function */
     328       15982 :         g_corr[2] = xy;
     329       15982 :         move16();
     330       15982 :         g_corr[3] = exp_xy;
     331       15982 :         move16();
     332             :     }
     333             :     ELSE
     334             :     {
     335     1434534 :         yy = extract_h( Ltmp1 ); // exp_yy
     336             :         /* Ltmp1 = L_shr(Ltmp1, sub(30, exp_yy));*/
     337             : 
     338             :         /* Compute scalar product <xn[],y1[]> */
     339     1434534 :         Ltmp2 = Dot_product12_o( xn, y1, L_subfr, &exp_xy, &Overflow );
     340     1434534 :         *Overflow_out |= Overflow;
     341     1434534 :         move16();
     342     1434534 :         xy = extract_h( Ltmp2 );
     343             :         /* Ltmp2 = L_shr(Ltmp2, sub(30, exp_xy));*/
     344             : 
     345     1434534 :         g_corr[0] = yy;
     346     1434534 :         move16();
     347     1434534 :         g_corr[1] = exp_yy;
     348     1434534 :         move16();
     349             :         /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function*/
     350     1434534 :         g_corr[2] = xy; // exp_xy
     351     1434534 :         move16();
     352     1434534 :         g_corr[3] = exp_xy;
     353     1434534 :         move16();
     354             :     }
     355             : 
     356             :     /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */
     357     1450516 :     test();
     358     1450516 :     IF( xy >= 0 && NE_16( s_or( yy, xy ), 16384 ) )
     359             :     {
     360             :         /* compute gain = xy/yy */
     361     1377533 :         xy = shr( xy, 1 );      /* be sure that xy < yy */
     362     1377533 :         gain = div_s( xy, yy ); // Q15
     363     1377533 :         i = sub( exp_xy, exp_yy );
     364     1377533 :         gain = shl_o( gain, i, &Overflow ); /* saturation can occur here */
     365     1377533 :         *Overflow_out |= Overflow;
     366     1377533 :         move16();
     367             : 
     368     1377533 :         gain = s_max( gain, 0 );
     369     1377533 :         gain = s_min( gain, GAIN_PIT_MAX ); /* 1.2 in Q14 */
     370             :     }
     371             :     ELSE
     372             :     {
     373       72983 :         gain = 0;
     374       72983 :         move16();
     375             :     }
     376             : 
     377             :     /* Limit the energy of pitch contribution */
     378     1450516 :     IF( norm_flag )
     379             :     {
     380             :         /*that part of code seems never used*/
     381             :         /* Compute scalar product <xn[],xn[]> */
     382           0 :         xx = round_fx( Dot_product12_offs( xn, xn, L_subfr, &exp_xx, 1 ) );
     383             : 
     384             :         /* gain_p_snr = sqrt(<xn,xn>/<y1,y1>) */
     385           0 :         tmp = BASOP_Util_Divide1616_Scale( xx, yy, &exp_div );
     386           0 :         exp_xx = add( sub( exp_xx, exp_yy ), exp_div );
     387           0 :         tmp = Sqrt16( tmp, &exp_xx ); // exp_xx
     388             : 
     389             :         /* Note: shl works as shl or shr. */
     390           0 :         exp_xx = sub( exp_xx, 1 );
     391             :         BASOP_SATURATE_WARNING_OFF_EVS
     392           0 :         gain_p_snr = round_fx_sat( L_shl_sat( Mpy_32_16_1( 1717986944l /*ACELP_GAINS_CONST Q31*/, tmp ), exp_xx ) );
     393             :         BASOP_SATURATE_WARNING_ON_EVS
     394             : 
     395           0 :         gain = s_min( gain, gain_p_snr ); // Q14
     396             :     }
     397             : 
     398     1450516 :     return gain; // Q14
     399             : }

Generated by: LCOV version 1.14