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

Generated by: LCOV version 1.14