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

Generated by: LCOV version 1.14