LCOV - code coverage report
Current view: top level - lib_enc - gaus_enc_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ e95243e9e67ddeb69dddf129509de1b3d95b402e Lines: 0 290 0.0 %
Date: 2025-09-14 03:13:15 Functions: 0 3 0.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 "rom_com_fx.h"  /* Static table prototypes                */
       8             : #include "rom_com.h"     /* Static table prototypes                */
       9             : #include "rom_enc.h"     /* Static table prototypes                */
      10             : #include "prot_fx.h"     /* Function prototypes                    */
      11             : #include "prot_fx_enc.h" /* Function prototypes                    */
      12             : //#include "basop_mpy.h"
      13             : 
      14             : /*-------------------------------------------------------------------*
      15             :  * Local constants
      16             :  *-------------------------------------------------------------------*/
      17             : 
      18             : #define NMAX 8 /* Control of the routine's complexity */
      19             : /* #define FAC_DELTA  16.0f */
      20             : #define SFAC_DELTA 11
      21             : 
      22             : /*-------------------------------------------------------------------*
      23             :  * Local functions
      24             :  *-------------------------------------------------------------------*/
      25             : 
      26             : static Word16 cod_2pos_fx( const Word16 ind1, const Word16 ind2, const Word16 sign1, const Word16 sign2, const Word16 n );
      27             : 
      28             : static void gauss2v_fx( BSTR_ENC_HANDLE hBstr, const Word16 h[], const Word16 xn[], const Word16 dn[], Word16 code[], Word16 y1[], Word32 *gain, const Word16 lg, const Word16 shift, const Word16 Q_new, const Word16 nb_bits );
      29             : /*-------------------------------------------------------------------*
      30             :  * Gaus_encode
      31             :  *
      32             :  * Encoder UnVoiced excitation coding using Gaussian codebooks
      33             :  * - ACELP quantized Gaussian excitation
      34             :  * - gain quantization
      35             :  * - Total excitation for UnVoiced coders
      36             :  * - Updates
      37             :  *-------------------------------------------------------------------*/
      38           0 : Word16 gaus_encode_fx(
      39             :     Encoder_State *st_fx,  /* i/o: encoder state structure */
      40             :     const Word16 i_subfr,  /* i  : subframe index                                       Q0*/
      41             :     const Word16 *h1,      /* i  : weighted filter input response                       Q14*/
      42             :     const Word16 *xn,      /* i  : target vector                                        Q12*/
      43             :     Word16 *exc,           /* o  : pointer to excitation signal frame                   Q_new*/
      44             :     Word16 *mem_w0,        /* o  : weighting filter denominator memory                  Q_new*/
      45             :     Word16 *clip_gain,     /* o  : memory of gain of pitch clipping algorithm           [2.56x,Q14,Q8,Q0,Q14,Q14]*/
      46             :     Word16 *tilt_code,     /* o  : synthesis excitation spectrum tilt                   Q15*/
      47             :     Word16 *code,          /* o  : algebraic excitation                                                         Q9*/
      48             :     Word32 *gain_code,     /* o  : Code gain.                                                                           Q16*/
      49             :     Word16 *y2,            /* o  : zero-memory filtered adaptive excitation                     Q9*/
      50             :     Word16 *gain_inov,     /* o  : innovation gain                                                                      Q12*/
      51             :     Word16 *voice_fac,     /* o  : voicing factor                                                                       Q15*/
      52             :     Word16 *gain_pit,      /* o  : adaptive excitation gain                                                     Q14*/
      53             :     const Word16 Q_new,    /* i  : scaling factor                                       */
      54             :     const Word16 shift,    /* i  : scaling factor                                       */
      55             :     Word32 *norm_gain_code /* o  : normalized innovative cb. gain                                       Q16*/
      56             : )
      57             : {
      58             :     Word16 nb_bits, idx;
      59           0 :     Word16 i = 0;
      60             :     Word32 Ltmp;
      61             :     Word16 dn[L_SUBFR], exp_code, gcode; /* Correlation between xn and h1 */
      62             :     Word16 exp, tmp, tmp_idx;
      63             : #ifndef ISSUE_1867_replace_overflow_libenc
      64             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
      65             :     Flag Overflow = 0;
      66             :     move32();
      67             : #endif
      68             : #endif
      69             : 
      70             :     /*----------------------------------------------------------------*
      71             :      *  Encode gaussian excitation
      72             :      *----------------------------------------------------------------*/
      73             : 
      74             :     /* Correlation between target xn2[] and impulse response h1[] */
      75           0 :     corr_xh_fx( xn, dn, h1 );
      76             : 
      77           0 :     tmp_idx = shr( i_subfr, 6 );
      78           0 :     nb_bits = st_fx->acelp_cfg.fixed_cdk_index[tmp_idx]; /* Q0 */
      79           0 :     move16();
      80             : 
      81           0 :     gauss2v_fx( st_fx->hBstr, h1, xn, dn, code, y2, gain_code, L_SUBFR, shift, Q_new, shr( nb_bits, 1 ) );
      82             : 
      83             :     /*----------------------------------------------------------------*
      84             :      *  Encode gaussian gain
      85             :      *----------------------------------------------------------------*/
      86             : 
      87             :     /* codeword energy computation */
      88           0 :     Ltmp = Dot_product12( code, code, L_SUBFR, &exp_code );
      89             : 
      90           0 :     exp_code = sub( exp_code, 18 + 6 ); /* exp: -18 (code in Q9), -6 (L_subfr = 64) */
      91           0 :     Ltmp = Isqrt_lc( Ltmp, &exp_code );
      92           0 :     *gain_inov = extract_h( L_shl_sat( Ltmp, sub( exp_code, 3 ) ) ); /* g_code_inov in Q12 */
      93             : 
      94           0 :     nb_bits = st_fx->acelp_cfg.gains_mode[tmp_idx]; /* Q0 */
      95           0 :     move16();
      96             :     /* low bound = -30; stepSize  = 1.71875; inv_stepSize  = 0.5818181 */
      97           0 :     idx = gain_enc_gaus_fx( gain_code, nb_bits, -7680, 28160, 19065 ); /* Q0 */
      98           0 :     push_indice( st_fx->hBstr, IND_GAIN, idx, nb_bits );
      99             : 
     100             :     /*----------------------------------------------------------------*
     101             :      * Total excitation for Unvoiced coders
     102             :      *----------------------------------------------------------------*/
     103             : #ifdef ISSUE_1867_replace_overflow_libenc
     104           0 :     gcode = round_fx_sat( L_shl_sat( *gain_code, Q_new ) ); /* scaled gain_code with Qnew */
     105             : #else
     106             :     gcode = round_fx_o( L_shl_o( *gain_code, Q_new, &Overflow ), &Overflow ); /* scaled gain_code with Qnew */
     107             : #endif
     108           0 :     FOR( i = 0; i < L_SUBFR; i++ )
     109             :     {
     110           0 :         exc[i + i_subfr] = round_fx( L_shl( L_mult( gcode, code[i] ), 15 - 9 ) ); /* Q_new */
     111             :     }
     112             : 
     113             :     /*----------------------------------------------------------------*
     114             :      * Updates: last value of new target is stored in mem_w0
     115             :      *----------------------------------------------------------------*/
     116             : 
     117           0 :     Ltmp = L_mult( gcode, y2[L_SUBFR - 1] ); /* Q_new + 10 */
     118           0 :     Ltmp = L_shl( Ltmp, add( 5, shift ) );   /* Q_new + 15 + shift */
     119           0 :     Ltmp = L_negate( Ltmp );
     120           0 :     Ltmp = L_mac( Ltmp, xn[L_SUBFR - 1], 16384 ); /* Q_new + 15 + shift */
     121           0 :     Ltmp = L_shl_sat( Ltmp, sub( 1, shift ) );    /* Q_new + 16 */
     122           0 :     *mem_w0 = round_fx_sat( Ltmp );               /* Q_new */
     123           0 :     move16();
     124           0 :     init_gp_clip_fx( clip_gain ); /* reset pitch clipping parameters  */
     125             : 
     126           0 :     *gain_pit = 0;
     127           0 :     *tilt_code = 0;
     128           0 :     move16();            /* purely unvoiced */
     129           0 :     *voice_fac = -32768; /* -1 in Q31 */
     130           0 :     move16();            /* purely unvoiced */
     131           0 :     exp = sub( norm_s( *gain_inov ), 1 );
     132           0 :     exp = s_max( exp, 0 );
     133             : 
     134           0 :     tmp = div_s( shr( 8192, exp ), *gain_inov );
     135           0 :     *norm_gain_code = L_shr( Mult_32_16( *gain_code, tmp ), sub( 1, exp ) ); /* Q16 */
     136           0 :     move16();
     137             : 
     138           0 :     return ( L_SUBFR << 6 );
     139             : }
     140             : /*-------------------------------------------------------------------*
     141             :  * gauss2v()
     142             :  *
     143             :  * encoder of Gaussian Codebook for unvoiced
     144             :  * consisting of addition of 2 Gaussian vectors
     145             :  *
     146             :  * One Gaussian vector of 192 values vectors delayed by 2
     147             :  *-------------------------------------------------------------------*/
     148           0 : void gauss2v_fx(
     149             :     BSTR_ENC_HANDLE hBstr, /* i/o: encoder state structure */
     150             :     const Word16 h[],      /* i  : weighted LP filter impulse response     Q15 */
     151             :     const Word16 xn[],     /* i  : target signal                           Q12 */
     152             :     const Word16 dn[],     /* i  : backward filtered target                Q12 */
     153             :     Word16 code[],         /* o  : gaussian excitation                     Q9  */
     154             :     Word16 y1[],           /* o  : zero-memory filtered gauss. excitation  Q8  */
     155             :     Word32 *gain,          /* o  : excitation gain. 32-bit number in       Q16 */
     156             :     const Word16 lg,       /* i  : subframe size                           Q0  */
     157             :     const Word16 shift,    /* i  : Scaling factor                          Q0  */
     158             :     const Word16 Q_new,    /* i  : Scaling factor                          Q0  */
     159             :     const Word16 nb_bits   /* i  : nb ob bits per track (max 6)            Q0  */
     160             : )
     161             : {
     162             :     Word16 i, j, ind1, ind2;
     163             :     Word16 nvec, step;
     164             :     Word32 cor, cora, dotprod;
     165             :     Word16 enerw;
     166             :     Word32 eneri, cor2;
     167             :     Word32 enerw32, cor2w32;
     168             :     Word16 *cpt1;
     169             :     Word16 *pt1, *pt2;
     170             :     Word32 max_val[NMAX + 1];
     171             :     Word16 *pos[NMAX + 1];
     172             :     Word32 sign[NMAX + 1];
     173             :     Word32 ener[NMAX + 1], corr[NMAX + 1], ener1;
     174             :     Word16 dico2[L_SUBFR * NMAX];
     175             :     Word16 exp_num;
     176             :     Word16 exp_den;
     177             :     Word16 Num;
     178             :     Word16 Den;
     179             :     Word32 GainPortion1;
     180             :     Word32 GainPortion2;
     181             :     Word32 cor_abs;
     182             :     Word16 cor_neg;
     183             :     Word16 div_result;
     184             :     Word32 ener_sqrt;
     185             :     Word32 Portion;
     186             :     Word16 sign1, sign2;
     187             :     Word16 enerw_norm, enerw_mantissa;
     188             :     Word16 cor2w_norm, cor2w_mantissa;
     189             :     Word16 eneri_norm, eneri_mantissa;
     190             :     Word16 cor2_norm, cor2_mantissa;
     191             :     Word16 difference_norm;
     192             :     Word32 cor32; /* 32-bit intermediate value*/
     193             :     Word16 hi1, lo1;
     194             :     Word16 update_best;
     195             :     Word16 idx;
     196             :     Word32 Lc0, Lc1, Lnum, Lden;
     197             :     Word16 gxx, gcc, index_delta, delta, m_sign, inv_delta;
     198             :     Word16 hg[190], Gaus_dico2[190];
     199             :     Word16 shiftP3;
     200             : #ifndef ISSUE_1867_replace_overflow_libenc
     201             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     202             :     Flag Overflow = 0;
     203             :     move32();
     204             : #endif
     205             : #endif
     206             : 
     207             :     /*----------------------------------------------------------------*
     208             :      * Encode the tilt of gaussian excitation
     209             :      *----------------------------------------------------------------*/
     210             : 
     211             :     /* Compute spectral tilt of target */
     212           0 :     Lc0 = L_mult( xn[1], xn[1] ); /* Q25 */
     213           0 :     Lc1 = L_mult( xn[1], xn[0] ); /* Q25 */
     214           0 :     FOR( i = 2; i < L_SUBFR; i++ )
     215             :     {
     216             :         /* fc0 += xn[i]*xn[i]   */
     217             :         /* fc1 += xn[i]*xn[i-1] */
     218           0 :         Lc0 = L_mac_sat( Lc0, xn[i], xn[i] );     /* Q25 */
     219           0 :         Lc1 = L_mac_sat( Lc1, xn[i], xn[i - 1] ); /* Q25 */
     220             :     }
     221             :     /* fgxx = fc1/fc0 */
     222           0 :     exp_num = sub( norm_l( Lc1 ), 1 );
     223           0 :     Num = extract_h( L_shl( Lc1, exp_num ) );
     224           0 :     m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
     225           0 :     Num = abs_s( Num );
     226           0 :     Lc0 = L_max( Lc0, 1 );
     227           0 :     exp_den = norm_l( Lc0 );
     228           0 :     Den = extract_h( L_shl( Lc0, exp_den ) );                          /* Q9 + exp_den */
     229           0 :     gxx = shr( div_s( Num, Den ), sub( exp_num, sub( exp_den, 2 ) ) ); /* Q13 */
     230           0 :     gxx = i_mult2( gxx, m_sign );                                      /* Apply sign */
     231             : 
     232           0 :     set16_fx( hg, 0, 190 );                       /* Compute spectral tilt of filtered codebook */
     233           0 :     Copy( h, hg, L_SUBFR );                       // Q15
     234           0 :     conv_fx( gaus_dico_fx, hg, Gaus_dico2, 190 ); // Q12
     235             : 
     236           0 :     Lc0 = L_mult( Gaus_dico2[1], Gaus_dico2[1] ); /* Q25 */
     237           0 :     Lc1 = L_mult( Gaus_dico2[1], Gaus_dico2[0] ); /* Q25 */
     238           0 :     FOR( i = 2; i < 190; i++ )
     239             :     {
     240             :         /* fc0 += fgaus_dico2[i]*fgaus_dico2[i]   */
     241             :         /* fc1 += fgaus_dico2[i]*fgaus_dico2[i-1] */
     242           0 :         Lc0 = L_mac( Lc0, Gaus_dico2[i], Gaus_dico2[i] );     /* Q25 */
     243           0 :         Lc1 = L_mac( Lc1, Gaus_dico2[i], Gaus_dico2[i - 1] ); /* Q25 */
     244             :     }
     245             : 
     246             :     /* fgcc = fc1/fc0 */
     247             : 
     248           0 :     exp_num = sub( norm_l( Lc1 ), 1 );
     249           0 :     Num = extract_h( L_shl( Lc1, exp_num ) );
     250           0 :     m_sign = s_or( shr( Num, 16 ), 1 ); /* Remove sign */
     251           0 :     Num = abs_s( Num );
     252             : 
     253           0 :     Lc0 = L_max( Lc0, 1 );
     254           0 :     exp_den = norm_l( Lc0 );
     255           0 :     Den = extract_h( L_shl( Lc0, exp_den ) );
     256           0 :     gcc = shr( div_s( Num, Den ), sub( exp_num, sub( exp_den, 2 ) ) ); /* Q13 */
     257           0 :     gcc = i_mult2( gcc, m_sign );                                      /* Apply sign */
     258             : 
     259             :     /* fdelta = (1-fgcc*fgxx) / (2*fgcc+fgxx) Compute and quantize spectral tilt modification factor */
     260           0 :     Lnum = L_sub( 134217728L, L_mult( gcc, gxx ) );  /* Q30 */
     261           0 :     Lden = L_mac( L_mult( gxx, 8192 ), gcc, 16384 ); /* Q30 */
     262             : 
     263           0 :     exp_num = sub( norm_l( Lnum ), 1 );
     264           0 :     Num = extract_h( L_shl( Lnum, exp_num ) ); /* Q14 + exp_den */
     265           0 :     m_sign = s_or( shr( Num, 16 ), 1 );        /* Remove sign */
     266           0 :     Num = abs_s( Num );
     267             : 
     268           0 :     Lden = L_max( Lden, 1 );
     269           0 :     exp_den = norm_l( Lden );
     270           0 :     Den = extract_h( L_shl( Lden, exp_den ) );
     271             : 
     272           0 :     delta = shr_sat( div_s( Num, Den ), sub( exp_num, exp_den ) ); /* Q15 */
     273           0 :     delta = i_mult2( delta, m_sign );                              /* Apply sign                Q0*/
     274             :     /* index_delta = (short)(FAC_DELTA * fdelta) */
     275           0 :     index_delta = shr( delta, SFAC_DELTA );
     276             : 
     277             :     /* index_delta  [0,7] */
     278           0 :     index_delta = s_max( index_delta, 0 );
     279           0 :     index_delta = s_min( index_delta, 7 );
     280             : 
     281             :     /* fdelta = STEP_DELTA * (float)index_delta */
     282           0 :     delta = shl( index_delta, 11 ); /* delta in Q15 */
     283             : 
     284           0 :     IF( delta > 0 ) /* Adapt spectral tilt of initial codebook */
     285             :     {
     286             :         /* Computation of 1 / (1+fdelta*fdelta) */
     287           0 :         inv_delta = inv_delta_tab[sub( index_delta, 1 )];
     288           0 :         move16(); /* Q15 */
     289             : 
     290             :         /* fgaus_dico2[0] = gaus_dico[0] */
     291           0 :         Gaus_dico2[0] = gaus_dico_fx[0]; /* Q12 */
     292           0 :         move16();
     293           0 :         FOR( i = 1; i < 190; i++ )
     294             :         {
     295             :             /* fgaus_dico2[i] = (gaus_dico[i] - fdelta*gaus_dico[i-1]) / (1 + fdelta*fdelta) */
     296           0 :             Lnum = L_msu( L_deposit_h( gaus_dico_fx[i] ), delta, gaus_dico_fx[i - 1] );
     297           0 :             Gaus_dico2[i] = round_fx( Mpy_32_16_1( Lnum, inv_delta ) );
     298             :         }
     299             :     }
     300             :     ELSE
     301             :     {
     302           0 :         FOR( i = 0; i < 190; i++ )
     303             :         {
     304             :             /* fgaus_dico2[i] = gaus_dico[i] */
     305           0 :             Gaus_dico2[i] = gaus_dico_fx[i]; /* Q12 */
     306           0 :             move16();
     307             :         }
     308             :     }
     309             : 
     310             :     /*----------------------------------------------------------------*
     311             :      * Initializations
     312             :      *----------------------------------------------------------------*/
     313             : 
     314           0 :     ind1 = 0;
     315           0 :     move16();
     316           0 :     ind2 = 0;
     317           0 :     move16();
     318             : 
     319           0 :     nvec = shl( 1, nb_bits );
     320           0 :     step = shr( 0x80, nb_bits );
     321             : 
     322             :     /*----------------------------------------------------------------*
     323             :      * dot product between dn and gaussian codevectors,
     324             :      * keep NMAX best vectors
     325             :      *----------------------------------------------------------------*/
     326             : 
     327           0 :     set32_fx( max_val, 0, NMAX + 1 );
     328           0 :     set32_fx( sign, 0, NMAX + 1 );
     329             : 
     330           0 :     FOR( i = 0; i < NMAX + 1; i++ )
     331             :     {
     332           0 :         pos[i] = (Word16 *) Gaus_dico2;
     333             :     }
     334             : 
     335           0 :     cpt1 = Gaus_dico2;
     336           0 :     move16();
     337             : 
     338           0 :     FOR( i = 0; i < nvec; i++ )
     339             :     {
     340             :         /* Dot product without normalization, because values are compared with each other afterwards. */
     341           0 :         cor = Dot_product( cpt1, dn, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31*/
     342           0 :         cora = L_abs( cor );
     343           0 :         j = NMAX - 1;
     344           0 :         move16();
     345             : 
     346             :         DO
     347             :         {
     348           0 :             IF( GE_32( cora, max_val[j] ) )
     349             :             {
     350           0 :                 max_val[j + 1] = max_val[j];
     351           0 :                 move32(); /*Q31*/
     352           0 :                 pos[j + 1] = pos[j];
     353           0 :                 move16(); /*Pointer*/
     354           0 :                 sign[j + 1] = sign[j];
     355           0 :                 move32(); /*Q31*/
     356           0 :                 max_val[j] = cora;
     357           0 :                 move32(); /*Q31*/
     358           0 :                 pos[j] = cpt1;
     359           0 :                 move16(); /*Pointer*/
     360           0 :                 sign[j] = cor;
     361           0 :                 move32(); /*Q31*/
     362             :             }
     363           0 :             j--;
     364             :         }
     365           0 :         WHILE( j >= 0 );
     366           0 :         cpt1 += step;
     367             :     }
     368             : 
     369             :     /*----------------------------------------------------------------*
     370             :      * filter selected vectors
     371             :      * put sign
     372             :      * compute energy
     373             :      *----------------------------------------------------------------*/
     374             : 
     375           0 :     pt1 = dico2;
     376           0 :     move16();
     377           0 :     FOR( i = 0; i < NMAX; i++ )
     378             :     {
     379             :         /* Input vector (pos) Q12, filter coefs in Q15, result in same format as input vector (Q12) */
     380           0 :         conv_fx( pos[i], h, pt1, lg );
     381             : 
     382             :         /* put sign and compute energy */
     383           0 :         IF( sign[i] < 0 )
     384             :         {
     385           0 :             FOR( j = 0; j < lg; j++ )
     386             :             {
     387           0 :                 pt1[j] = negate( pt1[j] );
     388           0 :                 move16(); /*Store into dico2*/
     389             :             }
     390             :         }
     391           0 :         ener[i] = Dot_product( pt1, pt1, lg ); /* pt1 points to filtered vector in dico2, in Q12 */
     392           0 :         move32();                              /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */
     393           0 :         corr[i] = Dot_product( pt1, xn, lg );  /* must be equal to sign[i] !! */
     394           0 :         move32();                              /* pt1 points into dico2, in Q12. xn is in Q12 */
     395             :         /* Result is for Q12 * Q12 with length of 64 (6 bits) + 1 left shift => Q31 */
     396           0 :         pt1 += L_SUBFR;
     397             :     }
     398             : 
     399             :     /*------------------------------------------------------------------------*
     400             :      * try all combinations of NMAX best vectors
     401             :      *------------------------------------------------------------------------*/
     402             : 
     403           0 :     pt1 = dico2;
     404           0 :     move16();
     405             : 
     406             :     /* Initial values for search algorithm */
     407           0 :     enerw32 = L_deposit_h( 0x80 );
     408           0 :     cor2w32 = L_deposit_l( -2 );
     409           0 :     enerw_norm = norm_l( enerw32 );
     410           0 :     cor2w_norm = norm_l( cor2w32 );
     411           0 :     cor2w_mantissa = round_fx( L_shl( cor2w32, cor2w_norm ) );
     412           0 :     enerw_mantissa = round_fx( L_shl( enerw32, enerw_norm ) );
     413             : 
     414           0 :     FOR( i = 0; i < NMAX; i++ )
     415             :     {
     416           0 :         pt2 = pt1;
     417           0 :         move16();
     418           0 :         FOR( j = i; j < NMAX; j++ )
     419             :         {
     420           0 :             cor32 = L_add( corr[i], corr[j] ); /* Q31 */
     421             : 
     422           0 :             dotprod = Dot_product( pt1, pt2, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31 */
     423             : 
     424             :             /* eneri = round_fx(ener[i]) + round_fx(ener[j]) + 2*round_fx(dotprod) */
     425             :             /* Use ScalingShift to stay aligned with ener[] */
     426           0 :             eneri = L_shl( dotprod, 1 ); /* One left shift added for factor of 2 */
     427           0 :             eneri = L_add( ener[i], eneri );
     428           0 :             eneri = L_add( ener[j], eneri ); /* Q31 */
     429             : 
     430           0 :             lo1 = L_Extract_lc( cor32, &hi1 );
     431           0 :             cor2 = Sad_32( 0, hi1, lo1 ); /* Square + Add */
     432             : 
     433           0 :             cor2_norm = norm_l( cor2 );
     434           0 :             eneri_norm = norm_l( eneri );
     435             : #ifdef ISSUE_1867_replace_overflow_libenc
     436           0 :             cor2_mantissa = round_fx_sat( L_shl_sat( cor2, cor2_norm ) );
     437           0 :             eneri_mantissa = round_fx_sat( L_shl_sat( eneri, eneri_norm ) );
     438             : #else
     439             :             cor2_mantissa = round_fx_o( L_shl_o( cor2, cor2_norm, &Overflow ), &Overflow );
     440             :             eneri_mantissa = round_fx_o( L_shl_o( eneri, eneri_norm, &Overflow ), &Overflow );
     441             : #endif
     442           0 :             difference_norm = sub( add( cor2_norm, enerw_norm ), add( cor2w_norm, eneri_norm ) );
     443             : 
     444           0 :             update_best = 0;
     445           0 :             move16();
     446             : 
     447           0 :             IF( difference_norm > 0 )
     448             :             {
     449           0 :                 if ( GT_32( L_shr( L_mult( cor2_mantissa, enerw_mantissa ), difference_norm ),
     450             :                             L_mult( cor2w_mantissa, eneri_mantissa ) ) )
     451             :                 {
     452           0 :                     update_best = 1;
     453           0 :                     move16();
     454             :                 }
     455             :             }
     456             :             ELSE
     457             :             {
     458           0 :                 if ( L_msu_sat( L_shl( L_mult( cor2w_mantissa, eneri_mantissa ), difference_norm ), cor2_mantissa, enerw_mantissa ) < 0 ) // Saturation to be revisited
     459             :                 {
     460           0 :                     update_best = 1;
     461           0 :                     move16();
     462             :                 }
     463             :             }
     464           0 :             IF( update_best != 0 )
     465             :             {
     466           0 :                 cor2w_mantissa = cor2_mantissa;
     467           0 :                 move16();
     468           0 :                 cor2w_norm = cor2_norm;
     469           0 :                 move16();
     470           0 :                 enerw_mantissa = eneri_mantissa;
     471           0 :                 move16();
     472           0 :                 enerw_norm = eneri_norm;
     473           0 :                 move16();
     474           0 :                 ind1 = i;
     475           0 :                 move16();
     476           0 :                 ind2 = j;
     477           0 :                 move16();
     478             :             }
     479           0 :             pt2 += L_SUBFR;
     480             :         }
     481           0 :         pt1 += L_SUBFR;
     482             :     }
     483             : 
     484           0 :     enerw = round_fx( L_shr( L_deposit_h( enerw_mantissa ), enerw_norm ) );
     485             : 
     486             :     /*----------------------------------------------------------------*
     487             :      * Compute zero-memory filtered gauss. excitation y
     488             :      *----------------------------------------------------------------*/
     489             : 
     490           0 :     pt1 = dico2 + ind1 * L_SUBFR;
     491           0 :     move16(); /*Pointer arithmetic*/
     492           0 :     pt2 = dico2 + ind2 * L_SUBFR;
     493           0 :     move16();
     494             : 
     495           0 :     shiftP3 = add( shift, 3 );
     496           0 :     FOR( i = 0; i < lg; i++ )
     497             :     {
     498             :         /* Sum of 2 Q12 values, must give a Q1.8 */
     499           0 :         y1[i] = shr( add( pt1[i], pt2[i] ), shiftP3 );
     500           0 :         move16(); /* Compensate for "shift" */
     501             :     }
     502             : 
     503             :     /*----------------------------------------------------------------*
     504             :      * signs of vectors
     505             :      *----------------------------------------------------------------*/
     506             : 
     507           0 :     sign1 = ( -32768 );
     508           0 :     move16();
     509           0 :     if ( sign[ind1] >= 0 )
     510             :     {
     511           0 :         sign1 = 32767;
     512           0 :         move16();
     513             :     }
     514             : 
     515           0 :     sign2 = ( -32768 );
     516           0 :     move16();
     517           0 :     if ( sign[ind2] >= 0 )
     518             :     {
     519           0 :         sign2 = 32767;
     520           0 :         move16();
     521             :     }
     522             : 
     523             :     /*----------------------------------------------------------------*
     524             :      * Compute code
     525             :      *----------------------------------------------------------------*/
     526             : 
     527           0 :     pt1 = pos[ind1];
     528           0 :     move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */
     529           0 :     pt2 = pos[ind2];
     530           0 :     move16(); /* Points to gaussian vector (gaus_dico_fx) in Q12 */
     531             : 
     532             :     /* sign[ind1] and sign[ind2] */
     533           0 :     FOR( i = 0; i < lg; i++ )
     534             :     {
     535             :         /* code[i]=(pt1[i]*sign1 + pt2[i]*sign2) /8 */
     536             :         /* Division by 8 (shift by 3) is for scaling (Q12 to Q0.9 output) */
     537           0 :         code[i] = shr( add( mult( pt1[i], sign1 ), mult( pt2[i], sign2 ) ), 3 );
     538           0 :         move16();
     539             :     }
     540             : 
     541           0 :     cor = L_add( corr[ind1], corr[ind2] );
     542             : 
     543             :     /*----------------------------------------------------------------*
     544             :      * Compute index
     545             :      *----------------------------------------------------------------*/
     546             : 
     547           0 :     i = (Word16) ( ( pos[ind1] - Gaus_dico2 ) / step ); /* Division by step can be replaced by shift. Pointer arithmetic */
     548           0 :     j = (Word16) ( ( pos[ind2] - Gaus_dico2 ) / step ); /* Division by step can be replaced by shift. Pointer arithmetic */
     549             : 
     550           0 :     idx = cod_2pos_fx( i, j, sign1, sign2, nvec ); /* Q0 */
     551           0 :     move16();
     552             : 
     553           0 :     push_indice( hBstr, IND_GAUS_CDBK_INDEX, idx, 2 * nb_bits + 1 );
     554           0 :     push_indice( hBstr, IND_TILT_FACTOR, index_delta, 3 );
     555             : 
     556             :     /*----------------------------------------------------------------*
     557             :      * Find quantized gain
     558             :      *----------------------------------------------------------------*/
     559             : 
     560             :     /* Divide cor/enerw: intermediate result stored into GainPortion1 */
     561           0 :     cor_neg = 0;
     562           0 :     move16();
     563           0 :     if ( cor < 0 ) /* Make Num positive. */
     564             :     {
     565           0 :         cor_neg = 1;
     566           0 :         move16();
     567             :     }
     568           0 :     cor_abs = L_abs( cor );
     569             : 
     570           0 :     exp_num = sub( norm_l( cor_abs ), 1 );
     571           0 :     exp_den = norm_s( enerw );
     572           0 :     Num = round_fx( L_shl( cor_abs, exp_num ) );
     573           0 :     Den = shl( enerw, exp_den );
     574             : 
     575           0 :     GainPortion1 = L_deposit_l( 0 ); /* Unexpected division by zero. Eliminate this gain contribution */
     576           0 :     IF( Den != 0 )                   /* Protection against division by zero */
     577             :     {
     578           0 :         div_result = div_s( Num, Den ); /* Q15 */
     579           0 :         IF( cor_neg != 0 )
     580             :         {
     581           0 :             div_result = negate( div_result ); /* Retrieve sign */
     582             :         }
     583             :         /* Re-scale to compensate for normalization*/
     584           0 :         GainPortion1 = L_shr( L_deposit_l( div_result ), sub( exp_num, exp_den ) );
     585             :     }
     586             : 
     587           0 :     ener1 = Dot_product( xn, xn, lg ); /* Q12 * Q12 * length of 64 + 1 left shift ==> Q31 */
     588             : 
     589           0 :     exp_num = sub( norm_s( enerw ), 1 );
     590           0 :     exp_den = norm_l( ener1 );
     591           0 :     Num = shl( enerw, exp_num );
     592           0 :     Den = round_fx_sat( L_shl_sat( ener1, exp_den ) );
     593           0 :     GainPortion2 = L_deposit_l( 0 ); /* Unexpected division by zero. Eliminate this gain contribution */
     594           0 :     IF( Den != 0 )                   /* Protection against division by zero */
     595             :     {
     596           0 :         div_result = div_s( Num, Den ); /* Q15 */
     597             : 
     598             :         /* Re-scale to compensate for normalization*/
     599           0 :         GainPortion2 = L_shr_sat( L_deposit_l( div_result ), sub( exp_num, exp_den ) );
     600             :     }
     601             : 
     602           0 :     ener_sqrt = Isqrt( L_shl_sat( GainPortion2, 1 ) ); /* Make value a Q16 prior to division (align on power of 4) */
     603           0 :     ener_sqrt = L_shr( ener_sqrt, 8 );                 /* Left-shift Q23 result to make a Q15 result */
     604             : 
     605           0 :     Portion = Mult_32_16( GainPortion1, 19661 );       /* Performs GainPortion1*.6 */
     606           0 :     Portion = Madd_32_16( Portion, ener_sqrt, 13107 ); /* Performs ener_sqrt*.4 */
     607             : 
     608             :     /* Gain must be output in a 32-bit variable as a Q16 */
     609             :     /* Compensate for Q_new */
     610             : #ifdef ISSUE_1867_replace_overflow_libenc
     611           0 :     *gain = L_shl_sat( Portion, sub( 13, Q_new ) ); /* Q16 */
     612             : #else
     613             :     *gain = L_shl_o( Portion, sub( 13, Q_new ), &Overflow ); /* Q16 */
     614             : #endif
     615           0 :     move32();
     616             : 
     617           0 :     return;
     618             : }
     619             : /*---------------------------------------------------------------------*
     620             :  * Put selected codevector positions and signs into quantization index
     621             :  *---------------------------------------------------------------------*/
     622           0 : static Word16 cod_2pos_fx(                     /* o  :  codebook quantization index             */
     623             :                            const Word16 ind1,  /* i  :  index of 1st gaussian vector    Q0*/
     624             :                            const Word16 ind2,  /* i  :  index of 2nd gaussian vector    Q0*/
     625             :                            const Word16 sign1, /* i  :  sign of 1st gaussian vector             Qx*/
     626             :                            const Word16 sign2, /* i  :  sign of 2nd gaussian vector             Qx*/
     627             :                            const Word16 n      /* i  :  nb. of codebook vectors                 Q0*/
     628             : )
     629             : {
     630             :     Word16 i1, i2, index, s1, s2;
     631           0 :     s1 = 1;
     632           0 :     move16();
     633             : 
     634           0 :     if ( sign1 > 0 )
     635             :     {
     636           0 :         s1 = 0;
     637           0 :         move16();
     638             :     }
     639           0 :     s2 = 1;
     640           0 :     move16();
     641           0 :     if ( sign2 > 0 )
     642             :     {
     643           0 :         s2 = 0;
     644           0 :         move16();
     645             :     }
     646             : 
     647           0 :     IF( EQ_16( s1, s2 ) )
     648             :     {
     649           0 :         IF( LE_16( ind1, ind2 ) )
     650             :         {
     651           0 :             i1 = ind1; /* Q0 */
     652           0 :             move16();
     653           0 :             i2 = ind2; /* Q0 */
     654           0 :             move16();
     655             :         }
     656             :         ELSE
     657             :         {
     658           0 :             i1 = ind2; /* Q0 */
     659           0 :             move16();
     660           0 :             i2 = ind1; /* Q0 */
     661           0 :             move16();
     662             :         }
     663             :     }
     664             :     ELSE
     665             :     {
     666           0 :         IF( GT_16( ind1, ind2 ) )
     667             :         {
     668           0 :             i1 = ind1; /* Q0 */
     669           0 :             move16();
     670           0 :             i2 = ind2; /* Q0 */
     671           0 :             move16();
     672             :         }
     673             :         ELSE
     674             :         {
     675           0 :             i1 = ind2; /* Q0 */
     676           0 :             move16();
     677           0 :             i2 = ind1; /* Q0 */
     678           0 :             move16();
     679           0 :             s1 = s2;
     680           0 :             move16();
     681             :         }
     682             :     }
     683             : 
     684           0 :     index = extract_l( L_mult( i1, n ) );
     685           0 :     index = add( index, shl( i2, 1 ) );
     686           0 :     index = add( index, s1 );
     687             : 
     688           0 :     return index;
     689             : }

Generated by: LCOV version 1.14