LCOV - code coverage report
Current view: top level - lib_enc - lp_exc_e_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ e95243e9e67ddeb69dddf129509de1b3d95b402e Lines: 155 170 91.2 %
Date: 2025-09-14 03:13:15 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             : #include <stdint.h>
       5             : #include "options.h" /* Compilation switches                   */
       6             : #include "cnst.h"    /* Common constants                       */
       7             : //#include "prot_fx.h"       /* Function prototypes                    */
       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      599001 : 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      599001 :     Word16 use_prev_sf_pit_gain = 0; // Q0
      57      599001 :     move16();
      58             : 
      59      599001 :     gain1 = 0;
      60      599001 :     move16();
      61      599001 :     gain2 = 0;
      62      599001 :     move16();
      63             : 
      64             :     /*----------------------------------------------------------------*
      65             :      * Find the target energy if the adaptive exc. is not filtered
      66             :      *----------------------------------------------------------------*/
      67      599001 :     test();
      68      599001 :     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      599001 :     exp_ener = 0;
      74      599001 :     move16();
      75      599001 :     wtmp = 0;
      76      599001 :     move16();
      77      599001 :     test();
      78      599001 :     IF( EQ_16( *lp_flag, FULL_BAND ) || EQ_16( *lp_flag, NORMAL_OPERATION ) )
      79             :     {
      80      557456 :         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      557456 :         move16();
      82             :     }
      83             : 
      84             :     /*----------------------------------------------------------------*
      85             :      * Filter the adaptive excitation
      86             :      * Find the target energy if the adapt. exc. is filtered
      87             :      *----------------------------------------------------------------*/
      88             : 
      89      599001 :     exp_ener1 = 0;
      90      599001 :     move16();
      91      599001 :     wtmp1 = 0;
      92      599001 :     move16();
      93      599001 :     test();
      94      599001 :     IF( ( ( *lp_flag == LOW_PASS ) ) || ( EQ_16( *lp_flag, NORMAL_OPERATION ) ) )
      95             :     {
      96      539607 :         test();
      97      539607 :         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    35074455 :             FOR( i = 0; i < L_subfr; i++ )
     111             :             {
     112    34534848 :                 Ltmp = L_mult( 5898, exc[i - 1 + i_subfr] ); /* constants in Q15 */
     113    34534848 :                 Ltmp = L_mac( Ltmp, 20972, exc[i + i_subfr] );
     114    34534848 :                 Ltmp = L_mac( Ltmp, 5898, exc[i + 1 + i_subfr] );
     115    34534848 :                 exc_tmp[i] = round_fx( Ltmp );
     116    34534848 :                 move16();
     117             :             }
     118             :         }
     119             : 
     120      539607 :         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      599001 :     if ( LT_16( exp_ener, exp_ener1 ) )
     124             :     {
     125       46754 :         wtmp = shr( wtmp, 1 ); // exp_ener + 1
     126             :     }
     127             : 
     128      599001 :     if ( GT_16( exp_ener, exp_ener1 ) )
     129             :     {
     130       77139 :         wtmp1 = shr( wtmp1, 1 ); // exp_ener1 + 1
     131             :     }
     132             : 
     133             :     /*-----------------------------------------------------------------*
     134             :      * use the best prediction (minimize quadratic error)
     135             :      *-----------------------------------------------------------------*/
     136             : 
     137      599001 :     test();
     138      599001 :     test();
     139      599001 :     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      375497 :         select = LOW_PASS;
     143      375497 :         move16();
     144      375497 :         Copy( exc_tmp, &exc[i_subfr], L_subfr ); // Q_new
     145      375497 :         Copy( y1_tmp, y1, L_subfr );             // Q_new-1+shift
     146      375497 :         Copy( xn2_tmp, xn2, L_subfr );           // Q_new-1+shift
     147             : 
     148      375497 :         IF( use_prev_sf_pit_gain == 0 )
     149             :         {
     150      375497 :             *gain_pit = gain2; // Q14
     151      375497 :             move16();
     152      375497 :             g_corr[0] = g_corr2[0];
     153      375497 :             move16();
     154      375497 :             g_corr[1] = g_corr2[1];
     155      375497 :             move16();
     156      375497 :             g_corr[2] = g_corr2[2];
     157      375497 :             move16();
     158      375497 :             g_corr[3] = g_corr2[3];
     159      375497 :             move16();
     160             :         }
     161             :     }
     162             :     ELSE
     163             :     {
     164             :         /* no LP filter used for pitch excitation prediction */
     165      223504 :         select = FULL_BAND;
     166      223504 :         move16();
     167      223504 :         IF( use_prev_sf_pit_gain == 0 )
     168             :         {
     169      223504 :             *gain_pit = gain1; // Q14
     170      223504 :             move16();
     171             :         }
     172             :     }
     173             : 
     174      599001 :     return select;
     175             : }
     176             : /*-------------------------------------------------------------------*
     177             :  * adpt_enr_fx()
     178             :  *
     179             :  * Find  adaptive excitation energy
     180             :  * This serves to decide about the filtering of the adaptive excitation
     181             :  *-------------------------------------------------------------------*/
     182             : 
     183     1097063 : static Word16 adpt_enr_fx(                          /* o  : adaptive excitation energy             mant     */
     184             :                            const Word16 codec_mode, /* i  : MODE1 or MODE2                                  */
     185             :                            const Word16 *exc,       /* i  : excitation vector                      Q_new    */
     186             :                            const Word16 *h1,        /* i  : impuls response                        Q15      */
     187             :                            Word16 *y1,              /* o  : zero-memory filtered adpt. excitation  12 bits  */
     188             :                            const Word16 L_subfr,    /* i  : vector length                                                                   */
     189             :                            Word16 *gain,            /* o  : subframe adaptive gain                 Q14      */
     190             :                            Word16 *g_corr,          /* o  : correlations for adptive gain           mant/exp*/
     191             :                            const Word16 clip_gain,  /* i  : adaptive gain clipping flag             Q0          */
     192             :                            const Word16 *xn,        /* i  : adaptive codebook target               12 bits      Q_new-1+shift*/
     193             :                            Word16 *xn2,             /* o  : algebraic codebook target              12 bits      Q_new-1+shift*/
     194             :                            Word16 *exp_ener         /* o  : adaptive excitation energy             exp      */
     195             :                            ,
     196             :                            Word16 use_prev_sf_pit_gain /* i : flag to use prev sf pitch gain or not */
     197             : )
     198             : {
     199             :     Word16 ener, i;
     200             :     Word16 exc_tmp[L_FRAME16k], xn_tmp[L_FRAME16k];
     201             :     Word32 Ltmp;
     202             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL /* Critical Overflow */
     203     1097063 :     Flag Overflow = 0;
     204             : #endif
     205             : 
     206     1097063 :     Overflow = 0;
     207     1097063 :     move16();
     208     1097063 :     Overflow =
     209     1097063 :         conv_fx( exc, h1, y1, L_subfr );
     210             : 
     211     1097063 :     IF( use_prev_sf_pit_gain == 0 )
     212             :     {
     213     1097063 :         *gain = corr_xy1_fx( xn, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
     214     1097063 :         move16();
     215             : 
     216     1097063 :         test();
     217     1097063 :         IF( GT_16( L_subfr, L_SUBFR ) && Overflow )
     218             :         {
     219       46221 :             FOR( i = 0; i < L_subfr; i++ )
     220             :             {
     221       45952 :                 exc_tmp[i] = mult( exc[i], 8192 /*0.25.Q15*/ ); // Q_new
     222       45952 :                 move16();
     223       45952 :                 xn_tmp[i] = mult( xn[i], 8192 /*0.25.Q15*/ ); // Q_new
     224       45952 :                 move16();
     225             :             }
     226         269 :             Overflow = 0;
     227             : 
     228         269 :             conv_fx( exc_tmp, h1, y1, L_subfr );
     229         269 :             *gain = corr_xy1_fx( xn_tmp, y1, g_corr, L_subfr, codec_mode == MODE2, &Overflow );
     230         269 :             move16();
     231             :         }
     232             : 
     233             :         /* clip gain, if necessary to avoid problems at decoder */
     234     1097063 :         test();
     235     1097063 :         if ( EQ_16( clip_gain, 1 ) && GT_16( *gain, 15565 ) ) /* constant in Q14 */
     236             :         {
     237        4310 :             *gain = 15565; // 0.95.Q14
     238        4310 :             move16();
     239             :         }
     240             : 
     241     1097063 :         test();
     242     1097063 :         IF( EQ_16( clip_gain, 2 ) && GT_16( *gain, 10650 ) ) // 0.65.Q14
     243             :         {
     244        4532 :             *gain = 10650; // 0.65.Q14
     245        4532 :             move16();
     246             :         }
     247             :     }
     248             : 
     249             :     /* find energy of new target xn2[] */
     250     1097063 :     updt_tar_fx( xn, xn2, y1, *gain, L_subfr );
     251             : 
     252     1097063 :     IF( GT_16( L_subfr, L_SUBFR ) )
     253             :     {
     254             :         /* could possibly happen in GSC */
     255       14914 :         Ltmp = Calc_Energy_Autoscaled( xn2, 0, L_subfr, exp_ener );
     256       14914 :         i = norm_l( Ltmp );
     257       14914 :         ener = extract_h( L_shl( Ltmp, i ) ); // exp_ener
     258       14914 :         i = sub( 31, i );
     259       14914 :         *exp_ener = sub( i, *exp_ener );
     260       14914 :         move16();
     261             :     }
     262             :     ELSE
     263             :     {
     264     1082149 :         ener = extract_h( Dot_product12( xn2, xn2, L_SUBFR, exp_ener ) ); // Q15
     265             :     }
     266             : 
     267     1097063 :     return ener;
     268             : }
     269             : 
     270             : /*-------------------------------------------------------------------*
     271             :  * corr_xy1()
     272             :  *
     273             :  * Find the correlations between the target xn[] and the filtered adaptive
     274             :  * codebook excitation y1[]. ( <y1,y1>  and -2<xn,y1> )
     275             :  *-------------------------------------------------------------------*/
     276             : 
     277     1172725 : Word16 corr_xy1_fx(                        /* o  : pitch gain  (0..GAIN_PIT_MAX)         */
     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             :                     ,
     284             :                     Flag *Overflow_out /* o :  propagating the Overflow flag to upper level */
     285             : )
     286             : {
     287             :     Word16 i;
     288             :     Word16 tmp, xx, xy, yy, exp_xy, exp_xx, exp_yy, exp_div, gain, gain_p_snr;
     289             :     Word32 Ltmp1, Ltmp2;
     290             :     Word16 xn[L_FRAME16k], y1[L_FRAME16k];
     291             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     292     1172725 :     Flag Overflow = 0;
     293             : #endif
     294             : 
     295             :     /*----------------------------------------------------------------*
     296             :      * Find the ACELP correlations and the pitch gain
     297             :      *----------------------------------------------------------------*/
     298             : 
     299             :     /* Compute scalar product <y1[],y1[]> */
     300     1172725 :     Copy( xn_1, xn, L_subfr ); // Q_new
     301     1172725 :     Copy( y1_1, y1, L_subfr );
     302     1172725 :     Overflow = 0;
     303     1172725 :     move16();
     304     1172725 :     Ltmp1 = Dot_product12_o( y1, y1, L_subfr, &exp_yy, &Overflow );
     305     1172725 :     *Overflow_out |= Overflow;
     306     1172725 :     move16();
     307     1172725 :     IF( Overflow )
     308             :     {
     309       83971 :         FOR( i = 0; i < L_subfr; i++ )
     310             :         {
     311       82816 :             xn[i] = mult_r( xn_1[i], 4096 /*0.125.Q15*/ ); // Q-new
     312       82816 :             move16();
     313       82816 :             y1[i] = mult_r( y1_1[i], 4096 /*0.125.Q15*/ );
     314       82816 :             move16();
     315             :         }
     316             : 
     317        1155 :         Ltmp1 = Dot_product12( y1, y1, L_subfr, &exp_yy );
     318        1155 :         exp_yy = add( exp_yy, 6 );
     319        1155 :         yy = extract_h( Ltmp1 );
     320             : 
     321             :         /* Compute scalar product <xn[],y1[]> */
     322        1155 :         Ltmp2 = Dot_product12( xn, y1, L_subfr, &exp_xy );
     323        1155 :         xy = extract_h( Ltmp2 );
     324        1155 :         exp_xy = add( exp_xy, 6 );
     325             : 
     326        1155 :         g_corr[0] = yy;
     327        1155 :         move16();
     328        1155 :         g_corr[1] = exp_yy;
     329        1155 :         move16();
     330             :         /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function */
     331        1155 :         g_corr[2] = xy;
     332        1155 :         move16();
     333        1155 :         g_corr[3] = exp_xy;
     334        1155 :         move16();
     335             :     }
     336             :     ELSE
     337             :     {
     338     1171570 :         yy = extract_h( Ltmp1 ); // exp_yy
     339             :         /* Ltmp1 = L_shr(Ltmp1, sub(30, exp_yy));*/
     340             : 
     341             :         /* Compute scalar product <xn[],y1[]> */
     342     1171570 :         Ltmp2 = Dot_product12_o( xn, y1, L_subfr, &exp_xy, &Overflow );
     343     1171570 :         *Overflow_out |= Overflow;
     344     1171570 :         move16();
     345     1171570 :         xy = extract_h( Ltmp2 );
     346             :         /* Ltmp2 = L_shr(Ltmp2, sub(30, exp_xy));*/
     347             : 
     348     1171570 :         g_corr[0] = yy;
     349     1171570 :         move16();
     350     1171570 :         g_corr[1] = exp_yy;
     351     1171570 :         move16();
     352             :         /* -2.0*temp1 + 0.01 is done in Gain_enc_2 function*/
     353     1171570 :         g_corr[2] = xy; // exp_xy
     354     1171570 :         move16();
     355     1171570 :         g_corr[3] = exp_xy;
     356     1171570 :         move16();
     357             :     }
     358             : 
     359             :     /* find pitch gain and bound it by [0,GAIN_PIT_MAX] */
     360     1172725 :     test();
     361     1172725 :     IF( xy >= 0 && NE_16( s_or( yy, xy ), 16384 ) )
     362             :     {
     363             :         /* compute gain = xy/yy */
     364     1119046 :         xy = shr( xy, 1 );      /* be sure that xy < yy */
     365     1119046 :         gain = div_s( xy, yy ); // Q15
     366     1119046 :         i = sub( exp_xy, exp_yy );
     367     1119046 :         gain = shl_o( gain, i, &Overflow ); /* saturation can occur here */
     368     1119046 :         *Overflow_out |= Overflow;
     369     1119046 :         move16();
     370             : 
     371     1119046 :         gain = s_max( gain, 0 );
     372     1119046 :         gain = s_min( gain, GAIN_PIT_MAX ); /* 1.2 in Q14 */
     373             :     }
     374             :     ELSE
     375             :     {
     376       53679 :         gain = 0;
     377       53679 :         move16();
     378             :     }
     379             : 
     380             :     /* Limit the energy of pitch contribution */
     381     1172725 :     IF( norm_flag )
     382             :     {
     383             :         /*that part of code seems never used*/
     384             :         /* Compute scalar product <xn[],xn[]> */
     385           0 :         xx = round_fx( Dot_product12_offs( xn, xn, L_subfr, &exp_xx, 1 ) );
     386             : 
     387             :         /* gain_p_snr = sqrt(<xn,xn>/<y1,y1>) */
     388           0 :         tmp = BASOP_Util_Divide1616_Scale( xx, yy, &exp_div );
     389           0 :         exp_xx = add( sub( exp_xx, exp_yy ), exp_div );
     390           0 :         tmp = Sqrt16( tmp, &exp_xx ); // exp_xx
     391             : 
     392             :         /* Note: shl works as shl or shr. */
     393           0 :         exp_xx = sub( exp_xx, 1 );
     394             :         BASOP_SATURATE_WARNING_OFF_EVS
     395           0 :         gain_p_snr = round_fx_sat( L_shl_sat( Mpy_32_16_1( 1717986944l /*ACELP_GAINS_CONST Q31*/, tmp ), exp_xx ) );
     396             :         BASOP_SATURATE_WARNING_ON_EVS
     397             : 
     398           0 :         gain = s_min( gain, gain_p_snr ); // Q14
     399             :     }
     400             : 
     401     1172725 :     return gain; // Q14
     402             : }

Generated by: LCOV version 1.14