LCOV - code coverage report
Current view: top level - lib_dec - FEC_clas_estim_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 341 405 84.2 %
Date: 2025-05-03 01:55:50 Functions: 4 4 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 "options.h" /* Compilation switches                   */
       7             : #include "cnst.h"    /* Common constants                       */
       8             : #include "rom_com.h" /* Static table prototypes                */
       9             : #include "prot_fx.h" /* Function prototypes                    */
      10             : #include "basop_util.h"
      11             : 
      12             : /*-------------------------------------------------------------------*
      13             :  * Local function prototypes
      14             :  *-------------------------------------------------------------------*/
      15             : static Word16 FEC_dec_class_fx( Decoder_State *st_fx, Word32 *enr_q );
      16             : static void Corre( const Word16 *x, const Word16 *y, const Word16 l, Word16 *gain );
      17             : 
      18             : /*---------------------------------------------------------------------*
      19             :  * Local Constants
      20             :  *---------------------------------------------------------------------*/
      21             : #define UNS6 10923 / 2
      22             : #define UNS5 13107 / 2
      23             : 
      24             : #define K_COR_FX 14004     /* Q14      0.8547f   <-0.29, 0.88> */
      25             : #define C_COR_FX 266180599 /* Q14+16   0.2479f                 */
      26             : 
      27             : #define K_TILT_FX 13653     /*Q14       0.8333f   <-0.35, 0.85> */
      28             : #define C_TILT_FX 313210491 /*Q14+16    0.2917f                 */
      29             : 
      30             : #define K_ZC_FX -1310   /*Q15       -0.04f     <63, 38>     */
      31             : #define C_ZC_FX 2642416 /*11Q20     2.52                    */
      32             : 
      33             : #define K_ENR_FX 1311    /*Q15       0.04        <-14, 11>   */
      34             : #define C_ENR_FX 9395241 /*Q8+16     0.56f                   */
      35             : 
      36             : #define K_PC_FX -1169  /*Q15       -0.0357f    <45, 17>    */
      37             : #define C_PC_FX 105323 /*Q0+16     1.6071f                 */
      38             : 
      39             : 
      40             : /*======================================================================*/
      41             : /* FUNCTION : FEC_clas_estim()                                          */
      42             : /*----------------------------------------------------------------------*/
      43             : /* PURPOSE :  Estimation of classification                              */
      44             : /*        information, if not available in the bitsream                 */
      45             : /*                                                                      */
      46             : /*======================================================================*/
      47             : 
      48      254310 : void FEC_clas_estim_fx(
      49             :     Decoder_State *st_fx, /* i/o: decoder state handle                    */
      50             :     const Word16 Opt_AMR_WB,
      51             :     /* i  : flag indicating AMR-WB IO mode          */ /*A*/
      52             :     const Word16 L_frame,                              /* i  : length of the frame                     */
      53             :     Word16 *clas,                                      /* i/o: frame classification                    */
      54             :     const Word16 coder_type,                           /* i  : coder type                              */
      55             :     const Word16 *pitch,                               /* i  : pitch values for each subframe      (Q6)*/
      56             :     Word16 *syn,                                       /* i  : synthesis buffer                        */
      57             :     Word16 *lp_speech,                                 /* i/o: long term active speech energy average Q8 */
      58             :     Word16 *decision_hyst,
      59             :     /* i/o: hysteresis of the music/speech decision */ /*A*/
      60             :     Word16 *UV_cnt,
      61             :     /* i/o: number of consecutives frames classified as UV */ /*A*/
      62             :     Word16 *LT_UV_cnt,                                        // Q6
      63             :     /* i/o: long term consecutives frames classified as UV */ /*A*/
      64             :     Word16 *Last_ener,                                        // Q8
      65             :     /* i/o: last_energy frame                       */        /*A*/
      66             :     Word16 *locattack,
      67             :     /* i/o: detection of attack (mainly to localized speech burst) */ /*A*/
      68             :     Word16 *lt_diff_etot,                                             // Q8
      69             :     /* i/o: long-term total energy variation        */                /*A*/
      70             :     Word16 *amr_io_class,
      71             :     /* i/o: classification for AMR-WB IO mode       */ /*A*/
      72             :     Word16 Q_syn,                                      /* i  : Synthesis scaling                       */
      73             :     Word16 *class_para,                                // Q14
      74             :     /* o  : classification para. fmerit1            */ /*A*/
      75             :     Word16 *mem_syn_clas_estim,                        /* i/o: memory of the synthesis signal for frame class estimation */
      76             :     Word16 *Q_mem_syn,
      77             :     /* i/o: exponent for memory of synthesis signal for frame class estimation */ /*B*/
      78             :     Word16 LTP_Gain,
      79             :     /* i  : LTP gain is 0..0.6 or -1  Q15                                       */ /*B*/
      80             :     Word16 mode,
      81             :     /* i  : signal classifier mode                                              */ /*B*/
      82             :     Word16 bfi,
      83             :     /* i  : bad frame indicator                                                 */ /*B*/
      84             :     Word32 last_core_brate,                                                        /* i  : bitrate of previous frame                                           */
      85             :     const Word16 FEC_mode                                                          /* i  : ACELP FEC mode                                 */
      86             : )
      87             : {
      88             :     Word16 i, j, pos;
      89      254310 :     Word16 *pt1, *pt2, zc_frame, frame_ener = 1, tmp_scale = 0, tmp_scale_syn, tmp_scale_mem;
      90      254310 :     Word16 tiltn, corn, zcn, pcn, fmerit1, enern, ener = 0 /*not necessary, just to quiet a warning so not cmplxty counted*/, tilt, diff_ener;
      91             :     Word16 voicing, cor_max[4], *synth, tmp16, exp1, exp2;
      92             :     Word32 Ltmp, Ltmp1;
      93             :     Word16 tmpS, T0, pc, /*max,*/ tmp_x, tmp_y;
      94             :     Word16 old_synth[L_SYN_MEM_CLAS_ESTIM + L_FRAME16k];
      95             :     Word16 nb_subfr;
      96             :     Word16 pos_limit;
      97             :     Word16 codec_mode, narrowBand, tcxonly, preemph_fac;
      98             :     Word16 memmax;
      99      254310 :     move16();
     100      254310 :     move16();
     101      254310 :     move16();
     102             : 
     103      254310 :     nb_subfr = shr( L_frame, 6 );
     104      254310 :     memmax = 0;
     105      254310 :     move16();
     106      254310 :     tmp_scale_syn = 0;
     107      254310 :     move16();
     108             : 
     109      254310 :     codec_mode = st_fx->codec_mode;
     110      254310 :     move16();
     111      254310 :     tcxonly = st_fx->tcxonly; /* i  : tcxonly flag          */ /*B*/
     112      254310 :     move16();
     113      254310 :     narrowBand = st_fx->narrowBand; /* i  : narrowband flag       */ /*B*/
     114      254310 :     move16();
     115      254310 :     preemph_fac = st_fx->preemph_fac; /* i  : preemphasis factor    */ /*B*/
     116      254310 :     move16();
     117             :     /*------------------------------------------------------------------------*
     118             :      * Copy synthesized into local buffer
     119             :      *------------------------------------------------------------------------*/
     120             : 
     121             :     /* After Rate Switching st->last_core is reset to 0. Check for last_core_brate is needed */
     122      254310 :     test();
     123      254310 :     test();
     124      254310 :     test();
     125      254310 :     test();
     126      254310 :     test();
     127      254310 :     test();
     128      254310 :     test();
     129      254310 :     test();
     130      254310 :     test();
     131      254310 :     test();
     132      254310 :     test();
     133      254310 :     test();
     134      254310 :     IF( ( EQ_32( last_core_brate, SID_1k75 ) || EQ_32( last_core_brate, ACELP_6k60 ) || EQ_32( last_core_brate, ACELP_8k85 ) || EQ_32( last_core_brate, ACELP_12k65 ) || EQ_32( last_core_brate, ACELP_14k25 ) || EQ_32( last_core_brate, ACELP_15k85 ) || EQ_32( last_core_brate, ACELP_18k25 ) || EQ_32( last_core_brate, ACELP_19k85 ) || EQ_32( last_core_brate, ACELP_23k05 ) || EQ_32( last_core_brate, ACELP_23k85 ) ) && !Opt_AMR_WB && EQ_16( codec_mode, MODE2 ) && GT_16( L_frame, L_FRAME ) )
     135             :     {
     136             :         Word16 oldLenClasBuff, newLenClasBuff;
     137         669 :         oldLenClasBuff = extract_l( L_shr( Mpy_32_16_1( L_mult0( st_fx->last_L_frame, getInvFrameLen( st_fx->L_frame ) /*Q21*/ ) /*Q21*/, L_SYN_MEM_CLAS_ESTIM /*Q0*/ ) /*Q6*/, 6 ) /*Q0*/ );
     138         669 :         newLenClasBuff = L_SYN_MEM_CLAS_ESTIM;
     139         669 :         move16();
     140         669 :         lerp( &mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM - oldLenClasBuff], &mem_syn_clas_estim[L_SYN_MEM_CLAS_ESTIM - newLenClasBuff], newLenClasBuff, oldLenClasBuff );
     141             :     }
     142      254310 :     synth = old_synth + L_SYN_MEM_CLAS_ESTIM;
     143             : 
     144             :     /*Rescale synthesis mem buffer or synthesis buffer, if necessary -
     145             :     allign them to the same scaling in case of switching MODE2->MODE1*/
     146      254310 :     IF( EQ_16( codec_mode, MODE2 ) )
     147             :     {
     148      114184 :         memmax = 1;
     149      114184 :         move16();
     150             :         /*find maximum of mem syn*/
     151    29573656 :         FOR( i = 0; i < L_SYN_MEM_CLAS_ESTIM; i++ )
     152             :         {
     153    29459472 :             memmax = s_max( memmax, mem_syn_clas_estim[i] );
     154             :         }
     155             : 
     156      114184 :         tmp_scale = sub( *Q_mem_syn, Q_syn );
     157      114184 :         IF( tmp_scale > 0 ) /*mem syn is bigger, scale it down*/
     158             :         {
     159        4723 :             tmp_scale_mem = negate( tmp_scale );
     160        4723 :             Scale_sig( mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, tmp_scale_mem );
     161             :         }
     162             :         ELSE /*synthesis is bigger, scale it down*/
     163             :         {
     164             :             /*check for upscaling mem syn, first*/
     165      109461 :             tmp_scale_mem = norm_s( sub( memmax, 1 ) );
     166      109461 :             if ( EQ_16( memmax, 1 ) )
     167             :             {
     168        4696 :                 tmp_scale_mem = 14;
     169        4696 :                 move16();
     170             :             }
     171      109461 :             tmp_scale_syn = sub( add( *Q_mem_syn, tmp_scale_mem ), Q_syn ); /*if this is negative, syn can be scaled down*/
     172      109461 :             test();
     173      109461 :             IF( tmp_scale_syn > 0 || EQ_16( mode, 1 /*CLASSIFIER_TCX*/ ) ) /*dont scale up syn, but scale mem_syn, adequately*/
     174             :             {
     175      109461 :                 tmp_scale_mem = sub( tmp_scale_mem, tmp_scale_syn );
     176      109461 :                 tmp_scale_syn = 0;
     177      109461 :                 move16();
     178             :             }
     179             : 
     180      109461 :             Scale_sig( mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, tmp_scale_mem );
     181      109461 :             *Q_mem_syn = add( *Q_mem_syn, tmp_scale_mem );
     182      109461 :             move16();
     183             :         }
     184             :     }
     185             : 
     186      254310 :     tmp_scale = -1;
     187      254310 :     move16();
     188             : 
     189      254310 :     Copy_Scale_sig( mem_syn_clas_estim, old_synth, L_SYN_MEM_CLAS_ESTIM, tmp_scale );
     190      254310 :     Copy_Scale_sig( syn, synth, L_frame, add( tmp_scale_syn, tmp_scale ) );
     191             : 
     192             :     /*Tell MODE2 decoder the scaling of the buffer*/
     193      254310 :     *Q_mem_syn = add( add( Q_syn, tmp_scale_syn ), tmp_scale );
     194      254310 :     move16();
     195             : 
     196             :     /**Q_mem_syn = *Q_syn;  move16();*/
     197             : 
     198      254310 :     test();
     199      254310 :     IF( EQ_16( codec_mode, MODE2 ) && EQ_16( mode, 1 /*CLASSIFIER_TCX*/ ) )
     200             :     {
     201             :         /* TCX outputs non-pe-speech */
     202      113574 :         move16();
     203      113574 :         tmp16 = shl( syn[-1], tmp_scale ); /*dont forget to scale the mem*/
     204      113574 :         preemph_copy_fx( synth, synth, preemph_fac, L_frame, &tmp16 );
     205             :     }
     206             : 
     207             :     /*------------------------------------------------------------------------*
     208             :      * GC, TC and AC frames
     209             :      *------------------------------------------------------------------------*/
     210             :     /* Do the classification only
     211             :     - MODE1: when the class is not transmitted in the bitstream
     212             :     - MODE2: on good frames (classifier is also called for bfi=1) */
     213      254310 :     test();
     214      254310 :     test();
     215      254310 :     test();
     216      254310 :     test();
     217      254310 :     test();
     218      254310 :     test();
     219      254310 :     IF( ( EQ_16( codec_mode, MODE1 ) && ( FEC_mode == 0 || LE_16( coder_type, UNVOICED ) || Opt_AMR_WB ) ) || ( EQ_16( codec_mode, MODE2 ) && NE_16( bfi, 1 ) && !tcxonly ) )
     220             :     {
     221             :         /*------------------------------------------------------------------------*
     222             :          * Overwrite classification decision using coder_type information
     223             :          *------------------------------------------------------------------------*/
     224      149301 :         test();
     225      149301 :         IF( EQ_16( coder_type, VOICED ) )
     226             :         {
     227       26700 :             *clas = VOICED_CLAS;
     228       26700 :             move16();
     229             :         }
     230      122601 :         ELSE IF( EQ_16( coder_type, UNVOICED ) )
     231             :         {
     232       19758 :             *clas = UNVOICED_CLAS;
     233       19758 :             move16();
     234             :         }
     235      102843 :         ELSE IF( EQ_16( coder_type, INACTIVE ) && !Opt_AMR_WB )
     236             :         {
     237       12565 :             *clas = INACTIVE_CLAS;
     238       12565 :             move16();
     239             :         }
     240             :         ELSE
     241             :         {
     242             :             /*------------------------------------------------------------------------*
     243             :              * Compute the zero crossing rate for all subframes
     244             :              *------------------------------------------------------------------------*/
     245             : 
     246       90278 :             pt1 = (Word16 *) synth - 1;
     247       90278 :             move16();
     248       90278 :             tmpS = shr( *pt1, 15 ); /* sets 'tmpS to -1 if *pt1 < 0 */
     249       90278 :             Ltmp = L_deposit_l( 0 );
     250    25782630 :             FOR( j = 0; j < L_SUBFR * nb_subfr; j++ )
     251             :             {
     252    25692352 :                 tmp16 = add( 1, tmpS );
     253    25692352 :                 pt1++;
     254    25692352 :                 if ( *pt1 != 0 ) /* Do only count zero crossing, no zero touchings */
     255             :                 {
     256    25262040 :                     tmpS = shr( *pt1, 15 ); /* 1Clk: >=0 ---> 0 OTHERWISE -1 */
     257             :                 }
     258    25692352 :                 Ltmp = L_msu0( Ltmp, tmpS, tmp16 );
     259             :             }
     260             : 
     261       90278 :             zc_frame = shl( extract_l( Ltmp ), 4 ); /* Q4 */
     262             : 
     263       90278 :             if ( EQ_16( L_frame, L_FRAME16k ) )
     264             :             {
     265             :                 /*zc_frame *= 0.8f;*/ /* Renormalization for 12.8kHz core*/
     266       40331 :                 zc_frame = mult_r( zc_frame, 26214 );
     267             :             }
     268             : 
     269             : 
     270             :             /*------------------------------------------------------------------------*
     271             :              * Compute the normalized correlation pitch-synch. at the end of the frame
     272             :              *------------------------------------------------------------------------*/
     273       90278 :             T0 = shr( pitch[3], 6 );
     274       90278 :             Ltmp1 = L_mult( pitch[3], 256 );
     275             : 
     276       90278 :             if ( GT_16( T0, L_SUBFR * 3 / 2 ) )
     277             :             {
     278       65357 :                 T0 = mac_r( Ltmp1, pitch[2], 256 );
     279             :             }
     280             : 
     281             : 
     282       90278 :             pt1 = synth;
     283       90278 :             move16();
     284       90278 :             pos = sub( L_frame, T0 ); /* T0 [34 231] */
     285             : 
     286             : 
     287       90278 :             Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[0] );
     288       90278 :             T0 = mult_r_sat( add_sat( pitch[2], pitch[3] ), 256 );
     289       90278 :             pos_limit = sub( L_frame, L_SUBFR );
     290       90278 :             j = s_min( 1, s_max( 0, sub( pos, pos_limit ) ) );
     291       90278 :             Ltmp = L_deposit_l( cor_max[0] );
     292       90278 :             IF( j > 0 )
     293             :             {
     294       14255 :                 j = 16384;
     295       14255 :                 move16();
     296       14255 :                 pos = sub( pos, T0 ); /* T0 [34 231] */
     297       14255 :                 Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[1] );
     298       14255 :                 Ltmp = L_add( Ltmp, cor_max[1] );
     299       14255 :                 IF( GT_16( pos, pos_limit ) )
     300             :                 {
     301        1940 :                     j = 10923;
     302        1940 :                     move16();
     303        1940 :                     pos = sub( pos, T0 ); /* T0 [34 231] */
     304        1940 :                     Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[2] );
     305        1940 :                     Ltmp = L_add( Ltmp, cor_max[2] );
     306             :                 }
     307       14255 :                 IF( GT_16( pos, pos_limit ) )
     308             :                 {
     309         271 :                     j = 8192;
     310         271 :                     move16();
     311         271 :                     pos = sub( pos, T0 ); /* T0 [34 231] */
     312         271 :                     Corre( &pt1[pos], &pt1[pos - T0], T0, &cor_max[3] );
     313         271 :                     Ltmp = L_add( Ltmp, cor_max[3] );
     314             :                 }
     315             :             }
     316             : 
     317       90278 :             voicing = cor_max[0];
     318       90278 :             move16();
     319       90278 :             IF( j > 0 )
     320             :             {
     321       14255 :                 voicing = extract_l( Mult_32_16( Ltmp, j ) );
     322             :             }
     323             :             /*------------------------------------------------------------------------*
     324             :              * Compute pitch coherence
     325             :              *------------------------------------------------------------------------*/
     326             : 
     327       90278 :             pc = 0;
     328       90278 :             move16();
     329       90278 :             test();
     330       90278 :             test();
     331       90278 :             IF( EQ_16( codec_mode, MODE1 ) || !( NE_16( LTP_Gain, -32768 /*-1.f Q15*/ ) && EQ_16( mode, CLASSIFIER_TCX ) ) )
     332             :             {
     333       33065 :                 pc = shr( abs_s( sub( add_sat( pitch[3], sub( pitch[2], pitch[1] ) ), pitch[0] ) ), 6 );
     334             : 
     335       33065 :                 IF( EQ_16( L_frame, L_FRAME16k ) )
     336             :                 {
     337        8045 :                     pc = mult_r( pc, 26214 ); /* Renormalization for 12.8kHz core*/
     338             :                 }
     339             :             }
     340             : 
     341             :             /*------------------------------------------------------------------------*
     342             :              * Compute spectral tilt
     343             :              *------------------------------------------------------------------------*/
     344       90278 :             pt1 = (Word16 *) synth + L_SUBFR;
     345       90278 :             move16();
     346       90278 :             pt2 = (Word16 *) synth + L_SUBFR - 1;
     347       90278 :             move16();
     348       90278 :             Ltmp = L_mult0( *pt1, *pt1 );
     349       90278 :             Ltmp1 = L_mult0( *pt1, *pt2 );
     350    19914560 :             FOR( j = 1; j < L_SUBFR * ( nb_subfr - 1 ); j++ )
     351             :             {
     352    19824282 :                 pt1++;
     353    19824282 :                 pt2++;
     354    19824282 :                 Ltmp = L_mac0_sat( Ltmp, *pt1, *pt1 );
     355    19824282 :                 Ltmp1 = L_mac0_sat( Ltmp1, *pt1, *pt2 );
     356             :             }
     357       90278 :             tilt = 0;
     358       90278 :             move16();
     359             : 
     360       90278 :             IF( Ltmp != 0 )
     361             :             {
     362             :                 BASOP_SATURATE_WARNING_OFF_EVS
     363       90248 :                 tmp16 = extract_l( L_or( L_shr( Ltmp1, 32 ), 1 ) ); /* sets a flag -1 or 1 for sign of Ltmp1 */
     364             :                 BASOP_SATURATE_WARNING_ON_EVS
     365       90248 :                 Ltmp1 = L_abs( Ltmp1 );
     366       90248 :                 exp1 = norm_l( Ltmp1 );
     367       90248 :                 tmp_y = extract_h( L_shl( Ltmp1, exp1 ) );
     368       90248 :                 exp1 = sub( 31 - 1 + 3, exp1 );
     369       90248 :                 exp2 = norm_l( Ltmp );
     370       90248 :                 tmp_x = extract_h( L_shl( Ltmp, exp2 ) );
     371       90248 :                 exp2 = sub( 31 - 1 + 3, exp2 );
     372             :                 BASOP_SATURATE_WARNING_OFF_EVS
     373       90248 :                 tmpS = shr( sub_sat( tmp_x, tmp_y ), 16 ); /* if tmp_x >= tmp_y tmpS = 0, -1 otherwise */
     374             :                 BASOP_SATURATE_WARNING_ON_EVS
     375       90248 :                 tmp_y = shl( tmp_y, tmpS );
     376       90248 :                 exp1 = sub( exp1, tmpS );
     377             : 
     378       90248 :                 tilt = div_s( tmp_y, tmp_x );
     379       90248 :                 tilt = shl_sat( tilt, sub( exp1, exp2 ) ); /* saturate to 1.0 */
     380             : 
     381       90248 :                 tilt = i_mult2( tilt, tmp16 );
     382             :             }
     383             : 
     384             :             /*------------------------------------------------------------------------*
     385             :              * Compute pitch-synchronous energy at the frame end
     386             :              *------------------------------------------------------------------------*/
     387       90278 :             ener = frame_energy_fx( L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn );
     388             : 
     389             :             /*------------------------------------------------------------------------*
     390             :              * transform parameters between 0 & 1
     391             :              * find unique merit function
     392             :              *------------------------------------------------------------------------*/
     393       90278 :             enern = mac_r( C_ENR_FX, K_ENR_FX, ener ); /*Q8*/
     394             : 
     395       90278 :             tiltn = extract_h( L_shr( L_mac( C_TILT_FX, K_TILT_FX, tilt ), 6 ) ); /*Q14 -> Q8*/
     396             : 
     397       90278 :             corn = extract_h( L_shr( L_mac( C_COR_FX, K_COR_FX, voicing ), 6 ) ); /*Q14 -> Q8*/
     398             : 
     399       90278 :             zcn = extract_h( L_shl( L_mac( C_ZC_FX, K_ZC_FX, zc_frame ), 4 ) ); /* Q4 -> Q8*/
     400             : 
     401             :             BASOP_SATURATE_WARNING_OFF_EVS
     402       90278 :             tmp16 = sub_sat( LTP_Gain, -32768 /*-1.f Q15*/ );
     403             :             BASOP_SATURATE_WARNING_ON_EVS
     404       90278 :             test();
     405       90278 :             test();
     406       90278 :             IF( EQ_16( codec_mode, MODE2 ) && tmp16 != 0 && EQ_16( mode, CLASSIFIER_TCX ) )
     407             :             {
     408       57213 :                 pcn = round_fx( L_shl( Mpy_32_16_1( C_PC_FX /*Q16*/, LTP_Gain /*Q15*/ ), 8 ) ); /*Q16*/
     409             :             }
     410             :             ELSE
     411             :             {
     412       33065 :                 pcn = extract_h( L_shl( L_mac( C_PC_FX, K_PC_FX, pc ), 8 ) ); /* Q0 -> Q8*/
     413             :             }
     414             : 
     415       90278 :             pcn = s_min( 256, pcn );
     416       90278 :             pcn = s_max( 0, pcn );
     417             :             /* fmerit1 = (1.0f/6.0f) * (tiltn + 2.0f*corn + zcn + pcn + enern) */
     418       90278 :             Ltmp = L_mult( tiltn, UNS6 );
     419       90278 :             Ltmp = L_mac( Ltmp, corn, 2 * UNS6 );
     420       90278 :             Ltmp = L_mac( Ltmp, zcn, UNS6 );
     421       90278 :             Ltmp = L_mac( Ltmp, pcn, UNS6 );
     422       90278 :             Ltmp = L_mac( Ltmp, enern, UNS6 );
     423             :             BASOP_SATURATE_WARNING_OFF_EVS
     424       90278 :             fmerit1 = round_fx_sat( L_shl_sat( Ltmp, 15 - 8 ) ); /*Q15 can saturate to 1.0 */
     425             :             BASOP_SATURATE_WARNING_ON_EVS
     426       90278 :             test();
     427       90278 :             IF( EQ_16( codec_mode, MODE2 ) && narrowBand != 0 )
     428             :             {
     429           0 :                 fmerit1 = mult_r( fmerit1, 29491 /*0.9f Q15*/ ); /* 0.90 */
     430             :             }
     431       90278 :             IF( EQ_16( codec_mode, MODE1 ) )
     432             :             {
     433       19666 :                 *class_para = round_fx( L_shl( Ltmp, 14 - 8 ) ); /*Q14 - cannot be saturated, degrades HF synthesis */
     434       19666 :                 move16();
     435             :             }
     436             : 
     437             :             /*------------------------------------------------------------------------*
     438             :              * frame classification
     439             :              *------------------------------------------------------------------------*/
     440       90278 :             IF( NE_16( coder_type, VOICED ) )
     441             :             {
     442       90278 :                 Word16 result = UNVOICED_CLAS;
     443       90278 :                 move16();
     444       90278 :                 SWITCH( *clas )
     445             :                 {
     446       73041 :                     case VOICED_CLAS:
     447             :                     case ONSET:
     448             :                     case SIN_ONSET:
     449             :                     case VOICED_TRANSITION:
     450       73041 :                         test();
     451       73041 :                         test();
     452       73041 :                         IF( LT_16( fmerit1, 12780 /*0.39f Q15*/ ) )
     453             :                         {
     454        3782 :                             result = UNVOICED_CLAS;
     455        3782 :                             move16();
     456             :                         }
     457       69259 :                         ELSE IF( LT_16( fmerit1, 20644 /*0.63f Q15*/ ) && ( LT_16( ener, -3840 ) || EQ_16( codec_mode, MODE2 ) ) )
     458             :                         {
     459       18046 :                             result = VOICED_TRANSITION;
     460       18046 :                             move16();
     461             :                         }
     462             :                         ELSE
     463             :                         {
     464       51213 :                             result = VOICED_CLAS;
     465       51213 :                             move16();
     466             :                         }
     467             : 
     468       73041 :                         BREAK;
     469             : 
     470       17237 :                     case UNVOICED_CLAS:
     471             :                     case UNVOICED_TRANSITION:
     472             :                     case INACTIVE_CLAS:
     473       17237 :                         IF( GT_16( fmerit1, 18350 /*0.56f Q15*/ ) )
     474             :                         {
     475        9670 :                             result = ONSET;
     476        9670 :                             move16();
     477             :                         }
     478        7567 :                         ELSE IF( GT_16( fmerit1, 14746 /*0.45f Q15*/ ) )
     479             :                         {
     480        2519 :                             result = UNVOICED_TRANSITION;
     481        2519 :                             move16();
     482             :                         }
     483             :                         ELSE
     484             :                         {
     485        5048 :                             result = UNVOICED_CLAS;
     486        5048 :                             move16();
     487             :                         }
     488       17237 :                         BREAK;
     489             :                 }
     490       90278 :                 *clas = result;
     491       90278 :                 move16();
     492             :             }
     493             :         }
     494             : 
     495             : 
     496      149301 :         IF( EQ_16( codec_mode, MODE1 ) )
     497             :         {
     498             :             /*------------------------------------------------------------------------*
     499             :              * Overwrite classification decision in case of music
     500             :              *------------------------------------------------------------------------*/
     501       36855 :             IF( EQ_16( coder_type, AUDIO ) )
     502             :             {
     503        6834 :                 ( *decision_hyst ) = add( *decision_hyst, 4 );
     504        6834 :                 move16();
     505             :             }
     506             :             ELSE
     507             :             {
     508       30021 :                 ( *decision_hyst ) = sub( *decision_hyst, 1 );
     509       30021 :                 move16();
     510             :             }
     511             : 
     512       36855 :             IF( EQ_16( coder_type, INACTIVE ) )
     513             :             {
     514       12565 :                 *decision_hyst = sub( *decision_hyst, 10 );
     515       12565 :                 move16();
     516             :             }
     517       36855 :             IF( GT_16( *decision_hyst, 200 ) )
     518             :             {
     519        3836 :                 *decision_hyst = 200;
     520        3836 :                 move16();
     521             :             }
     522       33019 :             ELSE IF( *decision_hyst < 0 )
     523             :             {
     524       23586 :                 *decision_hyst = 0;
     525       23586 :                 move16();
     526             :             }
     527             : 
     528       36855 :             test();
     529       36855 :             test();
     530       36855 :             if ( GT_16( *decision_hyst, 16 ) && LT_16( *clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) )
     531             :             {
     532        1038 :                 *clas = VOICED_CLAS;
     533        1038 :                 move16();
     534             :             }
     535             :         } /*MODE1*/
     536             : 
     537             :         /*---------------------------------------------------------------------------------*
     538             :          * Measure energy on active voice frames (to improve FEC performance)
     539             :          *---------------------------------------------------------------------------------*/
     540      149301 :         IF( EQ_16( *clas, VOICED_CLAS ) )
     541             :         {
     542       78951 :             test();
     543       78951 :             test();
     544       78951 :             test();
     545       78951 :             test();
     546       78951 :             test();
     547       78951 :             IF( ( EQ_16( codec_mode, MODE2 ) && EQ_16( coder_type, VOICED ) ) || ( EQ_16( codec_mode, MODE1 ) && ( Opt_AMR_WB || ( NE_16( coder_type, GENERIC ) && NE_16( coder_type, TRANSITION ) ) ) ) )
     548             :             {
     549             :                 /* pitch-synchronous energy at the frame end */
     550       33213 :                 enern = frame_energy_fx( L_frame, pitch, synth, *lp_speech, &frame_ener, *Q_mem_syn );
     551             :             }
     552             :             /* update of long-term active speech energy */
     553       78951 :             Ltmp = L_mult0( 655, frame_ener ); /* 0.01 */
     554       78951 :             *lp_speech = mac_r( Ltmp, 32440, *lp_speech );
     555       78951 :             move16(); /* lp_speech update */
     556             :         }
     557             : 
     558      149301 :         IF( EQ_16( codec_mode, MODE1 ) )
     559             :         {
     560             : 
     561             :             /*---------------------------------------------------------------------------------*
     562             :              * Overwrite classification decision to UNVOICED_CLAS in case of INACTIVE frame
     563             :              *---------------------------------------------------------------------------------*/
     564       36855 :             test();
     565       36855 :             if ( EQ_16( coder_type, INACTIVE ) && NE_16( *clas, INACTIVE_CLAS ) )
     566             :             {
     567           0 :                 *clas = UNVOICED_CLAS;
     568           0 :                 move16();
     569             :             }
     570             : 
     571             :             /*---------------------------------------------------------------------------------*
     572             :              * Classification refinement to improve noise coding (only in AMR-WB IO mode)
     573             :              *---------------------------------------------------------------------------------*/
     574       36855 :             IF( Opt_AMR_WB )
     575             :             {
     576           0 :                 *locattack = 0;
     577           0 :                 move16();
     578             : 
     579             :                 /*-----------------------------------------------------------------------------*
     580             :                  * Unvoiced signal but not silence
     581             :                  *-----------------------------------------------------------------------------*/
     582             : 
     583           0 :                 test();
     584           0 :                 IF( EQ_16( *clas, UNVOICED_CLAS ) && NE_16( coder_type, INACTIVE ) )
     585             :                 {
     586           0 :                     IF( LE_16( *lp_speech, 40 * 256 /*Q8*/ ) )
     587             :                     {
     588           0 :                         *UV_cnt = 16;
     589           0 :                         move16();
     590             :                     }
     591             :                     ELSE
     592             :                     {
     593           0 :                         move16();
     594           0 :                         *UV_cnt = sub( *UV_cnt, 8 );
     595             :                     }
     596             :                 }
     597             : 
     598             :                 /*-----------------------------------------------------------------------------*
     599             :                  * Neither unvoiced nor clean silence
     600             :                  * Number of frames between UV is increased
     601             :                  *-----------------------------------------------------------------------------*/
     602             : 
     603           0 :                 ELSE IF( NE_16( coder_type, INACTIVE ) )
     604             :                 {
     605           0 :                     move16();
     606           0 :                     *UV_cnt = add( *UV_cnt, 1 );
     607             :                 }
     608             : 
     609             :                 /*-----------------------------------------------------------------------------*
     610             :                  * Maximum/minimum number of frames between UV reached
     611             :                  *-----------------------------------------------------------------------------*/
     612             : 
     613           0 :                 /* Range 0..300 */ move16();
     614           0 :                 *UV_cnt = s_max( s_min( 300, *UV_cnt ), 0 );
     615             : 
     616             :                 /*-----------------------------------------------------------------------------*
     617             :                  * IF VAD = 0 (no voice activity)
     618             :                  *   long-term average updated towards to speech
     619             :                  *   maximum number of frames between UV is limited to 125
     620             :                  * Else
     621             :                  *   update long-term average
     622             :                  *-----------------------------------------------------------------------------*/
     623             : 
     624           0 :                 IF( EQ_16( coder_type, INACTIVE ) )
     625             :                 {
     626           0 :                     move16();
     627           0 :                     *LT_UV_cnt = mult_r( 31130 /*0.95f*/, *LT_UV_cnt ); /* tend to speech if no activity */
     628           0 :                     *UV_cnt = s_min( 125, *UV_cnt );
     629           0 :                     move16();
     630             :                 }
     631             :                 ELSE
     632             :                 {
     633             :                     /* *LT_UV_cnt = 0.9f * *LT_UV_cnt + 0.1f * *UV_cnt */
     634             : 
     635           0 :                     Ltmp = L_mult( 3277 /*0.1f*/, *UV_cnt );
     636             :                     /* Bring to Q22 */
     637           0 :                     Ltmp = L_shl( Ltmp, 6 );
     638             :                     /* Add to 0.9 x *LT_UV_cnt (Already in Q6) */
     639           0 :                     Ltmp = L_mac( Ltmp, 29491 /*0.9f*/, *LT_UV_cnt ); /* Q22*/
     640             :                     /* Store */
     641           0 :                     *LT_UV_cnt = round_fx( Ltmp );
     642           0 :                     move16();
     643             :                 }
     644             : 
     645             :                 /*-----------------------------------------------------------------------------*
     646             :                  * Compute frame energy difference
     647             :                  * IF long-term average is high and energy difference is relatively low
     648             :                  *   classification is overwritten to AUDIO
     649             :                  * IF energy difference > 6.0dB
     650             :                  *   consider an attack
     651             :                  *-----------------------------------------------------------------------------*/
     652             : 
     653           0 :                 diff_ener = sub( ener, *Last_ener );
     654           0 :                 *Last_ener = ener;
     655           0 :                 move16();
     656           0 :                 *amr_io_class = *clas;
     657           0 :                 move16();
     658           0 :                 test();
     659           0 :                 if ( GT_16( *LT_UV_cnt, LT_UV_THR_FX ) && LT_16( diff_ener, 12 * 256 /*Q8*/ ) )
     660             :                 {
     661           0 :                     move16();
     662           0 :                     *amr_io_class = AUDIO_CLAS;
     663             :                 }
     664           0 :                 test();
     665           0 :                 test();
     666           0 :                 if ( ( GT_16( diff_ener, 6 * 256 /*Q8*/ ) && EQ_16( *clas, AUDIO_CLAS ) ) || GT_16( diff_ener, 9 * 256 /*Q8*/ ) )
     667             :                 {
     668           0 :                     *locattack = 1;
     669           0 :                     move16();
     670             :                 }
     671             : 
     672             :                 /*------------------------------------------------------------------------*
     673             :                  * Find mean of the past 40 frames energy variation
     674             :                  *------------------------------------------------------------------------*/
     675             : 
     676           0 :                 IF( NE_16( coder_type, INACTIVE ) )
     677             :                 {
     678           0 :                     Ltmp = L_deposit_l( 0 );
     679           0 :                     FOR( i = 1; i < MAX_LT; i++ )
     680             :                     {
     681           0 :                         Ltmp = L_mac( Ltmp, INV_MAX_LT_FX, lt_diff_etot[i - 1] ); /* divide by MAX_LT */
     682           0 :                         lt_diff_etot[i - 1] = lt_diff_etot[i];
     683           0 :                         move16();
     684             :                     }
     685           0 :                     Ltmp = L_mac( Ltmp, INV_MAX_LT_FX, lt_diff_etot[i - 1] ); /* divide by MAX_LT */
     686             :                     /* Ltmp is in Q24 (Q16+Q8) */
     687             : 
     688             :                     /*------------------------------------------------------------------------*
     689             :                      * Find statistical deviation of the energy variation history
     690             :                      * against the last 15 frames
     691             :                      *------------------------------------------------------------------------*/
     692             : 
     693           0 :                     Ltmp1 = L_deposit_l( 1 );
     694           0 :                     FOR( i = MAX_LT - 15; i < MAX_LT; i++ )
     695             :                     {
     696             :                         /* ftmp_c = lt_diff_etot[i] - mean_diff */
     697           0 :                         tmp16 = mac_r( Ltmp, lt_diff_etot[i], -32768L );
     698             :                         /* fcorr += ftmp_c*ftmp_c */
     699           0 :                         Ltmp1 = L_mac0( Ltmp1, tmp16, tmp16 ); /* in Q16 (Q8xQ8)*/
     700             :                     }
     701           0 :                     lt_diff_etot[i - 1] = diff_ener;
     702           0 :                     move16();
     703             : 
     704             :                     /*------------------------------------------------------------------------*
     705             :                      * Compute statistical deviation
     706             :                      * Overwrite classification, if needed
     707             :                      *------------------------------------------------------------------------*/
     708             : 
     709             :                     /* dev = (float)sqrt(fcorr / (MAX_LT-15)) */
     710           0 :                     Ltmp = Sqrt_Ratio32( Ltmp1, 16 /*Q16*/, MAX_LT - 15, 0 /*Q0*/, &tmp16 );
     711           0 :                     tmp16 = round_fx( L_shr( Ltmp, sub( 15 - 8, tmp16 ) ) ); /* Put in Q8 (Don't care about Possible Saturation) */
     712             : 
     713           0 :                     test();
     714           0 :                     IF( EQ_16( *amr_io_class, AUDIO_CLAS ) && GT_16( tmp16, 5 * 256 /*Q8*/ ) )
     715             :                     {
     716           0 :                         *amr_io_class = *clas;
     717           0 :                         move16();
     718             :                         /* *UV_cnt =  (short)(80 + *UV_cnt*0.2f) */
     719           0 :                         *UV_cnt = add( 80, mult( *UV_cnt, 6554 ) );
     720           0 :                         move16();
     721             :                     }
     722             :                 }
     723             :             } /*if (Opt_AMR_WB)*/
     724             :         }     /*if (codec_mode==MODE1)*/
     725             : 
     726             : 
     727             :     } /* Do the classification only
     728             :  - MODE1: when the class is not transmitted in the bitstream
     729             :  - MODE2: on good frames (classifier is also called for bfi=1) */
     730             : 
     731             : 
     732             :     /* update the memory of synthesis for frame class estimation */
     733      254310 :     IF( EQ_16( codec_mode, 2 ) )
     734             :     {
     735      114184 :         Copy( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM );
     736             :     }
     737             :     ELSE
     738             :     {
     739      140126 :         Copy_Scale_sig( old_synth + L_frame, mem_syn_clas_estim, L_SYN_MEM_CLAS_ESTIM, negate( tmp_scale ) );
     740      140126 :         *Q_mem_syn = sub( add( Q_syn, tmp_scale_syn ), tmp_scale );
     741      140126 :         move16();
     742             :     }
     743             : 
     744             : 
     745      254310 :     return;
     746             : }
     747             : 
     748      100332 : static Word16 FEC_dec_class_fx(
     749             :     Decoder_State *st_fx, /* i/o: decoder state structure */
     750             :     Word32 *enr_q         /* i  : decoded energy Q0                       */
     751             : )
     752             : {
     753             :     Word16 clas, tmpS;
     754             :     Word16 sfrac;
     755             :     Word32 L_tmp;
     756             : 
     757      100332 :     clas = ONSET;
     758      100332 :     move16();
     759             : 
     760      100332 :     IF( NE_16( st_fx->coder_type, VOICED ) )
     761             :     {
     762             :         /* decode the class */
     763       96143 :         tmpS = (Word16) get_next_indice_fx( st_fx, FEC_BITS_CLS );
     764             : 
     765       96143 :         IF( tmpS == 0 )
     766             :         {
     767       41127 :             clas = UNVOICED_CLAS;
     768       41127 :             move16();
     769             :         }
     770       55016 :         ELSE IF( EQ_16( tmpS, 1 ) )
     771             :         {
     772        6401 :             IF( GE_16( st_fx->last_good, VOICED_TRANSITION ) )
     773             :             {
     774        5387 :                 clas = VOICED_TRANSITION;
     775        5387 :                 move16();
     776             :             }
     777             :             ELSE
     778             :             {
     779        1014 :                 clas = UNVOICED_TRANSITION;
     780        1014 :                 move16();
     781             :             }
     782             :         }
     783       48615 :         ELSE IF( EQ_16( tmpS, 2 ) )
     784             :         {
     785       41933 :             clas = VOICED_CLAS;
     786       41933 :             move16();
     787             :         }
     788             :     }
     789             :     ELSE
     790             :     {
     791        4189 :         clas = VOICED_CLAS;
     792        4189 :         move16();
     793             :     }
     794             : 
     795             :     /* decode the energy */
     796      100332 :     test();
     797      100332 :     test();
     798      100332 :     IF( GT_16( st_fx->acelp_cfg.FEC_mode, 1 ) )
     799             :     {
     800       57623 :         tmpS = (Word16) get_next_indice_fx( st_fx, FEC_BITS_ENR );
     801             :         /* convert from logarithmic to linear domain (the range is 0 : 3.0 : 96 dB) */
     802       57623 :         tmpS = mult_r( shl( tmpS, 10 ), 24576 ); /* Q10*Q13->Q8 */
     803       57623 :         L_tmp = L_mult( tmpS, 10885 );           /* 0.332192 in Q15 */
     804       57623 :         L_tmp = L_shr( L_tmp, 8 );               /* From Q24 to Q16 */
     805       57623 :         sfrac = L_Extract_lc( L_tmp, &tmpS );
     806       57623 :         *enr_q = Pow2( tmpS, sfrac );
     807       57623 :         move32();
     808             :     }
     809             : 
     810      100332 :     return clas;
     811             : }
     812             : 
     813      109205 : Word16 FEC_pos_dec_fx(
     814             :     Decoder_State *st_fx, /* i/o: decoder state structure                    */
     815             :     Word16 *last_pulse_pos,
     816             :     /* o  : last glotal pulse position in the lost ACB */ // Q0
     817             :     Word32 *enr_q,                                        /* o  : decoded energy     in Q0                   */
     818             :     const Word16 nBits_es_Pred                            /* i  : number of bits for Es_pred Q                */
     819             : )
     820             : {
     821             :     Word16 pitch_index, T0, T0_frac, T0_min, T0_max;
     822             :     Word16 bit_pos_pitch_index, nBits;
     823             : 
     824      109205 :     T0 = 0;
     825      109205 :     move16();
     826      109205 :     IF( GT_16( st_fx->coder_type, UNVOICED ) )
     827             :     {
     828             :         /* decode the clas and energy information */
     829      103271 :         IF( LT_16( st_fx->coder_type, AUDIO ) )
     830             :         {
     831      100332 :             st_fx->clas_dec = FEC_dec_class_fx( st_fx, enr_q );
     832      100332 :             move16();
     833             : 
     834      100332 :             test();
     835      100332 :             test();
     836      100332 :             test();
     837      100332 :             if ( EQ_16( st_fx->coder_type, GENERIC ) && EQ_16( st_fx->clas_dec, VOICED_CLAS ) && ( LE_16( st_fx->last_good, UNVOICED_CLAS ) || EQ_16( st_fx->last_good, INACTIVE_CLAS ) ) )
     838             :             {
     839          38 :                 st_fx->clas_dec = SIN_ONSET;
     840          38 :                 move16();
     841             :             }
     842             :         }
     843             : 
     844      103271 :         test();
     845      103271 :         IF( EQ_16( st_fx->coder_type, GENERIC ) && GT_16( st_fx->acelp_cfg.FEC_mode, 2 ) )
     846             :         {
     847        9006 :             nBits = st_fx->acelp_cfg.pitch_bits[0]; /* The first pitch index is located right after the actual position + the last pulse position index + predicted innovation energy index */
     848        9006 :             bit_pos_pitch_index = add( add( st_fx->next_bit_pos, FEC_BITS_POS ), nBits_es_Pred );
     849        9006 :             test();
     850        9006 :             test();
     851        9006 :             if ( GE_32( st_fx->core_brate, MIN_BRATE_AVQ_EXC ) && LE_32( st_fx->core_brate, MAX_BRATE_AVQ_EXC_TD ) && EQ_16( st_fx->coder_type, GENERIC ) )
     852             :             {
     853             :                 /* Harmonic flag is present */
     854        6467 :                 bit_pos_pitch_index = add( bit_pos_pitch_index, 1 );
     855             :             }
     856             :             /* retrieve the pitch index */
     857        9006 :             pitch_index = (Word16) get_indice( st_fx, bit_pos_pitch_index, nBits );
     858             : 
     859             :             /* decode pitch period */
     860        9006 :             T0_min = PIT_MIN;
     861        9006 :             move16();
     862        9006 :             T0_max = PIT_MAX;
     863        9006 :             move16();
     864        9006 :             pit16k_Q_dec_fx( pitch_index, 10, 1, &T0, &T0_frac, &T0_min, &T0_max, &st_fx->BER_detect );
     865             : 
     866             :             /* decode last pulse position */
     867        9006 :             *last_pulse_pos = (Word16) get_next_indice_fx( st_fx, FEC_BITS_POS );
     868             : 
     869             :             /* respect the sign */
     870        9006 :             IF( GE_16( *last_pulse_pos, 128 ) )
     871             :             {
     872        1550 :                 *last_pulse_pos = negate( s_and( *last_pulse_pos, 0x7F ) );
     873        1550 :                 move16();
     874             :             }
     875        9006 :             IF( GE_16( T0, 128 ) )
     876             :             {
     877        2860 :                 *last_pulse_pos = add( *last_pulse_pos, *last_pulse_pos );
     878        2860 :                 move16();
     879             :             }
     880             : 
     881        9006 :             if ( st_fx->BER_detect )
     882             :             {
     883           0 :                 *last_pulse_pos = 0;
     884           0 :                 move16();
     885             :             }
     886             :         }
     887             :     }
     888             : 
     889      109205 :     return T0;
     890             : }
     891             : /*----------------------------------------------------------------------*
     892             :  * Corre:
     893             :  *
     894             :  * Correlation function.  Signal x is compared to target signal y
     895             :  * Information about the similarity between vectors is returned in *gain
     896             :  *----------------------------------------------------------------------*/
     897      106744 : static void Corre(
     898             :     const Word16 *x, /* i  : vector 1                     Q12 */
     899             :     const Word16 *y, /* i  : vector 2                     Q12 */
     900             :     const Word16 l,  /* i  : length of vectors                */
     901             :     Word16 *gain     /* o  : normalized correlation gain  Q15 */
     902             : )
     903             : {
     904             :     Word16 cor, cor_exp;
     905             :     Word16 den, den_exp;
     906             :     Word16 den2, den2_exp;
     907             :     Word32 tmp;
     908             :     Word16 tmp_exp;
     909             : 
     910             :     /* keep Q15 normalized result */
     911      106744 :     cor = extract_h( Dot_product12( x, y, l, &cor_exp ) );
     912      106744 :     den = add_sat( extract_h( Dot_product12( y, y, l, &den_exp ) ), 1 );
     913      106744 :     den2 = extract_h( Dot_product12( x, x, l, &den2_exp ) );
     914             : 
     915             :     /* keep Q31 normalized result */
     916      106744 :     tmp = L_mult( den, den2 );
     917      106744 :     tmp_exp = norm_l( tmp );
     918      106744 :     tmp = L_shl( tmp, tmp_exp );
     919      106744 :     tmp_exp = sub( add( den_exp, den2_exp ), tmp_exp );
     920             : 
     921      106744 :     tmp = Isqrt_lc( tmp, &tmp_exp );
     922             :     /* keep Q15 result */
     923      106744 :     gain[0] = shl_sat( mult_r( cor, extract_h( tmp ) ), add( cor_exp, tmp_exp ) );
     924      106744 :     move16();
     925      106744 : }

Generated by: LCOV version 1.14