LCOV - code coverage report
Current view: top level - lib_enc - q_gain2p_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ e95243e9e67ddeb69dddf129509de1b3d95b402e Lines: 242 272 89.0 %
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             : 
       5             : #include <stdint.h>
       6             : #include <assert.h>
       7             : #include "options.h"
       8             : #include "cnst.h" /* Common constants                     */
       9             : #include "basop_util.h"
      10             : #include "rom_com_fx.h"
      11             : #include "rom_com.h"     /* Common constants                       */
      12             : #include "prot_fx.h"     /* Function prototypes                    */
      13             : #include "prot_fx_enc.h" /* Function prototypes                    */
      14             : #include "basop_util.h"  /* Function prototypes                    */
      15             : 
      16             : static Word16 gain_enc(                     /* o   : quantization pitch index                                    <Q0> */
      17             :                         const Word16 *code, /* i   : algebraic excitation                                        <Q9> */
      18             :                         Word16 lcode,       /* i   : Subframe size in range: 40,64,80                            <Q0> */
      19             :                         Word16 *gain_pit,   /* o   : quantized pitch gain                                       <Q16> */
      20             :                         /* i/o : only func=1,coder_type=1 quantized pitch gain              <Q16> */
      21             :                         Word32 *gain_code,       /* o   : quantized codebook gain                                    <Q16> */
      22             :                         ACELP_CbkCorr *g_coeff,  /* i   : correlations <y1,y1>, -2<xn,y1>,<y2,y2>, -2<xn,y2> and 2<y1,y2>  */
      23             :                         Word16 mean_ener,        /* i   : only func=0: mean_ener defined in open-loop (3 bits)        <Q8> */
      24             :                         const Word16 clip_gain,  /* i   : only func=0,1: gain pitch clipping flag (1 = clipping)      <Q0> */
      25             :                         Word32 *past_gcode,      /* o   : past gain of code                                          <Q16> */
      26             :                         Word16 *gain_inov,       /* o   : Q12 innovation gain                                        <Q12> */
      27             :                         const Word16 coder_type, /* i   : only func=0,1: coder type                                   <Q0> */
      28             :                         const Word16 func_type   /* i   : algorithm: 0=gain_enc_mless, 1=gain_enc_2                   <Q0> */
      29             : );
      30             : 
      31             : /*-------------------------------------------------------------------------*
      32             :  * procedure q_gain2_plus                                                  *
      33             :  * ~~~~~~~~~~~~~~~~~~~~~~                                                  *
      34             :  * Quantization of pitch and codebook gains.                               *
      35             :  * The following routines is Q_gains updated for AMR_WB_PLUS.              *
      36             :  * MA prediction is removed and MEAN_ENER is now quantized with 2 bits and *
      37             :  * transmitted once every ACELP frame to the gains decoder.                *
      38             :  * The pitch gain and the code gain are vector quantized and the           *
      39             :  * mean-squared weighted error criterion is used in the quantizer search.  *
      40             :  *-------------------------------------------------------------------------*/
      41        3060 : void encode_acelp_gains_fx(
      42             :     Word16 *code,
      43             :     Word16 gains_mode,
      44             :     Word16 mean_ener_code,
      45             :     Word16 clip_gain,
      46             :     ACELP_CbkCorr *g_corr,
      47             :     Word16 *gain_pit,
      48             :     Word32 *gain_code,
      49             :     Word16 **pt_indice,
      50             :     Word32 *past_gcode,
      51             :     Word16 *gain_inov,
      52             :     Word16 L_subfr,
      53             :     Word16 *code2,
      54             :     Word32 *gain_code2,
      55             :     Word16 noisy_speech_flag /* i   : noisy speech flag                                            */
      56             : )
      57             : {
      58        3060 :     Word16 index = 0, func_type = 0;
      59        3060 :     move16();
      60        3060 :     move16();
      61             : 
      62             :     BASOP_SATURATE_ERROR_ON_EVS;
      63             : 
      64        3060 :     SWITCH( gains_mode )
      65             :     {
      66        3060 :         case 1:
      67             :         case 2:
      68             :         case 3:
      69             :             /* Memory-less gain coding */
      70        3060 :             gains_mode = sub( gains_mode, 1 );
      71        3060 :             func_type = FUNC_GAIN_ENC_MLESS;
      72        3060 :             move16();
      73        3060 :             BREAK;
      74           0 :         case 4:
      75             :         case 5:
      76           0 :             assert( 0 );
      77             :             BREAK;
      78           0 :         case 6:
      79             :             /* UV gains quantizer (6 bits/subfr) */
      80           0 :             gains_mode = sub( gains_mode, 6 );
      81           0 :             func_type = FUNC_GAIN_ENC_UV;
      82           0 :             move16();
      83           0 :             BREAK;
      84           0 :         case 7:
      85           0 :             gains_mode = sub( gains_mode, 7 );
      86           0 :             func_type = FUNC_GAIN_ENC_GACELP_UV;
      87           0 :             move16();
      88           0 :             BREAK;
      89           0 :         default:
      90           0 :             IVAS_ERROR( IVAS_ERR_INTERNAL, "invalid gains coding for acelp!" );
      91           0 :             func_type = 0;
      92           0 :             move16(); /*To avoid compiler warning*/
      93           0 :             BREAK;
      94             :     }
      95             : 
      96        3060 :     IF( func_type == FUNC_GAIN_ENC_MLESS )
      97             :     {
      98        3060 :         index = gain_enc( code, L_subfr, gain_pit, gain_code, g_corr, mean_ener_code,
      99             :                           clip_gain, past_gcode, gain_inov, gains_mode, func_type );
     100             :     }
     101             :     ELSE
     102             :     {
     103           0 :         index = gain_enc_uv_fx( code, code2, L_subfr, gain_pit, gain_code, gain_code2,
     104             :                                 noisy_speech_flag, g_corr, mean_ener_code, past_gcode, gain_inov, func_type );
     105             :     }
     106             : 
     107        3060 :     move16();
     108        3060 :     **pt_indice = index;
     109        3060 :     ( *pt_indice )++;
     110             : 
     111             :     BASOP_SATURATE_ERROR_OFF_EVS;
     112        3060 : }
     113             : 
     114             : /*---------------------------------------------------------------------*
     115             :  * procedure gain_enc_mless
     116             :  * Quantization of pitch and codebook gains.
     117             :  * - an initial predicted gain, gcode0, is first determined based on
     118             :  *   the predicted scaled innovation energy
     119             :  * - the correction  factor gamma = g_code / gcode0 is then vector quantized
     120             :  *   along with gain_pit
     121             :  * - the mean-squared weighted error criterion is used for the quantizer search
     122             :  *---------------------------------------------------------------------*/
     123             : 
     124        3060 : static Word16 gain_enc(                     /* o   : quantization pitch index                                    <Q0> */
     125             :                         const Word16 *code, /* i   : algebraic excitation                                        <Q9> */
     126             :                         Word16 lcode,       /* i   : Subframe size in range: 40,64,80                            <Q0> */
     127             :                         Word16 *gain_pit,   /* o   : quantized pitch gain                                       <Q16> */
     128             :                         /* i/o : only func=1,coder_type=1 quantized pitch gain              <Q16> */
     129             :                         Word32 *gain_code,       /* o   : quantized codebook gain                                    <Q16> */
     130             :                         ACELP_CbkCorr *g_coeff,  /* i   : correlations <y1,y1>, -2<xn,y1>,<y2,y2>, -2<xn,y2> and 2<y1,y2>  */
     131             :                         Word16 mean_ener,        /* i   : only func=0: mean_ener defined in open-loop (3 bits)        <Q8> */
     132             :                         const Word16 clip_gain,  /* i   : only func=0,1: gain pitch clipping flag (1 = clipping)      <Q0> */
     133             :                         Word32 *past_gcode,      /* o   : past gain of code                                          <Q16> */
     134             :                         Word16 *gain_inov,       /* o   : Q12 innovation gain                                        <Q12> */
     135             :                         const Word16 coder_type, /* i   : only func=0,1: coder type                                   <Q0> */
     136             :                         const Word16 func_type   /* i   : algorithm: 0=gain_enc_mless, 1=gain_enc_2                   <Q0> */
     137             : )
     138             : {
     139             :     Word16 i, j, index, size, min_index, exp_L_tmp1;
     140             :     Word16 gcode0, gcode0_gi, exp_gcode0, exp_sum, exp_code, g_code_shl;
     141             : 
     142             :     Word16 g_code;
     143             :     Word16 coeff0, coeff1, coeff2, coeff3, coeff4, exp_coeff0, exp_coeff1, exp_coeff2, exp_coeff3, exp_coeff4;
     144             :     Word16 shr_coeff0, shr_coeff1, shr_coeff2, shr_coeff3, shr_coeff4;
     145             :     const Word16 *p;
     146             :     const Word16 *t_qua_gain;
     147             :     Word32 L_tmp, dist_min, L_tmp1;
     148             : #ifndef ISSUE_1867_replace_overflow_libenc
     149             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     150             :     Flag Overflow = 0;
     151             :     move16();
     152             : #endif
     153             : #endif
     154             : 
     155             : 
     156        3060 :     assert( ( func_type != FUNC_GAIN_ENC_UV ) && ( func_type != FUNC_GAIN_ENC_GACELP_UV ) );
     157             : 
     158             :     /* Debug test value (not instrumented) */
     159        3060 :     gcode0 = -3000;
     160        3060 :     move16();
     161             : 
     162             :     /*----------------------------------------------------------------*
     163             :      * - calculate the unscaled innovation energy
     164             :      * - calculate the predicted gain code
     165             :      *----------------------------------------------------------------*/
     166             : 
     167             :     /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
     168        3060 :     L_tmp = calc_gain_inov( code, lcode, &L_tmp1, &exp_L_tmp1 );
     169        3060 :     move16();
     170             : #ifdef ISSUE_1867_replace_overflow_libenc
     171        3060 :     *gain_inov = round_fx_sat( L_shl_sat( L_tmp, 15 - 3 ) ); /* gain_inov in Q12 */
     172             : #else
     173             :     *gain_inov = round_fx_o( L_shl_o( L_tmp, 15 - 3, &Overflow ), &Overflow ); /* gain_inov in Q12 */
     174             : #endif
     175        3060 :     move16();
     176             :     /*----------------------------------------------------------------*
     177             :      * calculate the predicted gain code
     178             :      *----------------------------------------------------------------*/
     179        3060 :     IF( func_type == FUNC_GAIN_ENC_MLESS )
     180             :     {
     181             :         /*j = 10 * log10((dot_product(code, code, lcode) + 0.01) / lcode) */
     182        3060 :         j = BASOP_Util_lin2dB( L_tmp1, exp_L_tmp1, 1 ); /* Q8 */
     183             : 
     184             :         /* predicted codebook gain */
     185        3060 :         gcode0 = sub( mean_ener, j ); /* Q8 */
     186             :     }
     187             : 
     188             :     /*----------------------------------------------------------------*
     189             :      *  Compute coefficients needed for the quantization.
     190             :      *
     191             :      *  coeff[0] =    yy1 yy1
     192             :      *  coeff[1] = -2 xn yy1
     193             :      *  coeff[2] =    y2 y2
     194             :      *  coeff[3] = -2 xn y2
     195             :      *  coeff[4] =  2 yy1 y2
     196             :      *
     197             :      * Product <yy1 yy1> and <xn yy1> have been computed in Adpt_enr() and
     198             :      * are in vector g_coeff[].
     199             :      *----------------------------------------------------------------*/
     200             : 
     201        3060 :     coeff0 = g_coeff->y1y1;
     202        3060 :     move16();
     203        3060 :     exp_coeff0 = g_coeff->y1y1_e;
     204        3060 :     move16();
     205        3060 :     coeff2 = g_coeff->y2y2;
     206        3060 :     move16();
     207        3060 :     exp_coeff2 = g_coeff->y2y2_e;
     208        3060 :     move16();
     209             : 
     210        3060 :     coeff1 = g_coeff->xy1;
     211        3060 :     move16();
     212        3060 :     exp_coeff1 = add( g_coeff->xy1_e, 1 );
     213        3060 :     coeff3 = g_coeff->xy2;
     214        3060 :     move16();
     215        3060 :     exp_coeff3 = add( g_coeff->xy2_e, 1 );
     216        3060 :     coeff4 = g_coeff->y1y2;
     217        3060 :     move16();
     218        3060 :     exp_coeff4 = add( g_coeff->y1y2_e, 1 );
     219             : 
     220             :     /*---------------------------------------------------------------*
     221             :      * Decode codebook gain and the adaptive excitation low-pass
     222             :      * filtering factor (Finalize computation )
     223             :      *---------------------------------------------------------------*/
     224             : 
     225             : 
     226             :     /* gcode0 = pow(10, 0.05 * (Es_pred - Ei)) */
     227             :     /*----------------------------------------------------------------*
     228             :      * gcode0 = pow(10.0, gcode0/20)                    gcode in Q8
     229             :      *        = pow(2, 3.321928*gcode0/20)
     230             :      *        = pow(2, 0.166096*gcode0)
     231             :      *----------------------------------------------------------------*/
     232             : 
     233             :     /* Check if gcode0 was uninitialized. */
     234        3060 :     assert( gcode0 != -3000 );
     235             : 
     236        3060 :     L_tmp = L_mult( gcode0, 5443 /*0.166096f Q15*/ );
     237        3060 :     exp_gcode0 = add( 1, extract_l( L_shr( L_tmp, 24 ) ) );
     238        3060 :     L_tmp = L_lshl( L_tmp, 7 );
     239        3060 :     L_tmp = L_and( 0x7FFFFFFF, L_tmp );
     240             : 
     241        3060 :     L_tmp = Pow2( 30, round_fx( L_tmp ) );
     242        3060 :     gcode0 = round_fx( L_tmp );
     243             :     /* exponent of gcode0 = exp_gcode0 */
     244             : 
     245             :     /*-----------------------------------------------------------------*
     246             :      * gain quantization initializations
     247             :      * - find the initial quantization pitch index
     248             :      * - set the gains searching range
     249             :      *----------------------------------------------------------------*/
     250             : 
     251             :     /*----------------------------------------------------------------*
     252             :      * Find the best quantizer
     253             :      *
     254             :      * Before doing the computation we need to align exponents of coeff[]
     255             :      * to be sure to have the maximum precision.
     256             :      *
     257             :      * In the table the pitch gains are in Q14, the code gains are in Q11 and
     258             :      * are multiplied by gcode0 which have been multiplied by 2^exp_gcode0.
     259             :      * Also when we compute g_pitch*g_pitch, g_code*g_code and g_pitch*g_code
     260             :      * we divide by 2^15.
     261             :      * Considering all the scaling above we have:
     262             :      *
     263             :      *   exp_code = exp_gcode0 + 4
     264             :      *   if (func_type == gain_enc_2)
     265             :      *         gcode0 *= gain_inov (in Q12)  => exp_code += 3
     266             :      *
     267             :      *   g_pitch*g_pitch  = +1+1
     268             :      *   g_pitch          = +1
     269             :      *   g_code*g_code    = (2*exp_code)
     270             :      *   g_code           = exp_code
     271             :      *   g_pitch*g_code   = + 1 + exp_code
     272             :      *
     273             :      *   g_pitch*g_pitch * coeff[0]  ;exp_max0 = exp_coeff[0] + 2
     274             :      *   g_pitch         * coeff[1]  ;exp_max1 = exp_coeff[1] + 1
     275             :      *   g_code*g_code   * coeff[2]  ;exp_max2 = exp_coeff[2] + (2*exp_code)
     276             :      *   g_code          * coeff[3]  ;exp_max3 = exp_coeff[3] + exp_code
     277             :      *   g_pitch*g_code  * coeff[4]  ;exp_max4 = exp_coeff[4] + 1 + exp_code
     278             :      *----------------------------------------------------------------*/
     279             : 
     280        3060 :     exp_code = add( exp_gcode0, 4 );
     281             : 
     282        3060 :     exp_coeff0 = add( exp_coeff0, 2 );
     283        3060 :     exp_coeff1 = add( exp_coeff1, 1 );
     284        3060 :     exp_coeff2 = add( exp_coeff2, shl( exp_code, 1 ) );
     285        3060 :     exp_coeff3 = add( exp_coeff3, exp_code );
     286        3060 :     exp_coeff4 = add( exp_coeff4, add( 1, exp_code ) );
     287             : 
     288             :     /* Find maximum exponent */
     289        3060 :     exp_sum = s_max( exp_coeff1, exp_coeff0 );
     290        3060 :     exp_sum = s_max( exp_coeff2, exp_sum );
     291        3060 :     exp_sum = s_max( exp_coeff3, exp_sum );
     292        3060 :     exp_sum = s_max( exp_coeff4, exp_sum );
     293        3060 :     exp_sum = add( exp_sum, 2 );
     294             : 
     295             :     /* Align exponents of summands in loop far below. */
     296        3060 :     shr_coeff0 = sub( exp_sum, exp_coeff0 );
     297        3060 :     shr_coeff1 = sub( exp_sum, exp_coeff1 );
     298        3060 :     shr_coeff2 = sub( exp_sum, exp_coeff2 );
     299        3060 :     shr_coeff3 = sub( exp_sum, exp_coeff3 );
     300        3060 :     shr_coeff4 = sub( exp_sum, exp_coeff4 );
     301             :     /* Codebook search */
     302             : 
     303        3060 :     dist_min = L_deposit_h( MAX_16 );
     304             : 
     305        3060 :     min_index = 0;
     306        3060 :     move16();
     307             : 
     308             :     {
     309             :         Word16 size_clip;
     310             : 
     311             : 
     312        3060 :         IF( coder_type == 0 )
     313             :         {
     314             : 
     315           0 :             t_qua_gain = E_ROM_qua_gain5b_const;
     316           0 :             size_clip = 9;
     317           0 :             size = NB_QUA_GAIN5B;
     318             :         }
     319        3060 :         ELSE IF( coder_type == 1 )
     320             :         {
     321             : 
     322         135 :             t_qua_gain = E_ROM_qua_gain6b_const;
     323         135 :             size_clip = 6;
     324         135 :             size = NB_QUA_GAIN6B; /* searching range of the gain quantizer */
     325             :         }
     326             :         ELSE
     327             :         {
     328             : 
     329        2925 :             t_qua_gain = E_ROM_qua_gain7b_const;
     330        2925 :             size_clip = 21;
     331        2925 :             size = NB_QUA_GAIN7B;
     332             :         }
     333        3060 :         move16();
     334        3060 :         move16();
     335             : 
     336        3060 :         if ( EQ_16( clip_gain, 1 ) )
     337             :         {
     338           0 :             size = sub( size, size_clip ); /* limit pitch gain  to 1.0 */
     339             :         }
     340        3060 :         gcode0_gi = gcode0;
     341        3060 :         move16();
     342             :     }
     343        3060 :     p = t_qua_gain;
     344             : 
     345        3060 :     index = 0;
     346        3060 :     move16();
     347             : 
     348             :     /* divide all coeff1,2,3,4 by coeff0 */
     349             :     /* in order to skip multiplication with coeff0 in loop */
     350        3060 :     assert( coeff0 >= 0x4000 );
     351        3060 :     coeff0 = div_s( 0x4000, coeff0 );
     352        3060 :     coeff1 = mult_r( coeff1, coeff0 );
     353        3060 :     coeff2 = mult_r( coeff2, coeff0 );
     354        3060 :     coeff3 = mult_r( coeff3, coeff0 );
     355        3060 :     coeff4 = mult_r( coeff4, coeff0 );
     356             : 
     357      386100 :     FOR( i = 0; i < size; i++ )
     358             :     {
     359             :         /*
     360             :            Note: gcode0_gi: either gcode0 or gcode0*gain_inov
     361             :            g_pitch = *p++;
     362             :            g_code = gcode0_gi * *p++;
     363             : 
     364             :            dist = g_pitch*g_pitch * coeff.y1y1
     365             :            + g_pitch        * coeff.xy1 (negated)
     366             :            + g_code*g_code  * coeff.y2y2
     367             :            + g_code         * coeff.xy2 (negated)
     368             :            + g_pitch*g_code * coeff.y1y2;
     369             :         */
     370             : 
     371             :         /* Since g_code has a significant dynamic, we prefer to normalize this 16-bit value */
     372      383040 :         g_code_shl = norm_s( p[2 * i + 1] );
     373      383040 :         g_code = shl( p[2 * i + 1], g_code_shl );
     374      383040 :         g_code = mult_r( g_code, gcode0_gi );
     375             :         BASOP_SATURATE_WARNING_OFF_EVS /* needed to skip overflow warnings due to exceeding shift values */
     376      383040 :             L_tmp = L_shr( Mpy_32_16_1( L_mult( g_code, g_code ), coeff2 ), shr_coeff2 );
     377      383040 :         if ( g_code_shl != 0 )
     378      374130 :             L_tmp = L_shr( L_tmp, g_code_shl );
     379      383040 :         L_tmp = L_sub( L_tmp, L_shr( L_mult( g_code, coeff3 ), shr_coeff3 ) );
     380      383040 :         L_tmp = L_add( L_tmp, L_shr( Mpy_32_16_1( L_mult( g_code, p[2 * i + 0] ), coeff4 ), shr_coeff4 ) );
     381      383040 :         if ( g_code_shl != 0 )
     382      374130 :             L_tmp = L_shr( L_tmp, g_code_shl );
     383             :         /* Here, we use L_mult0 to compensate the factor 0.5 applied to coeff[1..4] before */
     384      383040 :         L_tmp = L_add( L_tmp, L_shr( L_mult0( p[2 * i + 0], p[2 * i + 0] ), shr_coeff0 ) );
     385      383040 :         L_tmp = L_sub( L_tmp, L_shr( L_mult( p[2 * i + 0], coeff1 ), shr_coeff1 ) );
     386             : #ifdef ISSUE_1867_replace_overflow_libenc
     387      383040 :         L_tmp1 = L_sub_sat( L_tmp, dist_min );
     388             : #else
     389             :         L_tmp1 = L_sub_o( L_tmp, dist_min, &Overflow );
     390             : #endif
     391             :         BASOP_SATURATE_WARNING_ON_EVS
     392      383040 :         if ( L_tmp1 < 0 )
     393             :         {
     394       62796 :             index = i;
     395       62796 :             move16();
     396             :         }
     397      383040 :         if ( L_tmp1 < 0 )
     398             :         {
     399       62796 :             dist_min = L_min( L_tmp, dist_min );
     400             :         }
     401             :     }
     402        3060 :     index = add( index, min_index );
     403        3060 :     *gain_pit = t_qua_gain[2 * index + 0];
     404        3060 :     move16();
     405        3060 :     g_code = t_qua_gain[2 * index + 1];
     406        3060 :     move16();
     407             : 
     408        3060 :     L_tmp = L_mult( g_code, gcode0 ); /* Q11*Q15 -> Q27 */
     409        3060 :     exp_gcode0 = add( exp_gcode0, -11 );
     410             : #ifdef ISSUE_1867_replace_overflow_libenc
     411        3060 :     L_tmp = L_shl_sat( L_tmp, exp_gcode0 ); /*   Q27 -> Q16 */
     412             : #else
     413             :     L_tmp = L_shl_o( L_tmp, exp_gcode0, &Overflow ); /*   Q27 -> Q16 */
     414             : #endif
     415             : 
     416        3060 :     *gain_code = L_tmp;
     417        3060 :     move32();
     418             :     /* Q16/Q12 => Q5 */
     419        3060 :     L_tmp = L_deposit_h( BASOP_Util_Divide3216_Scale( L_tmp, *gain_inov, &i ) );
     420             : #ifdef ISSUE_1867_replace_overflow_libenc
     421        3060 :     *past_gcode = L_shl_sat( L_tmp, sub( i, 15 - 12 ) );
     422             : #else
     423             :     *past_gcode = L_shl_o( L_tmp, sub( i, 15 - 12 ), &Overflow );
     424             : #endif
     425        3060 :     move16();
     426             : 
     427        3060 :     return index;
     428             : }
     429             : 
     430        8060 : Word16 gain_enc_uv_fx(                           /* o   : quantization pitch index                                    <Q0> */
     431             :                        const Word16 *code,       /* i   : algebraic excitation                                        <Q9> */
     432             :                        const Word16 *code2,      /* i   : gaussian excitation                                         <Q9> */
     433             :                        Word16 lcode,             /* i   : Subframe size in range: 40,64,80                            <Q0> */
     434             :                        Word16 *gain_pit,         /* o   : quantized pitch gain                                       <Q16> */
     435             :                        Word32 *gain_code,        /* o   : quantized codebook gain                                    <Q16> */
     436             :                        Word32 *gain_code2,       /* o   : quantized codebook gain                                    <Q16> */
     437             :                        Word16 noisy_speech_flag, /* i   : noisy speech flag                                                */
     438             :                        ACELP_CbkCorr *g_coeff,   /* i   : correlations <y1,y1>, -2<xn,y1>,<y2,y2>, -2<xn,y2> and 2<y1,y2>  */
     439             :                        Word16 mean_ener,         /* i   : only func=0: mean_ener defined in open-loop (3 bits)        <Q8> */
     440             :                        Word32 *past_gcode,       /* o   : past gain of code                                          <Q16> */
     441             :                        Word16 *gain_inov,        /* o   : Q12 innovation gain                                        <Q12> */
     442             :                        const Word16 func_type    /* i   : algorithm: 2=gain_enc_uv_fx, 3=gain_enc_gacelp_uv              <Q0> */
     443             : )
     444             : {
     445             :     Word16 i, index, exp_L_tmp1, tmp;
     446             :     Word16 exp_gcode;
     447             :     Word16 g_code;
     448             :     Word32 L_tmp, L_tmp1;
     449             :     Word8 gacelp_uv;
     450             :     Word32 pred_nrg_frame;
     451             :     Word16 exp_gcode2, g_code2, norm_code2;
     452             :     Word16 c, c_e, c_index2, c_index2_e, c_first, c_first_e;
     453             :     Word16 s, tmp1, s1;
     454             :     Word16 index2;
     455        8060 :     const Word16 log2_scale = 16;
     456        8060 :     move16();
     457             : #ifndef ISSUE_1867_replace_overflow_libenc
     458             : #ifdef BASOP_NOGLOB_DECLARE_LOCAL
     459             :     Flag Overflow = 0;
     460             :     move16();
     461             : #endif
     462             : #endif
     463        8060 :     pred_nrg_frame = 0; /* to suppress compilation warnings */
     464        8060 :     g_code2 = 0;        /* to suppress compilation warnings */
     465        8060 :     exp_gcode2 = 0;     /* to suppress compilation warnings */
     466        8060 :     move32();
     467        8060 :     move16();
     468        8060 :     move16();
     469             : 
     470             : 
     471        8060 :     assert( ( func_type != FUNC_GAIN_ENC_MLESS ) );
     472             : 
     473             :     /* Debug check value (not instrumented) */
     474        8060 :     index2 = -3000;
     475        8060 :     move16();
     476             : 
     477        8060 :     gacelp_uv = 0;
     478        8060 :     move16();
     479        8060 :     if ( EQ_16( func_type, FUNC_GAIN_ENC_GACELP_UV ) )
     480             :     {
     481        8060 :         gacelp_uv = 1;
     482        8060 :         move16();
     483             :     }
     484             : 
     485             :     /*----------------------------------------------------------------*
     486             :      * - calculate the unscaled innovation energy
     487             :      * - calculate the predicted gain code
     488             :      *----------------------------------------------------------------*/
     489             : 
     490             :     /* gain_inov = 1.0f / sqrt((dot_product(code, code, L_SUBFR) + 0.01) / L_SUBFR) */
     491        8060 :     L_tmp = calc_gain_inov( code, lcode, NULL, NULL );
     492        8060 :     *gain_inov = round_fx( L_shl( L_tmp, 15 - 3 ) ); /* gain_inov in Q12 */
     493        8060 :     move16();
     494             : 
     495             :     /*----------------------------------------------------------------*
     496             :      * calculate the predicted gain code
     497             :      *----------------------------------------------------------------*/
     498        8060 :     IF( gacelp_uv != 0 )
     499             :     {
     500             :         /* pred_nrg_frame = (float)pow(10.0,mean_ener/20.0); */
     501        8060 :         L_tmp = L_mult( mean_ener, 10885 /*0.166096f * 2 Q15*/ );                       /* 6Q25 */
     502        8060 :         pred_nrg_frame = BASOP_Util_InvLog2( L_sub( L_tmp, 503316480l /*15.f Q25*/ ) ); /* 15Q16 */
     503             : 
     504             :         /* gcode = pred_nrg_frame * (*gain_inov); */
     505        8060 :         L_tmp = Mpy_32_16_1( pred_nrg_frame, *gain_inov ); /* 18Q13 */
     506        8060 :         i = norm_l( L_tmp );
     507        8060 :         g_code = round_fx_sat( L_shl( L_tmp, i ) );
     508        8060 :         exp_gcode = sub( 18, i );
     509             : 
     510             :         /* norm_code2 = 1.0f / sqrt((dot_product(code2, code2, lcode) + 0.01f) / lcode); */
     511        8060 :         L_tmp = calc_gain_inov( code2, lcode, NULL, NULL );
     512        8060 :         norm_code2 = round_fx( L_shl( L_tmp, 15 - 3 ) ); /* Q12 */
     513             : 
     514             :         /* g_code2 = pred_nrg_frame * norm_code2; */
     515        8060 :         L_tmp = Mpy_32_16_1( pred_nrg_frame, norm_code2 ); /* 18Q13 */
     516        8060 :         i = norm_l( L_tmp );
     517        8060 :         g_code2 = round_fx_sat( L_shl_sat( L_tmp, i ) );
     518        8060 :         exp_gcode2 = sub( 18, i );
     519             :     }
     520             :     ELSE
     521             :     {
     522           0 :         g_code = *gain_inov;
     523           0 :         move16();
     524           0 :         exp_gcode = 3;
     525           0 :         move16();
     526             :     }
     527             : 
     528        8060 :     tmp = BASOP_Util_Divide1616_Scale( g_coeff->xy2, mult_r( g_coeff->y2y2, g_code ), &i ); /*Correlation based*/
     529        8060 :     L_tmp = L_shl( L_deposit_h( tmp ), add( i, sub( g_coeff->xy2_e, add( g_coeff->y2y2_e, add( exp_gcode, log2_scale ) ) ) ) );
     530             :     /* exponent of L_tmp is 16, accounted below by adding log2(2^16) */
     531             : 
     532        8060 :     index = 0;
     533        8060 :     move16();
     534             : 
     535        8060 :     IF( L_tmp > 0 )
     536             :     {
     537             :         /*index = (int)(((20.f*log10(g_code)+30.f)/1.9f)+0.5f))); */
     538             :         /* Since ((20*log10(x)+30)/1.9)+0.5 = 63 (max index) implies x is between 2^15 and 2^16,
     539             :            L_tmp might saturate at 65535 and above. That is why log2_scale is 16. */
     540        8060 :         tmp = BASOP_Util_lin2dB( L_tmp, 16, 0 ); /* Q8 */
     541             : 
     542        8060 :         IF( gacelp_uv != 0 )
     543             :         {
     544        8060 :             L_tmp = L_mult( add( tmp, 5120 /*20.0f Q8*/ ), 26214 /*1.0f/1.25f Q15*/ );
     545             :         }
     546             :         ELSE
     547             :         {
     548           0 :             L_tmp = L_mult( add( tmp, 7680 /*30.0f Q8*/ ), 17246 /*1.0f/1.9f Q15*/ );
     549             :         }
     550             : 
     551        8060 :         index = round_fx( L_shr( L_tmp, 8 ) );
     552        8060 :         index = s_max( 0, s_min( 63, index ) );
     553        8060 :         if ( gacelp_uv != 0 )
     554        8060 :             index = s_min( 31, index );
     555             :     }
     556             : 
     557             :     /* *gain_code= (float) pow(10.f,(((index*1.9f)-30.f)/20.f)); */
     558             : 
     559             :     /*----------------------------------------------------------------*
     560             :      * gcode0 = pow(10.0, gcode0/20)
     561             :      *        = pow(2, 3.321928*gcode0/20)
     562             :      *        = pow(2, 0.166096*gcode0)
     563             :      *----------------------------------------------------------------*/
     564        8060 :     IF( gacelp_uv != 0 )
     565             :     {
     566        8060 :         L_tmp = L_mac( -111465139l /*-0.166096*20.0f Q25*/, shl( index, 16 - 7 ), 6803 /*0.166096f*1.25f Q15*/ );
     567             :     }
     568             :     ELSE
     569             :     {
     570           0 :         L_tmp = L_mac( -167197708l /*-0.166096*30.0f Q25*/, shl( index, 16 - 7 ), 10341 /*0.166096f*1.9f Q15*/ );
     571             :     }
     572        8060 :     i = add( 1, extract_l( L_shr( L_tmp, 25 ) ) );
     573        8060 :     L_tmp = L_lshl( L_tmp, 6 );
     574        8060 :     L_tmp = L_and( 0x7FFFFFFF, L_tmp );
     575             : 
     576        8060 :     L_tmp = Pow2( 30, round_fx( L_tmp ) );
     577        8060 :     L_tmp = L_shl( L_tmp, sub( i, ( 31 - 16 ) ) ); /* Q16 */
     578             : 
     579        8060 :     IF( gacelp_uv != 0 )
     580             :     {
     581             :         /* *past_gcode = L_tmp * pred_nrg_frame; */
     582        8060 :         i = norm_l( L_tmp );
     583        8060 :         L_tmp1 = L_shl( L_tmp, i );
     584        8060 :         exp_L_tmp1 = sub( 15, i );
     585             : 
     586        8060 :         i = norm_l( pred_nrg_frame );
     587        8060 :         L_tmp1 = Mpy_32_32( L_tmp1, L_shl( pred_nrg_frame, i ) );
     588        8060 :         exp_L_tmp1 = add( exp_L_tmp1, sub( 15, i ) );
     589             : 
     590        8060 :         *past_gcode = L_shl( L_tmp1, sub( exp_L_tmp1, 15 ) ); /* Q16 */
     591        8060 :         move32();
     592             :     }
     593             :     ELSE
     594             :     {
     595           0 :         *past_gcode = L_tmp; /*unscaled gain*/
     596           0 :         move32();
     597             :     }
     598             : 
     599             : 
     600        8060 :     *gain_code = L_shl_sat( Mpy_32_16_1( *past_gcode, *gain_inov ), 3 );
     601        8060 :     move32();
     602             : 
     603        8060 :     *gain_pit = 0;
     604        8060 :     move16();
     605             : 
     606        8060 :     IF( gacelp_uv != 0 )
     607             :     {
     608             :         /* c_first = 0.8f*g_coeff->xx - (*gain_code) * (*gain_code) * g_coeff->y2y2; */
     609             :         /* c_first = g_coeff->xx - (*gain_code) * (*gain_code) * g_coeff->y2y2; */
     610        8060 :         tmp = g_coeff->xx;
     611        8060 :         move16();
     612        8060 :         if ( noisy_speech_flag != 0 )
     613             :         {
     614         532 :             tmp = mult_r( 26214 /*0.8f Q15*/, tmp );
     615             :         }
     616             : 
     617        8060 :         s1 = norm_l( *gain_code );
     618             : #ifdef ISSUE_1867_replace_overflow_libenc
     619        8060 :         tmp1 = round_fx_sat( L_shl( *gain_code, s1 ) );
     620             : #else
     621             :         tmp1 = round_fx_o( L_shl_o( *gain_code, s1, &Overflow ), &Overflow );
     622             : #endif
     623        8060 :         s1 = sub( 15, s1 );
     624        8060 :         tmp1 = mult_r( mult_r( tmp1, tmp1 ), g_coeff->y2y2 );
     625             : 
     626        8060 :         c_first_e = BASOP_Util_Add_MantExp( tmp, g_coeff->xx_e,
     627        8060 :                                             negate( tmp1 ), add( g_coeff->y2y2_e, shl( s1, 1 ) ),
     628             :                                             &c_first );
     629             : 
     630        8060 :         L_tmp = Mpy_32_16_1( *gain_code, BASOP_Util_Divide1616_Scale( g_code2, g_code, &s ) );
     631        8060 :         L_tmp = L_shl( L_tmp, sub( sub( add( s, exp_gcode2 ), exp_gcode ), 2 ) ); /* Q16 */
     632        8060 :         L_tmp1 = L_add( L_tmp, 0 );
     633             : 
     634        8060 :         s1 = norm_l( *gain_code );
     635             : #ifdef ISSUE_1867_replace_overflow_libenc
     636        8060 :         tmp1 = round_fx_sat( L_shl( *gain_code, s1 ) );
     637             : #else
     638             :         tmp1 = round_fx_o( L_shl_o( *gain_code, s1, &Overflow ), &Overflow );
     639             : #endif
     640        8060 :         s1 = sub( 15, s1 );
     641             : 
     642        8060 :         c_index2 = 0x7FFF;
     643        8060 :         move16();
     644        8060 :         c_index2_e = 127;
     645        8060 :         move16();
     646       40300 :         FOR( i = 0; i < 4; i++ )
     647             :         {
     648             :             /* c = c_first - L_tmp1 * (L_tmp1 * g_coeff->y1y1 + 2 * (*gain_code) * g_coeff->y1y2); */
     649       32240 :             s = norm_l( L_tmp1 );
     650       32240 :             tmp = round_fx_sat( L_shl_sat( L_tmp1, s ) );
     651       32240 :             s = sub( 15, s );
     652             : 
     653       32240 :             c_e = BASOP_Util_Add_MantExp( mult_r( tmp, g_coeff->y1y1 ), add( s, g_coeff->y1y1_e ),
     654       32240 :                                           mult_r( tmp1, g_coeff->y1y2 ), add( add( s1, g_coeff->y1y2_e ), 1 ),
     655             :                                           &c );
     656       32240 :             c = mult_r( c, tmp );
     657       32240 :             c_e = add( c_e, s );
     658       32240 :             c_e = BASOP_Util_Add_MantExp( c_first, c_first_e, negate( c ), c_e, &c );
     659             : 
     660       32240 :             tmp = 0;
     661       32240 :             move16();
     662       32240 :             if ( LT_16( c_e, c_index2_e ) )
     663             :             {
     664       17678 :                 tmp = 1;
     665       17678 :                 move16();
     666             :             }
     667       32240 :             test();
     668       32240 :             if ( EQ_16( c_e, c_index2_e ) && LT_16( abs_s( c ), abs_s( c_index2 ) ) )
     669             :             {
     670        9190 :                 tmp = 1;
     671        9190 :                 move16();
     672             :             }
     673             : 
     674       32240 :             IF( tmp != 0 )
     675             :             {
     676       26868 :                 index2 = i;
     677       26868 :                 move16();
     678       26868 :                 c_index2 = c;
     679       26868 :                 move16();
     680       26868 :                 c_index2_e = c_e;
     681       26868 :                 move16();
     682       26868 :                 *gain_code2 = L_tmp1;
     683       26868 :                 move32();
     684             :             }
     685             : 
     686       32240 :             L_tmp1 = L_add( L_tmp1, L_tmp );
     687             :         }
     688             : 
     689             :         /* check if value was uninitialized */
     690        8060 :         assert( index2 != -3000 );
     691        8060 :         index = add( index, shl( index2, 5 ) );
     692             :     }
     693             : 
     694             : 
     695        8060 :     return index;
     696             : }

Generated by: LCOV version 1.14