LCOV - code coverage report
Current view: top level - lib_enc - ivas_stereo_td_analysis_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 733 988 74.2 %
Date: 2025-05-03 01:55:50 Functions: 11 12 91.7 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include "options.h"
      35             : #include <math.h>
      36             : #include "cnst.h"
      37             : #include "rom_com.h"
      38             : #include "prot_fx.h"
      39             : #include "ivas_rom_com.h"
      40             : #include "ivas_cnst.h"
      41             : #include "rom_enc.h"
      42             : #include "wmc_auto.h"
      43             : #include "ivas_prot_fx.h"
      44             : #include "ivas_rom_com_fx.h"
      45             : 
      46             : 
      47             : /*-------------------------------------------------------------------*
      48             :  * Local constants
      49             :  *-------------------------------------------------------------------*/
      50             : 
      51             : #define RMS_MIN_FX_Q20     ( 1572864000 ) /* 1500 in Q20 */ /* Minimum energy for ratio index*/
      52             : #define RMS_MIN2_FX_Q21    ( 2097152000 ) /* 1000 in Q21 */ /* Minimum energy for LR encoding*/
      53             : #define CORR_THRES_FX_Q15  ( 31130 ) /* 0.95f in Q15 */     /* Maximal open loop correlation */
      54             : #define DT_ENER_THR_FX_Q16 ( 13107200 ) /* 200 in Q16 */    /* Energy variation threshold */
      55             : 
      56             : #define RMS_MIN        1500                       /* Minimum energy for ratio index*/
      57             : #define RMS_MIN2       1000                       /* Minimum energy for LR encoding*/
      58             : #define CORR_THRES     0.95f                      /* Maximal open loop correlation */
      59             : #define RMS_MIN_Q16    98304000 /* 1500 in Q16 */ /* Minimum energy for ratio index*/
      60             : #define RMS_MIN2_Q16   65536000 /* 1000 in Q16 */ /* Minimum energy for LR encoding*/
      61             : #define CORR_THRES_Q15 31130                      /* Maximal open loop correlation */
      62             : 
      63             : #define ALP_REF_FX_Q31 ( 1717986918 ) /* 0.8f in Q31 */ /* smoothing factor */
      64             : #define BET_REF_FX_Q31 ( ONE_IN_Q31 - ALP_REF_FX_Q31 )
      65             : 
      66             : #define ALP1_FX_Q31 ( 1073741824 ) /* 0.5f in Q31 */ /* smoothing factor in case of correlation are going in different directions */
      67             : #define BET1_FX_Q31 ( ONE_IN_Q31 - ALP1_FX_Q31 )     /* increase the update rate */
      68             : 
      69             : #define ALP2_FX_Q31 ( 429496729 ) /* 0.2f in Q31 */ /* smoothing factor in case of correlation are going in different directions in SM mode*/
      70             : #define BET2_FX_Q31 ( ONE_IN_Q31 - ALP2_FX_Q31 )    /* increase the update rate in SM mode*/
      71             : 
      72             : #define RATIO_MAX 1.5f /* Maximum correlation ratio */
      73             : 
      74             : #define RATIO_MAX_FX_Q30      ( 1610612736 ) /* 1.5f in Q30 */ /* Maximum correlation ratio */
      75             : #define RATIO_MAX_FX_Q24      ( 25165824 ) /* 1.5f in Q24 */   /* Maximum correlation ratio */
      76             : #define RATIO_MAX_FX_Q23      ( 12582912 ) /* 1.5f in Q23 */   /* Maximum correlation ratio */
      77             : #define LIMIT_ADAP_FAC_FX_Q16 ( 9830 )                         /* 0.15f in Q16 */
      78             : #define MIN_ADAP_FAC_FX_Q16   ( 6554 )                         /*0.1f in Q16*/
      79             : #define M_ADAP_FX_Q31         ( 1932735 )                      /* 0.0009f in Q31 */
      80             : #define B_ADAP_FX_Q16         ( 10486 )                        /* 0.16f in Q16 */
      81             : 
      82             : #define PC_LIMIT       64
      83             : #define RATIO_PG_HR    0.94f
      84             : #define RATIO_PG_HR_FX 2018634629 // 0.94f in Q31
      85             : #define RATIO_PG       0.92f
      86             : #define RATIO_PG_FX    1975684956 // 0.92f in Q31
      87             : #define PG2ND          3.0f
      88             : #define PG2ND_FX       6291456 // 3.0f in Q21
      89             : #define EUCLDST        0.04f
      90             : #define EUCLDST_FX     85899346 // 0.04f in Q31
      91             : #define RATIO_PG2      0.86f
      92             : #define RATIO_PG2_FX   1846835937 // 0.86f in Q31
      93             : #define PG2ND2         3.0f
      94             : #define PG2ND2_FX      6291456 // 3.0f in Q21
      95             : #define EUCLDST2       0.08f
      96             : #define EUCLDST2_FX    171798692 //  0.08f in Q31
      97             : 
      98             : #define RMS_THR          100
      99             : #define RMS_THR_Q16      ( 6553600 )
     100             : #define RATIO_PG_LRTD    0.96f
     101             : #define RATIO_PG_LRTD_FX 2061584302 // 0.96f in Q31
     102             : 
     103             : #define IVAS_BRATE_OMASA_STEREO_SW_THR 15000
     104             : 
     105             : // #define ONE_BY_100_Q15 ( 328 )
     106             : #define ONE_BY_100_Q31 ( 21474896 )
     107             : #define TEN_IN_Q27     ( 1342177280 ) /* 10.0f in Q27 */
     108             : #define TEN_IN_Q16     ( 655360 )     /* 10.0f in Q16 */
     109             : 
     110             : /*-------------------------------------------------------------------*
     111             :  * Local function prototypes
     112             :  *-------------------------------------------------------------------*/
     113             : 
     114             : static Word16 stereo_tdm_ener_analysis_SM_fx( CPE_ENC_HANDLE hCPE, Encoder_State **sts, const Word16 input_frame /*Q0*/, Word16 *tdm_SM_flag /*Q0*/ );
     115             : 
     116             : static void Get_corr_n_fx( const Word16 L[] /*q_in*/, const Word16 R[] /*q_in*/, Word32 *ic_Lm, Word16 *q_ic_Lm, Word32 *ic_Rm, Word16 *q_ic_Rm, const Word16 len, Word32 *es_em, const Word16 tdm_SM_calc_flag );
     117             : 
     118             : static Word16 stereo_smooth_LR_transition_fx( Word16 *tdm_prev_stable_idx, Word16 *tdm_ratio_transition_mov_flag, Word16 tdm_last_ratio_idx, Word16 *tdm_prev_desired_idx, Word16 *tdm_ratio_transition_cnt, const Word16 tdm_SM_flag, Word16 desired_idx );
     119             : 
     120             : static Word16 limit_idx_Dwnmix_fx( const Word16 idx_in /*Q0*/, const Word16 unclr_decision /*Q0*/, const Word16 inst_idx /*Q0*/, const Word16 previous_idx /*Q0*/, const Word16 tdm_last_LRTD_PriCh_cnt /*Q0*/, const Word16 tdm_last_LRTD_frame_cnt /*Q0*/ );
     121             : 
     122             : static Word16 limit_idx_NoDwnmix_fx( const Word16 idx_in /*Q0*/, const Word16 side_can_change /*Q0*/, const Word32 d_lt_corr_raw, const Word16 q_d_lt_corr_raw );
     123             : 
     124             : static void Get_LR_rms_fx( const Word16 *Left_in /*q_inp*/, const Word16 *Right_in /*q_inp*/, const Word16 input_frame, Word32 *rms_L, Word16 *q_rms_L, Word32 *rms_R, Word16 *q_rms_R );
     125             : 
     126             : static Word16 Get_dt_lt_ener_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono, const Word16 input_frame, const Word16 tdm_last_SM_flag, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word32 *tdm_lt_rms_L /*Q16*/, Word32 *tdm_lt_rms_R /*Q16*/, Word32 *tdm_last_ener_lt_L /*Q16*/, Word32 *tdm_last_ener_lt_R /*Q16*/, Word32 *tdm_LT_es_em /*Q21*/, Word16 *tdm_hyst_cnt, Word16 *tdm_NOOP_SM_flag_loc, Word32 *ener_R_dt /*Q16*/, Word32 *ener_L_dt /*Q16*/, Word32 *corr_LM, Word16 *q_corr_LM, Word32 *corr_RM, Word16 *q_corr_RM );
     127             : 
     128             : static void NOOP_decision_fx( CPE_ENC_HANDLE hCPE, const Word16 tdm_NOOP_flag_loc /*Q0*/, const Word16 tmp_SM_flag /*Q0*/, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, Word16 *tdm_SM_flag_loc /*Q0*/ );
     129             : 
     130             : static Word32 Comp_diff_lt_corr_fx( CPE_ENC_HANDLE hCPE, const Word16 IsSideMono /*Q0*/, const Word32 rms_L, const Word16 q_rms_L, const Word32 rms_R, const Word16 q_rms_R, const Word32 ener_L_dt /*Q16*/, const Word32 ener_R_dt /*Q16*/, Word32 corr_LM, Word16 q_corr_LM, Word32 corr_RM, Word16 q_corr_RM, const Word32 tdm_lt_rms_L /*Q16*/, const Word32 tdm_lt_rms_R /*Q16*/, Word32 *tdm_lt_corr_LM /*Q24*/, Word32 *tdm_lt_corr_RM /*Q24*/, Word32 *tdm_last_diff_lt_corr, Word16 *q_tdm_last_diff_lt_corr, Word32 *inst_ratio_L_out /*Q24*/, Word32 *diff_lt_corr, Word16 *q_d_lt_corr_raw );
     131             : 
     132             : 
     133             : /*-------------------------------------------------------------------*
     134             :  * Function stereo_tdm_ener_analysis()
     135             :  *
     136             :  *-------------------------------------------------------------------*/
     137        3827 : Word16 stereo_tdm_ener_analysis_fx(
     138             :     const Word16 ivas_format,   /* i  : IVAS format                         */
     139             :     CPE_ENC_HANDLE hCPE,        /* i  : CPE structure                       */
     140             :     const Word16 input_frame,   /* i  : Number of samples                   Q0*/
     141             :     Word16 *tdm_SM_or_LRTD_Pri, /* o  : channel combination scheme flag in TD stereo OR LRTD primary channel Q0*/
     142             :     Word16 *tdm_ratio_idx_SM    /* o  : TDM ratio index for SM mode         Q0*/
     143             : )
     144             : {
     145             :     Word32 diff_lt_corr_fx /*Q24*/;
     146             :     Word32 ratio_L_fx, dist_fx;
     147             :     Word16 i, side_can_change;
     148             :     Word16 idx, tdm_SM_flag_loc;
     149             :     Word16 tmp_SM_flag;
     150             :     Word16 desired_idx;
     151             :     Word32 rms_thd_fx; // Q16
     152             :     Word16 tdm_NOOP_flag_loc, tdm_NOOP_flag;
     153             :     STEREO_TD_ENC_DATA_HANDLE hStereoTD;
     154             :     Encoder_State **sts;
     155             :     Word32 d_lt_corr_raw_fx;
     156             :     Word16 q_d_lt_corr_raw;
     157             :     Word32 inst_ratio_L_fx; // Q24
     158             :     Word16 tdm_LRTD_pri_side;
     159             :     Word32 rms_L_fx, rms_R_fx;
     160             :     Word16 q_rms_L, q_rms_R;
     161             :     Word32 corr_RM_fx, corr_LM_fx;
     162             :     Word16 q_corr_LM, q_corr_RM;
     163             :     Word32 ener_R_dt_fx, ener_L_dt_fx;
     164             : 
     165        3827 :     hStereoTD = hCPE->hStereoTD;
     166        3827 :     sts = hCPE->hCoreCoder;
     167             : 
     168        3827 :     desired_idx = 0;
     169        3827 :     move16();
     170        3827 :     inst_ratio_L_fx = 0;
     171        3827 :     move32();
     172        3827 :     diff_lt_corr_fx = 0;
     173        3827 :     move32();
     174             :     /*----------------------------------------------------------------*
     175             :      * Compute L and R energy and Long term RMS of each channel
     176             :      *----------------------------------------------------------------*/
     177             : 
     178        3827 :     Get_LR_rms_fx( sts[0]->input_fx, sts[1]->input_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R );
     179             : 
     180             :     /*----------------------------------------------------------------*
     181             :      * Compute the 1st order energy difference difference
     182             :      * Compute the gain of L&R channel compared to mono
     183             :      * - estimate the long term evolution of the L to Mono gain
     184             :      * - estimate the long term evolution of the R to Mono gain
     185             :      * - estimate the long term difference between the long term
     186             :      * - evolution of the L and R to Mono gain
     187             :      *----------------------------------------------------------------*/
     188             : 
     189        3827 :     tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag; /* Q0 */
     190        3827 :     move16();
     191             : 
     192        3827 :     tmp_SM_flag = Get_dt_lt_ener_fx( hCPE, 0, input_frame, hStereoTD->tdm_last_SM_flag, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R,
     193             :                                      &hStereoTD->tdm_lt_rms_L_fx, &hStereoTD->tdm_lt_rms_R_fx, &hStereoTD->tdm_last_ener_lt_L_fx, &hStereoTD->tdm_last_ener_lt_R_fx,
     194             :                                      &hStereoTD->tdm_LT_es_em_fx, &hStereoTD->tdm_hyst_cnt, &tdm_NOOP_flag_loc,
     195             :                                      &ener_R_dt_fx, &ener_L_dt_fx, &corr_LM_fx, &q_corr_LM, &corr_RM_fx, &q_corr_RM );
     196             : 
     197        3827 :     hStereoTD->tdm_SM_reset_flag = 0;
     198        3827 :     move16();
     199             : 
     200             :     /*----------------------------------------------------------------*
     201             :      * Check if the signal has Near Out Of Phase characteristics
     202             :      * and trigger side/mono configuration if needed
     203             :      *----------------------------------------------------------------*/
     204             : 
     205        3827 :     NOOP_decision_fx( hCPE, tdm_NOOP_flag_loc, tmp_SM_flag, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, &tdm_SM_flag_loc );
     206             : 
     207             :     /*----------------------------------------------------------------*
     208             :      * Adjust stereo downmixing adaptation rate factor
     209             :      * in function of the signal energy. If signal energy is low,
     210             :      * adaptation rate factor is lower. This prevent stereo image
     211             :      * move on speech offset
     212             :      *----------------------------------------------------------------*/
     213        3827 :     d_lt_corr_raw_fx = Comp_diff_lt_corr_fx( hCPE, 0, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, ener_L_dt_fx, ener_R_dt_fx, corr_LM_fx, q_corr_LM, corr_RM_fx, q_corr_RM, hStereoTD->tdm_lt_rms_L_fx, hStereoTD->tdm_lt_rms_R_fx, &hStereoTD->tdm_lt_corr_LM_fx,
     214             :                                              &hStereoTD->tdm_lt_corr_RM_fx, &hStereoTD->tdm_last_diff_lt_corr_fx, &hStereoTD->q_tdm_last_diff_lt_corr, &inst_ratio_L_fx, &diff_lt_corr_fx, &q_d_lt_corr_raw );
     215             : 
     216        3827 :     IF( GT_16( q_d_lt_corr_raw, 31 ) )
     217             :     {
     218        1365 :         d_lt_corr_raw_fx = L_shr( d_lt_corr_raw_fx, sub( q_d_lt_corr_raw, Q31 ) ); /* Q31 */
     219        1365 :         q_d_lt_corr_raw = Q31;
     220        1365 :         move16();
     221             :     }
     222             : 
     223             :     /*----------------------------------------------------------------*
     224             :      * UNCLR classifier (detection of uncorrelated L and R channels)
     225             :      * Xtalk classifier (detection of cross-talk L and R channels)
     226             :      *----------------------------------------------------------------*/
     227             : 
     228        3827 :     unclr_classifier_td_fx( hCPE );
     229        3827 :     xtalk_classifier_td_fx( hCPE );
     230             : 
     231             :     /* switch to LRTD on cross-talk segments where two speakers are weakly correlated */
     232        3827 :     hStereoTD->prev_fr_LRTD_TD_dec = hCPE->hStereoClassif->lrtd_mode; /* Q0 */
     233        3827 :     move16();
     234             : 
     235             :     /*----------------------------------------------------------------*
     236             :      * When the energies of channels are low enough, compute the ratio
     237             :      * of L and R needed to create new mono/side signals
     238             :      *----------------------------------------------------------------*/
     239             : 
     240        3827 :     IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) )
     241             :     {
     242           0 :         test();
     243           0 :         test();
     244           0 :         if ( ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) || EQ_16( hCPE->hStereoTD->prev_fr_LRTD_TD_dec, 1 ) ) && ( LE_32( L_add( L_sub( hCPE->element_brate, 50 * FRAMES_PER_SEC ), L_add( hCPE->brate_surplus, hCPE->brate_surplus ) ), IVAS_BRATE_OMASA_STEREO_SW_THR ) ) )
     245             :         {
     246           0 :             hStereoTD->prev_fr_LRTD_TD_dec = 0;
     247           0 :             move16();
     248             :         }
     249             :     }
     250             : 
     251        3827 :     rms_thd_fx = RMS_MIN_Q16; /* Q16 */
     252        3827 :     move32();
     253        3827 :     IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
     254             :     {
     255        3827 :         rms_thd_fx = L_shr( rms_thd_fx, 2 ); /*Q16*/ /*rms_thd_fx *= 0.25f*/
     256        3827 :         test();
     257        3827 :         test();
     258        3827 :         IF( LE_32( hStereoTD->tdm_lt_rms_L_fx, 4915200 /* 75 in Q16*/ ) || LE_32( hStereoTD->tdm_lt_rms_R_fx, 4915200 /* 75 in Q16*/ ) /*|| sts[0]->last_coder_type == TRANSITION */ )
     259             :         {
     260         442 :             rms_thd_fx = L_shr( rms_thd_fx, 5 ); /* Q16*/ /*rms_thd_fx *= 0.03125f*/
     261             :         }
     262        3385 :         ELSE IF( GE_16( sts[0]->hVAD->hangover_cnt, 8 ) && GE_16( sts[1]->hVAD->hangover_cnt, 8 ) )
     263             :         {
     264           0 :             rms_thd_fx = imult3216( rms_thd_fx, 5 /*1/0.2f*/ ); /*Q16*/ /*rms_thd_fx /= 0.2f*/
     265             :         }
     266             : 
     267             :         /* Overwrite the LR decision flag in case the signals is already considered as S/M or when the signal is very similar between left and right channel */
     268        3827 :         test();
     269        3827 :         test();
     270        3827 :         test();
     271        3827 :         test();
     272        3827 :         test();
     273        3827 :         test();
     274        3827 :         test();
     275        3827 :         test();
     276        3827 :         test();
     277        3827 :         test();
     278        3827 :         test();
     279        3827 :         test();
     280        3827 :         test();
     281        3827 :         test();
     282        3827 :         test();
     283        3827 :         test();
     284        3827 :         test();
     285        3827 :         IF( EQ_16( tdm_SM_flag_loc, 1 ) )
     286             :         {
     287           0 :             hStereoTD->prev_fr_LRTD_TD_dec = 0;
     288           0 :             move16();
     289             :         }
     290        3827 :         ELSE IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && GT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 10 ) &&
     291             :                  ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( LT_32( hCPE->hStereoClassif->xtalk_score_fx, -1717986918 /* -0.8f in Q31*/ ) || LT_32( hCPE->hStereoClassif->xtalk_wscore_fx, -279172874 /*-0.13f in Q31*/ ) ) ) ||
     292             :                    ( EQ_16( hCPE->hStereoClassif->unclr_decision, 1 ) && sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && LT_32( L_abs( hCPE->hStereoClassif->unclr_wscore_fx ), 10737418 /* 0.005f in Q31 */ ) ) ) )
     293             :         {
     294             :             /* This forces the LRTD to switch to TD when inactive content happens on both channel */
     295          37 :             hStereoTD->prev_fr_LRTD_TD_dec = 0;
     296          37 :             move16();
     297             :         }
     298        3790 :         ELSE IF( hStereoTD->tdm_LRTD_flag == 0 &&
     299             :                  ( hCPE->hStereoClassif->vad_flag_glob == 0 || ( hCPE->hStereoClassif->unclr_decision == 0 && ( hCPE->hStereoClassif->xtalk_score_fx <= 0 || LE_32( hCPE->hStereoClassif->xtalk_wscore_fx, 214748364 /*0.1f in Q31 */ ) ) ) ||
     300             :                    ( EQ_16( hCPE->hStereoClassif->unclr_decision, 1 ) && ( sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS ) && LT_32( L_abs( hCPE->hStereoClassif->unclr_wscore_fx ), 53687091 /*0.025f in Q31 */ ) )
     301             :                    /* (sts[0]->last_clas == UNVOICED_CLAS && sts[1]->last_clas == UNVOICED_CLAS && hCPE->hStereoClassif->xtalk_wscore <= 0.0f)*/ ) )
     302             :         {
     303             :             /* This forces the LRTD to switch to TD when inactive content happens on both channel */
     304         127 :             hStereoTD->prev_fr_LRTD_TD_dec = 0;
     305         127 :             move16();
     306             :         }
     307             :     }
     308             : 
     309        3827 :     side_can_change = 0;
     310        3827 :     move16();
     311             : 
     312             :     /* update LRTD->DFT stereo hangover counters */
     313        3827 :     IF( EQ_16( hStereoTD->prev_fr_LRTD_TD_dec, 1 ) )
     314             :     {
     315        3663 :         hStereoTD->tdm_last_LRTD_frame_cnt = 0;
     316        3663 :         move16();
     317             :     }
     318             :     ELSE
     319             :     {
     320         164 :         hStereoTD->tdm_last_LRTD_frame_cnt = add( hStereoTD->tdm_last_LRTD_frame_cnt, 1 );
     321         164 :         move16();
     322         164 :         hStereoTD->tdm_last_LRTD_frame_cnt = s_min( hStereoTD->tdm_last_LRTD_frame_cnt, 100 );
     323         164 :         move16();
     324             :     }
     325             : 
     326        3827 :     IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) )
     327             :     {
     328          62 :         side_can_change = 1;
     329          62 :         move16();
     330             :     }
     331             : 
     332        3827 :     rms_L_fx = L_shl( rms_L_fx, sub( Q16, q_rms_L ) ); /* All the following energy comparison are done in Q16 */
     333        3827 :     rms_R_fx = L_shl( rms_R_fx, sub( Q16, q_rms_R ) );
     334        3827 :     test();
     335        3827 :     IF( EQ_16( hStereoTD->prev_fr_LRTD_TD_dec, 1 ) && side_can_change == 0 )
     336             :     {
     337        3601 :         test();
     338        3601 :         test();
     339        3601 :         test();
     340        3601 :         test();
     341        3601 :         IF( ( LE_32( hStereoTD->tdm_lt_rms_L_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) ||
     342             :             ( LE_32( hStereoTD->tdm_lt_rms_R_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_L_fx, L_shl( rms_thd_fx, 1 ) ) ) ||
     343             :             ( sts[0]->hVAD->hangover_cnt != 0 && LT_32( sts[1]->hNoiseEst->Etot_last_32fx, 201326592 /*12 in Q24*/ ) ) ||
     344             :             ( sts[1]->hVAD->hangover_cnt != 0 && LT_32( sts[0]->hNoiseEst->Etot_last_32fx, 201326592 /*12 in Q24*/ ) ) ||
     345             :             ( NE_16( sts[0]->hSpMusClas->past_dec[0], sts[1]->hSpMusClas->past_dec[0] ) ) )
     346             :         {
     347        2090 :             test();
     348        2090 :             test();
     349        2090 :             test();
     350        2090 :             test();
     351        2090 :             test();
     352        2090 :             test();
     353        2090 :             test();
     354        2090 :             test();
     355        2090 :             IF( ( ( LT_32( rms_L_fx, RMS_THR_Q16 ) && LT_32( rms_R_fx, RMS_THR_Q16 ) && LT_32( L_abs( L_sub( rms_R_fx, rms_L_fx ) ), RMS_THR_Q16 / 2 ) && GT_32( L_abs( d_lt_corr_raw_fx ), L_shr( 644245094 /*0.3f in Q31*/, sub( Q31, q_d_lt_corr_raw ) ) ) ) ||
     356             :                   ( LT_16( abs_s( sub( sts[0]->old_corr_fx, sts[1]->old_corr_fx ) ), 4915 /*0.15f in Q15*/ ) && GT_16( sts[0]->old_corr_fx, 22937 /*0.7f in Q15*/ ) && LT_16( sts[0]->old_corr_fx, 27853 /*0.85f in Q15*/ ) && LT_32( L_abs( L_sub( rms_L_fx, rms_R_fx ) ), rms_thd_fx ) && GT_32( L_abs( d_lt_corr_raw_fx ), L_shr( 644245094 /*0.3f in Q31*/, sub( Q31, q_d_lt_corr_raw ) ) ) ) ) /* Both channels are low energy, clean background switching is allowed */
     357             :             )
     358             :             {
     359         163 :                 side_can_change = 1;
     360         163 :                 move16();
     361             :             }
     362             :         }
     363             :     }
     364         226 :     ELSE IF( side_can_change == 0 ) /*if( hStereoTD->prev_fr_LRTD_TD_dec == 0 )*/
     365             :     {
     366         164 :         test();
     367         164 :         test();
     368         164 :         test();
     369         164 :         test();
     370         164 :         test();
     371         164 :         test();
     372         164 :         test();
     373         164 :         test();
     374         164 :         test();
     375         164 :         test();
     376         164 :         test();
     377         164 :         test();
     378         164 :         IF( ( ( LT_16( sts[0]->old_corr_fx, CORR_THRES_Q15 ) && LT_16( sts[1]->old_corr_fx, CORR_THRES_Q15 ) ) || ( LE_32( hStereoTD->tdm_lt_rms_L_fx, RMS_MIN2_Q16 ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, RMS_MIN2_Q16 ) ) ) &&
     379             :             ( ( ( LE_32( hStereoTD->tdm_lt_rms_L_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || ( LE_32( hStereoTD->tdm_lt_rms_R_fx, rms_thd_fx ) && LE_32( hStereoTD->tdm_lt_rms_L_fx, L_shl( rms_thd_fx, 1 ) ) ) ) ||
     380             :               ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( sts[0]->tdm_LRTD_flag == 0 || ( EQ_16( sts[0]->tdm_LRTD_flag, 1 ) && ( ( LT_32( rms_L_fx, L_shl( rms_thd_fx, 1 ) ) && LT_32( rms_R_fx, L_shl( rms_thd_fx, 1 ) ) ) || ( NE_16( sts[0]->hSpMusClas->past_dec[0], sts[1]->hSpMusClas->past_dec[0] ) ) ) ) ) ) /* Even if the UNCLR is set to 1, the content should be encoded with TD, lower swichting requierment */
     381             :               ) )
     382             :         {
     383         156 :             side_can_change = 1;
     384         156 :             move16();
     385             :         }
     386             :     }
     387             : 
     388        3827 :     test();
     389        3827 :     test();
     390        3827 :     IF( GE_32( hCPE->hStereoClassif->xtalk_wscore_fx, 107374182 /*0.05f in Q31*/ ) && hStereoTD->prev_fr_LRTD_TD_dec == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
     391             :     {
     392           2 :         side_can_change = 0;
     393           2 :         move16();
     394             :     }
     395        3827 :     test();
     396        3827 :     test();
     397        3827 :     IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) || EQ_16( hStereoTD->flag_skip_DMX, 1 ) )
     398             :     {
     399         100 :         desired_idx = LRTD_STEREO_LEFT_IS_PRIM;
     400         100 :         move16();
     401         100 :         hStereoTD->tdm_prev_desired_idx = LRTD_STEREO_LEFT_IS_PRIM;
     402         100 :         move16();
     403         100 :         ratio_L_fx = ONE_IN_Q31; /*Q31*/
     404         100 :         move32();
     405         100 :         hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM;
     406         100 :         move16();
     407         100 :         hStereoTD->tdm_ratio_transition_mov_flag = 0;
     408         100 :         move16();
     409         100 :         hStereoTD->tdm_last_ratio_idx = LRTD_STEREO_LEFT_IS_PRIM;
     410         100 :         move16();
     411         100 :         hStereoTD->tdm_ratio_transition_cnt = 0;
     412         100 :         move16();
     413         100 :         idx = TDM_NQ; /* Reserved quantizer index for special case */
     414         100 :         move16();
     415             :     }
     416        3727 :     ELSE IF( side_can_change || LE_16( sts[1]->ini_frame, 1 ) )
     417             :     {
     418         398 :         ratio_L_fx = L_max( diff_lt_corr_fx, -RATIO_MAX_FX_Q24 );                        // Q24
     419         398 :         ratio_L_fx = L_min( ratio_L_fx, RATIO_MAX_FX_Q24 );                              // Q24
     420         398 :         ratio_L_fx = Madd_32_32( ONE_IN_Q24, 1432371593 /*0.667f in Q31*/, ratio_L_fx ); // Q24
     421             : 
     422         398 :         test();
     423         398 :         test();
     424         398 :         IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 4 ) ) )
     425             :         {
     426          90 :             ratio_L_fx = hCPE->hStereoTD->tdm_last_ratio_fx; // Q31 /* note: the last_ratio is set in before in stereo_set_tdm() */
     427          90 :             move32();
     428             :         }
     429             :         ELSE
     430             :         {
     431             :             /*ratio_L = ( 1.0f - cosf( EVS_PI * ratio_L / 2.0f ) ) / 2.0f;*/
     432         308 :             ratio_L_fx = L_deposit_h( sub_sat( ONE_IN_Q14, getCosWord16( extract_l( Mpy_32_32( 1647099 /* EVS_PI/2 in Q20 */, ratio_L_fx ) ) ) ) ); // Q31 (Q14 + Q1(division by 2.0f) + Q16)
     433             :         }
     434             : 
     435         398 :         test();
     436         398 :         test();
     437         398 :         test();
     438         398 :         IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) || ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( hCPE->hStereoClassif->prev_lrtd_mode == 0 || GT_16( abs_s( sub( hCPE->hStereoTCA->indx_ica_gD, 20 ) ), 2 ) ) ) )
     439             :         {
     440         277 :             IF( GE_32( ratio_L_fx, 1138166333 /*0.53f in Q31*/ ) ) /* small hysteresis is used to prevent undesired switching during inactive segment */
     441             :             {
     442         143 :                 desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1;
     443         143 :                 move16();
     444             :             }
     445         134 :             ELSE IF( LT_32( ratio_L_fx, 1009317315 /*0.47f in Q31*/ ) )
     446             :             {
     447          99 :                 desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1;
     448          99 :                 move16();
     449             :             }
     450          35 :             ELSE IF( GT_32( L_sub( rms_L_fx, rms_R_fx ), 655360 /*10 in Q16*/ ) )
     451             :             {
     452           0 :                 desired_idx = LRTD_STEREO_LEFT_IS_PRIM - 1;
     453           0 :                 move16();
     454             :             }
     455             :             ELSE
     456             :             {
     457          35 :                 desired_idx = LRTD_STEREO_RIGHT_IS_PRIM + 1;
     458          35 :                 move16();
     459             :             }
     460             : 
     461         277 :             test();
     462         277 :             test();
     463         277 :             IF( NE_16( desired_idx, hStereoTD->tdm_prev_desired_idx ) && EQ_16( hStereoTD->tdm_last_LRTD_frame_cnt, 1 ) && LE_16( sts[0]->last_coder_type, UNVOICED ) ) /* TD transtionning to FD, we don't want an inversion of channels on the first transition frame */
     464             :             {
     465           0 :                 desired_idx = hStereoTD->tdm_prev_desired_idx;
     466           0 :                 move16();
     467             :             }
     468             :             ELSE
     469             :             {
     470         277 :                 hStereoTD->tdm_prev_desired_idx = desired_idx;
     471         277 :                 move16();
     472             :             }
     473         277 :             idx = desired_idx;
     474         277 :             move16();
     475             :         }
     476             :         ELSE
     477             :         {
     478         121 :             test();
     479         121 :             test();
     480         121 :             IF( GE_32( hCPE->element_brate, IVAS_48k ) && sts[0]->hVAD->hangover_cnt != 0 && LT_32( L_max( hStereoTD->tdm_lt_rms_L_fx, hStereoTD->tdm_lt_rms_R_fx ), 33554432 /* 512.0f in Q16*/ ) )
     481             :             {
     482           0 :                 ratio_L_fx = check_bounds_l( ratio_L_fx, 644245094 /*0.3f in Q31*/, 1503238554 /*0.7f in Q31*/ ); /* Q31 */
     483             :             }
     484             : 
     485         121 :             test();
     486         121 :             test();
     487         121 :             test();
     488         121 :             test();
     489         121 :             IF( ( GT_32( hCPE->hStereoTCA->instTargetGain_fx, 644245094 /*1.2f in Q29*/ ) || GT_32( hCPE->hStereoTCA->targetGain_fx, ONE_IN_Q29 ) ) && LT_32( ratio_L_fx, 858993459 /*0.4f  in Q31*/ ) )
     490             :             {
     491          59 :                 ratio_L_fx = 858993459; /*0.4f in Q31*/
     492          59 :                 move32();
     493             :             }
     494          62 :             ELSE IF( ( LT_32( hCPE->hStereoTCA->instTargetGain_fx, 429496730 /*0.8f*/ ) || LT_32( hCPE->hStereoTCA->targetGain_fx, ONE_IN_Q29 ) ) && GT_32( ratio_L_fx, 1288490189 /*0.6f in Q31*/ ) )
     495             :             {
     496           0 :                 ratio_L_fx = 1288490189; /* 0.6f in Q31 */
     497           0 :                 move32();
     498             :             }
     499             : 
     500         121 :             dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[0] ) ); // Q31
     501             : 
     502         121 :             desired_idx = 0;
     503         121 :             move16();
     504        3751 :             FOR( i = 1; i < TDM_NQ; i++ )
     505             :             {
     506        3630 :                 IF( LE_32( L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[i] ) ), dist_fx ) )
     507             :                 {
     508        1730 :                     dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx[i] ) ); // Q31
     509        1730 :                     desired_idx = i;
     510        1730 :                     move16();
     511             :                 }
     512             :             }
     513             : 
     514         121 :             idx = stereo_smooth_LR_transition_fx( &hStereoTD->tdm_prev_stable_idx, &hStereoTD->tdm_ratio_transition_mov_flag, hStereoTD->tdm_last_ratio_idx, &hStereoTD->tdm_prev_desired_idx, &hStereoTD->tdm_ratio_transition_cnt, tdm_SM_flag_loc, desired_idx ); /* Q0 */
     515             : 
     516             :             /* Change the switching level in case of dual mono (in case the scenario still accept left right switching */
     517             :             /* This logic is needed in case the content is exactly the same in the 2 channel and it is expected to get back to LRTD, to prevent the secondary channel to be completely empty */
     518         121 :             IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
     519             :             {
     520         121 :                 IF( LE_16( idx, LRTD_STEREO_MID_IS_PRIM ) )
     521             :                 {
     522          69 :                     idx = s_min( idx, LRTD_STEREO_MID_IS_PRIM - 1 );
     523             :                 }
     524             :                 ELSE
     525             :                 {
     526          52 :                     idx = s_max( idx, LRTD_STEREO_MID_IS_PRIM + 1 );
     527             :                 }
     528             : 
     529         121 :                 hStereoTD->tdm_prev_desired_idx = idx;
     530         121 :                 move16();
     531             :             }
     532             :             /* 0 and 30 are reserved to signal L-R only coding  */
     533             :         }
     534             :     }
     535             :     ELSE
     536             :     {
     537        3329 :         idx = hStereoTD->tdm_last_ratio_idx;
     538        3329 :         move16();
     539             :     }
     540             : 
     541        3827 :     hStereoTD->tdm_inst_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM;
     542        3827 :     move16();
     543        3827 :     tdm_LRTD_pri_side = -1;
     544        3827 :     move16();
     545        3827 :     IF( LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 5 ) )
     546             :     {
     547         245 :         desired_idx = 15;
     548         245 :         move16();
     549             :     }
     550             :     ELSE
     551             :     {
     552        3582 :         desired_idx = 0;
     553        3582 :         move16();
     554        3582 :         dist_fx = L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[0], 7 ) ) ); // Q24
     555             : 
     556      111042 :         FOR( i = 1; i < TDM_NQ; i++ )
     557             :         {
     558      107460 :             IF( LE_32( L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[i], 7 ) ) ), dist_fx ) )
     559             :             {
     560       51770 :                 dist_fx = L_abs( L_sub( inst_ratio_L_fx, L_shr( tdm_ratio_tabl_fx[i], 7 ) ) ); // Q24
     561       51770 :                 desired_idx = i;
     562       51770 :                 move16();
     563             :             }
     564             :         }
     565             :     }
     566             : 
     567        3827 :     IF( LT_16( sub( sts[1]->lp_speech_fx, sts[1]->lp_noise_fx ), 12800 /*50.0f in Q8*/ ) ) /* likely presence of noisy content */
     568             :     {
     569             :         /* pointing in the right direction, inverse it else do nothing */
     570          33 :         test();
     571          33 :         test();
     572          33 :         test();
     573          33 :         test();
     574          33 :         IF( ( GT_16( idx, LRTD_STEREO_MID_IS_PRIM ) && GT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) || ( LT_16( idx, LRTD_STEREO_MID_IS_PRIM ) && LT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) )
     575             :         {
     576             :             Word16 idx_offet;
     577           0 :             idx_offet = 5;
     578           0 :             move16();
     579           0 :             IF( GT_16( desired_idx, LRTD_STEREO_MID_IS_PRIM ) ) /* slightly Favor the 2nd channel */
     580             :             {
     581           0 :                 idx_offet = negate( idx_offet );
     582             :             }
     583           0 :             desired_idx = add( desired_idx, idx_offet );
     584           0 :             desired_idx = check_bounds_s_fx( desired_idx, 0, 30 ); /* Q0 */
     585             :         }
     586             :     }
     587             : 
     588        3827 :     test();
     589        3827 :     IF( sts[1]->clas != UNVOICED_CLAS || sts[0]->clas != UNVOICED_CLAS )
     590             :     {
     591        2936 :         desired_idx = check_bounds_s_fx( desired_idx, 5, 25 ); /* Q0 */
     592             :     }
     593             : 
     594        3827 :     hStereoTD->tdm_inst_ratio_idx = desired_idx;
     595        3827 :     move16();
     596        3827 :     IF( /*hCPE->last_element_mode == IVAS_CPE_MDCT ||*/ EQ_16( hStereoTD->flag_skip_DMX, 1 ) )
     597             :     {
     598             :         /*force tdm_inst_ratio_idx to the reserved index */
     599         100 :         hStereoTD->tdm_inst_ratio_idx = idx;
     600         100 :         move16();
     601         100 :         tdm_LRTD_pri_side = 1; /* left channel */
     602         100 :         move16();
     603             :     }
     604        3727 :     ELSE IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) )
     605             :     {
     606        3598 :         idx = limit_idx_NoDwnmix_fx( idx, side_can_change, d_lt_corr_raw_fx, q_d_lt_corr_raw );
     607             : 
     608        3598 :         hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_LEFT_IS_PRIM;
     609        3598 :         move16();
     610        3598 :         tdm_LRTD_pri_side = 0; /* right channel */
     611        3598 :         move16();
     612        3598 :         IF( idx != LRTD_STEREO_RIGHT_IS_PRIM )
     613             :         {
     614        3330 :             tdm_LRTD_pri_side = 1; /* left channel */
     615        3330 :             move16();
     616        3330 :             hStereoTD->tdm_prev_stable_idx = LRTD_STEREO_RIGHT_IS_PRIM;
     617        3330 :             move16();
     618             :         }
     619             :     }
     620             :     ELSE
     621             :     {
     622         129 :         test();
     623         129 :         test();
     624         129 :         idx = limit_idx_Dwnmix_fx( idx, ( hCPE->hStereoClassif->unclr_decision || ( EQ_16( sts[0]->flag_noisy_speech_snr, 1 ) && GT_32( hCPE->hStereoClassif->xtalk_wscore_fx, 214748365 /*0.1f*/ ) ) ), desired_idx, hStereoTD->tdm_last_ratio_idx, hStereoTD->tdm_last_LRTD_PriCh_cnt, hStereoTD->tdm_last_LRTD_frame_cnt );
     625             :     }
     626             : 
     627        3827 :     IF( GT_16( abs_s( sub( hStereoTD->tdm_last_ratio_idx, idx ) ), LRTD_STEREO_MID_IS_PRIM ) )
     628             :     {
     629          35 :         hStereoTD->tdm_last_LRTD_PriCh_cnt = 0;
     630          35 :         move16();
     631             :     }
     632             :     ELSE
     633             :     {
     634        3792 :         hStereoTD->tdm_last_LRTD_PriCh_cnt = add( hStereoTD->tdm_last_LRTD_PriCh_cnt, 1 );
     635        3792 :         move16();
     636             :     }
     637             : 
     638        3827 :     ratio_L_fx = tdm_ratio_tabl_fx_Q30[idx]; // Q30
     639        3827 :     move32();
     640             : 
     641        3827 :     test();
     642        3827 :     IF( EQ_16( hStereoTD->tdm_SM_modi_flag, 1 ) && hStereoTD->tdm_LRTD_flag == 0 )
     643             :     {
     644           0 :         idx = shr( add( hStereoTD->tdm_last_ratio_idx, add( LRTD_STEREO_MID_IS_PRIM, 1 ) ), 1 );
     645           0 :         ratio_L_fx = tdm_ratio_tabl_fx_Q30[idx]; // Q30
     646           0 :         move32();
     647             :     }
     648             : 
     649        3827 :     test();
     650        3827 :     test();
     651        3827 :     test();
     652        3827 :     IF( ( EQ_16( hStereoTD->tdm_ratio_transition_mov_flag, 1 ) && GE_16( hStereoTD->tdm_ratio_transition_cnt, 31 ) ) || ( ( EQ_16( hStereoTD->tdm_last_SM_flag, tdm_SM_flag_loc ) ) && ( EQ_16( idx, hStereoTD->tdm_prev_stable_idx ) ) ) )
     653             :     {
     654          46 :         hStereoTD->tdm_ratio_transition_cnt = 0;
     655          46 :         move16();
     656          46 :         hStereoTD->tdm_ratio_transition_mov_flag = 0;
     657          46 :         move16();
     658             :     }
     659             : 
     660        3827 :     test();
     661        3827 :     if ( hStereoTD->tdm_ratio_transition_mov_flag == 0 || tdm_SM_flag_loc == 0 )
     662             :     {
     663        3827 :         hStereoTD->tdm_prev_stable_idx = idx;
     664        3827 :         move16();
     665             :     }
     666             : 
     667             :     /* NOOP ratio calculation */
     668        3827 :     IF( tdm_SM_flag_loc )
     669             :     {
     670           0 :         IF( hStereoTD->tdm_SM_reset_flag )
     671             :         {
     672           0 :             hStereoTD->tdm_lt_corr_RM_SM_fx = 167772 /*0.01f Q24*/;
     673           0 :             move32();
     674           0 :             hStereoTD->tdm_lt_corr_LM_SM_fx = 167772 /*0.01f Q24*/;
     675           0 :             move32();
     676           0 :             hStereoTD->tdm_last_ratio_SM_fx = hStereoTD->tdm_last_ratio_fx; /* Q31 */
     677           0 :             move32();
     678           0 :             hStereoTD->tdm_last_ratio_idx_SM = hStereoTD->tdm_last_ratio_idx; /* Q0 */
     679           0 :             move16();
     680           0 :             hStereoTD->tdm_lt_rms_L_SM_fx = 2621440; // 40.0f Q16
     681           0 :             move32();
     682           0 :             hStereoTD->tdm_lt_rms_R_SM_fx = 2621440; // 40.0f Q16
     683           0 :             move32();
     684           0 :             hStereoTD->tdm_last_diff_lt_corr_SM_fx = 0;
     685           0 :             move32();
     686           0 :             hStereoTD->q_tdm_last_diff_lt_corr_SM = 0;
     687           0 :             move16();
     688           0 :             hStereoTD->tdm_last_ener_lt_R_SM_fx = 0;
     689           0 :             move32();
     690           0 :             hStereoTD->tdm_last_ener_lt_L_SM_fx = 0;
     691           0 :             move32();
     692             : 
     693           0 :             hStereoTD->tdm_noop_mov_flag = 0;
     694           0 :             move16();
     695           0 :             hStereoTD->tdm_noop_cnt = 0;
     696           0 :             move16();
     697           0 :             hStereoTD->tdm_last_SM_flag_noop = 0;
     698           0 :             move16();
     699           0 :             hStereoTD->tdm_prev_stable_idx_SM = 0;
     700           0 :             move16();
     701           0 :             hStereoTD->tdm_prev_desired_idx_SM = 0;
     702           0 :             move16();
     703           0 :             hStereoTD->tdm_LT_es_em_SM_fx = 209715; // 0.1f Q21;
     704           0 :             move32();
     705           0 :             hStereoTD->tdm_hyst_cnt_SM = 0;
     706           0 :             move16();
     707             :         }
     708             : 
     709           0 :         *tdm_ratio_idx_SM = stereo_tdm_ener_analysis_SM_fx( hCPE, sts, input_frame, &tdm_NOOP_flag ); /* Q0 */
     710           0 :         move16();
     711             :     }
     712             :     ELSE
     713             :     {
     714        3827 :         *tdm_ratio_idx_SM = LRTD_STEREO_MID_IS_PRIM;
     715        3827 :         move16();
     716        3827 :         tdm_NOOP_flag = 1;
     717        3827 :         move16();
     718             :     }
     719             : 
     720        3827 :     sts[0]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag;
     721        3827 :     move16();
     722        3827 :     sts[1]->tdm_LRTD_flag = hStereoTD->tdm_LRTD_flag;
     723        3827 :     move16();
     724             : 
     725             :     /* set channel combination scheme flag */
     726        3827 :     *tdm_SM_or_LRTD_Pri = tdm_SM_flag_loc; /* Q0 */
     727        3827 :     move16();
     728        3827 :     if ( EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) )
     729             :     {
     730        3698 :         *tdm_SM_or_LRTD_Pri = tdm_LRTD_pri_side; /* Q0 */
     731        3698 :         move16();
     732             :     }
     733             : 
     734        3827 :     hCPE->hStereoClassif->ratio_L_fx = ratio_L_fx; /* 31 - ratio_L_e */
     735        3827 :     move32();
     736        3827 :     hCPE->hStereoClassif->ratio_L_e = 1;
     737        3827 :     move16();
     738             : 
     739        3827 :     return idx;
     740             : }
     741             : 
     742             : /*-------------------------------------------------------------------*
     743             :  * Function Get_LR_rms_fx()
     744             :  *
     745             :  * Get current frame left and right rms values
     746             :  *-------------------------------------------------------------------*/
     747             : 
     748        3827 : static void Get_LR_rms_fx(
     749             :     const Word16 *Left_in,    /* q_inp */
     750             :     const Word16 *Right_in,   /* q_inp */
     751             :     const Word16 input_frame, /* Q0 */
     752             :     Word32 *rms_L,            /* q_rms_L */
     753             :     Word16 *q_rms_L,
     754             :     Word32 *rms_R, /* q_rms_R */
     755             :     Word16 *q_rms_R )
     756             : {
     757             :     Word32 ener_l, ener_r;
     758             :     Word32 ener_l_tmp, ener_r_tmp;
     759             :     Word16 guard_bits;
     760             :     Word64 W_ener_l_tmp, W_ener_r_tmp;
     761             :     Word16 i;
     762             :     Word16 exp_out_l, exp_out_r, exp_diff;
     763             : 
     764        3827 :     W_ener_l_tmp = 0;
     765        3827 :     move64();
     766        3827 :     W_ener_r_tmp = 0;
     767        3827 :     move64();
     768        3827 :     ener_l = ONE_BY_100_Q31; /* Q31 */
     769        3827 :     move32();
     770        3827 :     ener_r = ONE_BY_100_Q31; /* Q31 */
     771        3827 :     move32();
     772             : 
     773        3827 :     guard_bits = sub( 32, find_guarded_bits_fx( input_frame ) );
     774     2507827 :     FOR( i = 0; i < input_frame; i++ )
     775             :     {
     776     2504000 :         W_ener_l_tmp = W_mac0_16_16( W_ener_l_tmp, Left_in[i], Left_in[i] );   // Q0
     777     2504000 :         W_ener_r_tmp = W_mac0_16_16( W_ener_r_tmp, Right_in[i], Right_in[i] ); // Q0
     778             :     }
     779             :     /* Scaling back to the original proposal */
     780        3827 :     ener_l_tmp = W_extract_h( W_shl( W_ener_l_tmp, guard_bits ) ); // guard_bits - 32
     781        3827 :     ener_r_tmp = W_extract_h( W_shl( W_ener_r_tmp, guard_bits ) ); // guard_bits - 32
     782             : 
     783        3827 :     ener_l = BASOP_Util_Add_Mant32Exp( ener_l, 0, ener_l_tmp, sub( Q31, sub( guard_bits, 32 ) ), &exp_out_l ); /* Q31-exp_out_l */
     784        3827 :     ener_r = BASOP_Util_Add_Mant32Exp( ener_r, 0, ener_r_tmp, sub( Q31, sub( guard_bits, 32 ) ), &exp_out_r ); /* Q31-exp_out_r */
     785             : 
     786        3827 :     ener_l_tmp = BASOP_Util_Divide3232_Scale( ener_l, input_frame, &exp_diff ); /* Q31- exp_out_l*/
     787        3827 :     exp_out_l = sub( add( exp_diff, exp_out_l ), Q15 );
     788        3827 :     ener_r_tmp = BASOP_Util_Divide3232_Scale( ener_r, input_frame, &exp_diff ); /* Q31-exp_out_r */
     789        3827 :     exp_out_r = sub( add( exp_diff, exp_out_r ), Q15 );
     790             : 
     791        3827 :     *rms_L = Sqrt32( ener_l_tmp, &exp_out_l ); // Q31 - exp_out_l
     792        3827 :     move32();
     793        3827 :     *q_rms_L = sub( Q31, exp_out_l );
     794        3827 :     move16();
     795        3827 :     *rms_R = Sqrt32( ener_r_tmp, &exp_out_r ); // Q31 - exp_out_r
     796        3827 :     move32();
     797        3827 :     *q_rms_R = sub( Q31, exp_out_r );
     798        3827 :     move16();
     799             : 
     800        3827 :     return;
     801             : }
     802             : 
     803             : 
     804             : /*-------------------------------------------------------------------*
     805             :  * Function Get_dt_lt_ener_fx()
     806             :  *
     807             :  * Compute the gain of L&R channel compared to mono
     808             :  * - estimate the long term evolution of the L to Mono gain
     809             :  * - estimate the long term evolution of the R to Mono gain
     810             :  * - estimate the long term difference between the long term
     811             :  * - evolution of the L and R to Mono gain
     812             :  *-------------------------------------------------------------------*/
     813             : 
     814        3827 : static Word16 Get_dt_lt_ener_fx(
     815             :     CPE_ENC_HANDLE hCPE,
     816             :     const Word16 IsSideMono,       /* Q0 */
     817             :     const Word16 input_frame,      /* Q0 */
     818             :     const Word16 tdm_last_SM_flag, /* Q0 */
     819             :     const Word32 rms_L,            /* q_rms_L */
     820             :     const Word16 q_rms_L,
     821             :     const Word32 rms_R, /* q_rms_R */
     822             :     const Word16 q_rms_R,
     823             :     Word32 *tdm_lt_rms_L,         /* Q16 */
     824             :     Word32 *tdm_lt_rms_R,         /* Q16 */
     825             :     Word32 *tdm_last_ener_lt_L,   /* Q16 */
     826             :     Word32 *tdm_last_ener_lt_R,   /* Q16 */
     827             :     Word32 *tdm_LT_es_em,         /* Q21 */
     828             :     Word16 *tdm_hyst_cnt,         /* Q0 */
     829             :     Word16 *tdm_NOOP_SM_flag_loc, /* Q0 */
     830             :     Word32 *ener_R_dt,            /* Q16 */
     831             :     Word32 *ener_L_dt,            /* Q16 */
     832             :     Word32 *corr_LM,              /* q_corr_LM */
     833             :     Word16 *q_corr_LM,
     834             :     Word32 *corr_RM, /* q_corr_RM */
     835             :     Word16 *q_corr_RM )
     836             : {
     837             :     Encoder_State **sts;
     838             :     Word16 *Left_in_fx, *Right_in_fx;
     839             :     Word32 es_em_fx;
     840             :     Word16 tmp_SM_flag, tdm_SM_flag_loc;
     841             :     Word32 L_tmp, L_tmp1;
     842             :     Word16 exp_diff, tmp;
     843             : 
     844        3827 :     sts = hCPE->hCoreCoder;
     845             : 
     846        3827 :     Left_in_fx = sts[0]->input_fx;  /* Left channel  sts[0]->q_inp*/
     847        3827 :     Right_in_fx = sts[1]->input_fx; /* Right channel sts[1]->q_inp*/
     848             : 
     849        3827 :     tmp = sub( getScaleFactor16( sts[0]->input_fx, input_frame ), 1 );
     850        3827 :     Scale_sig( sts[0]->input_fx, input_frame, tmp ); /* sts[0]->q_inp + tmp */
     851        3827 :     sts[0]->q_inp = add( tmp, sts[0]->q_inp );
     852        3827 :     move16();
     853             : 
     854        3827 :     tmp = getScaleFactor16( sts[1]->input_fx, input_frame );
     855        3827 :     Scale_sig( sts[1]->input_fx, input_frame, tmp ); /* sts[1]->q_inp + tmp */
     856        3827 :     sts[1]->q_inp = add( tmp, sts[1]->q_inp );
     857        3827 :     move16();
     858             : 
     859        3827 :     Scale_sig( sts[0]->input_fx, input_frame, sub( s_min( sts[0]->q_inp, sts[1]->q_inp ), sts[0]->q_inp ) ); /* s_min( sts[0]->q_inp, sts[1]->q_inp ) */
     860        3827 :     Scale_sig( sts[1]->input_fx, input_frame, sub( s_min( sts[0]->q_inp, sts[1]->q_inp ), sts[1]->q_inp ) ); /* s_min( sts[0]->q_inp, sts[1]->q_inp ) */
     861        3827 :     sts[1]->q_inp = s_min( sts[0]->q_inp, sts[1]->q_inp );
     862        3827 :     move16();
     863        3827 :     sts[0]->q_inp = sts[1]->q_inp;
     864        3827 :     move16();
     865             : 
     866        3827 :     tdm_SM_flag_loc = tdm_last_SM_flag; /* Q0 */
     867        3827 :     move16();
     868             : 
     869        3827 :     test();
     870        3827 :     IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) && IsSideMono == 0 ) /* last coding mode not TD and normal mono/side case, quick update of lt energy */
     871             :     {
     872          62 :         *tdm_lt_rms_L = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_L ), sub( Q16, q_rms_L ) ); // (Q31, q_rms_L) -> q_rms_L -> Q16
     873          62 :         move32();
     874          62 :         *tdm_lt_rms_R = L_shl( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, rms_R ), sub( Q16, q_rms_R ) ); // (Q31, q_rms_R) -> q_rms_R -> Q16
     875          62 :         move32();
     876          62 :         L_tmp = Mpy_32_32( 1932735282 /* 0.9f in Q31 */, sts[0]->hNoiseEst->Etot_last_32fx ); //(Q31, Q24) -> Q24
     877          62 :         sts[1]->hNoiseEst->Etot_last_32fx = L_tmp;                                            // (Q24 >> Q16) -> Q8
     878          62 :         sts[1]->hVAD->hangover_cnt = 0;
     879          62 :         move16();
     880             :     }
     881             :     ELSE
     882             :     {
     883        3765 :         L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_L );                                     // Q16
     884        3765 :         L_tmp1 = Mpy_32_32( 858993459 /* 0.4f in Q31 */, rms_L );                                             // q_rms_L
     885        3765 :         *tdm_lt_rms_L = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q16, L_tmp1, sub( Q31, q_rms_L ), &exp_diff ); //(Q31 - exp_diff)
     886        3765 :         move32();
     887        3765 :         *tdm_lt_rms_L = L_shl( *tdm_lt_rms_L, sub( Q16, sub( Q31, exp_diff ) ) ); // Q16
     888        3765 :         move32();
     889        3765 :         L_tmp = Mpy_32_32( 1288490188 /* 0.6f in Q31 */, *tdm_lt_rms_R );                                     // Q16
     890        3765 :         L_tmp1 = Mpy_32_32( 858993459 /* 0.4f in Q31 */, rms_R );                                             // q_rms_L
     891        3765 :         *tdm_lt_rms_R = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q16, L_tmp1, sub( Q31, q_rms_R ), &exp_diff ); //(Q31 - exp_diff)
     892        3765 :         move32();
     893        3765 :         *tdm_lt_rms_R = L_shl( *tdm_lt_rms_R, sub( Q16, sub( Q31, exp_diff ) ) ); // Q16
     894        3765 :         move32();
     895             :     }
     896             : 
     897             :     /*----------------------------------------------------------------*
     898             :      * Compute the 1st order energy difference difference
     899             :      *----------------------------------------------------------------*/
     900             : 
     901        3827 :     *ener_R_dt = L_sub( *tdm_lt_rms_R, *tdm_last_ener_lt_R ); // Q16
     902        3827 :     move32();
     903        3827 :     *tdm_last_ener_lt_R = *tdm_lt_rms_R; // Q16
     904        3827 :     move32();
     905             : 
     906        3827 :     *ener_L_dt = L_sub( *tdm_lt_rms_L, *tdm_last_ener_lt_L ); // Q16
     907        3827 :     move32();
     908        3827 :     *tdm_last_ener_lt_L = *tdm_lt_rms_L; // Q16
     909        3827 :     move32();
     910             : 
     911             :     /*----------------------------------------------------------------*
     912             :      * Compute the gain of L&R channel compared to mono
     913             :      * - estimate the long term evolution of the L to Mono gain
     914             :      * - estimate the long term evolution of the R to Mono gain
     915             :      * - estimate the long term difference between the long term
     916             :      * - evolution of the L and R to Mono gain
     917             :      *----------------------------------------------------------------*/
     918             : 
     919        3827 :     Get_corr_n_fx( Left_in_fx, Right_in_fx, corr_LM, q_corr_LM, corr_RM, q_corr_RM, input_frame, &es_em_fx, IsSideMono );
     920             : 
     921        3827 :     hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = BASOP_Util_Add_Mant32Exp( *corr_LM, sub( Q31, *q_corr_LM ), L_negate( *corr_RM ), sub( Q31, *q_corr_RM ), &exp_diff ); /* Q31-exp_diff */
     922        3827 :     move32();
     923        3827 :     hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM] = L_shl( hCPE->hStereoClassif->xtalk_fv_fx[E_diff_corrLM_corrRM], sub( Q15, sub( Q31, exp_diff ) ) ); // Q15
     924        3827 :     move32();
     925             : 
     926        3827 :     IF( sts[0]->hVAD->hangover_cnt != 0 )
     927             :     {
     928         399 :         *tdm_LT_es_em = Mpy_32_32( 1932735282 /* 0.9f in Q31 */, *tdm_LT_es_em ); // Q21
     929         399 :         move32();
     930             :     }
     931             :     ELSE
     932             :     {
     933        3428 :         *tdm_LT_es_em = L_add( Mpy_32_32( 1932735282 /* 0.9f in Q31 */, *tdm_LT_es_em ), Mpy_32_32( 214748365 /* 0.1f in Q31 */, es_em_fx ) ); // Q21
     934        3428 :         move32();
     935             :     }
     936             : 
     937        3827 :     hCPE->hStereoClassif->xtalk_fv_fx[E_tdm_LT_es_em] = L_shr( *tdm_LT_es_em, 6 ); // Q15
     938        3827 :     move32();
     939             : 
     940        3827 :     tmp_SM_flag = 0;
     941        3827 :     move16();
     942             : 
     943        3827 :     test();
     944        3827 :     test();
     945        3827 :     test();
     946        3827 :     test();
     947        3827 :     test();
     948        3827 :     test();
     949        3827 :     IF( LT_16( s_min( sts[0]->old_corr_fx, sts[1]->old_corr_fx ), 27853 /* 0.85f in Q15 */ ) && LT_16( s_max( sts[0]->old_corr_fx, sts[1]->old_corr_fx ), 30147 /* 0.92f in Q15 */ ) &&
     950             :         ( GT_32( *tdm_LT_es_em, ONE_IN_Q22 /* 2.0f in Q21 */ ) || GT_32( es_em_fx, 5242880 /* 2.5f in Q21 */ ) ) && ( LE_16( sts[0]->hVAD->hangover_cnt, 1 ) && LE_16( sts[1]->hVAD->hangover_cnt, 3 ) && sts[0]->tdm_LRTD_flag == 0 ) )
     951             :     {
     952           1 :         tmp_SM_flag = 1;
     953           1 :         move16();
     954             :     }
     955        3827 :     if ( IsSideMono == 0 )
     956             :     {
     957        3827 :         *tdm_NOOP_SM_flag_loc = tdm_SM_flag_loc;
     958        3827 :         move16();
     959             :     }
     960             : 
     961        3827 :     IF( NE_16( tmp_SM_flag, tdm_SM_flag_loc ) )
     962             :     {
     963           1 :         test();
     964           1 :         test();
     965           1 :         test();
     966           1 :         IF( GE_16( *tdm_hyst_cnt, 2 ) && EQ_16( tmp_SM_flag, 1 ) && ( GT_16( sts[0]->tdm_pc, PC_LIMIT ) || GT_16( sts[1]->tdm_pc, PC_LIMIT ) ) )
     967             :         {
     968           0 :             tdm_hyst_cnt++;
     969           0 :             *tdm_NOOP_SM_flag_loc = tmp_SM_flag;
     970           0 :             move16();
     971           0 :             *tdm_hyst_cnt = 0;
     972           0 :             move16();
     973             :         }
     974           1 :         ELSE IF( GE_16( *tdm_hyst_cnt, 20 ) && tmp_SM_flag == 0 &&
     975             :                  ( GT_16( sts[0]->tdm_pc, PC_LIMIT ) || GT_16( sts[1]->tdm_pc, PC_LIMIT ) ) && ( LE_32( *tdm_LT_es_em, ONE_IN_Q20 /* 0.5f in Q21 */ ) || LT_32( es_em_fx, -20971520 /* -10.0f in Q21 */ ) ) )
     976             :         {
     977           0 :             tdm_hyst_cnt++;
     978           0 :             *tdm_NOOP_SM_flag_loc = tmp_SM_flag;
     979           0 :             move16();
     980           0 :             *tdm_hyst_cnt = 0;
     981           0 :             move16();
     982             :         }
     983             :     }
     984             :     ELSE
     985             :     {
     986        3826 :         *tdm_hyst_cnt = 0;
     987        3826 :         move16();
     988             :     }
     989             : 
     990        3827 :     return tmp_SM_flag; /* Q0 */
     991             : }
     992             : 
     993             : 
     994             : /*-------------------------------------------------------------------*
     995             :  * Function NOOP_decision_fx()
     996             :  *
     997             :  * Set Near Out Of Phase decision
     998             :  *-------------------------------------------------------------------*/
     999             : 
    1000        3827 : static void NOOP_decision_fx(
    1001             :     CPE_ENC_HANDLE hCPE,
    1002             :     const Word16 tdm_NOOP_flag_loc, /* Q0 */
    1003             :     const Word16 tmp_SM_flag,       /* Q0 */
    1004             :     const Word32 rms_L,             /* q_rms_L */
    1005             :     const Word16 q_rms_L,
    1006             :     const Word32 rms_R, /* q_rms_R */
    1007             :     const Word16 q_rms_R,
    1008             :     Word16 *tdm_SM_flag_loc /* Q0 */ )
    1009             : {
    1010             :     Word16 tdm_NOOP_switch_flag;
    1011             :     STEREO_TD_ENC_DATA_HANDLE hStereoTD;
    1012             :     Encoder_State **sts;
    1013             : 
    1014        3827 :     hStereoTD = hCPE->hStereoTD;
    1015        3827 :     sts = hCPE->hCoreCoder;
    1016             : 
    1017        3827 :     tdm_NOOP_switch_flag = 0;
    1018        3827 :     move16();
    1019        3827 :     hStereoTD->tdm_NOOP_cnt = add( hStereoTD->tdm_NOOP_cnt, 1 );
    1020        3827 :     move16();
    1021        3827 :     IF( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 )
    1022             :     {
    1023        3827 :         test();
    1024        3827 :         test();
    1025        3827 :         test();
    1026        3827 :         test();
    1027        3827 :         test();
    1028        3827 :         test();
    1029        3827 :         test();
    1030        3827 :         test();
    1031        3827 :         IF( ( ( GT_16( hStereoTD->tdm_SM_last2_clas[0], VOICED_TRANSITION ) && ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || EQ_16( hStereoTD->tdm_SM_last_clas[0], VOICED_TRANSITION ) ) ) ||
    1032             :               ( GT_16( hStereoTD->tdm_SM_last2_clas[1], VOICED_TRANSITION ) && ( hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS || EQ_16( hStereoTD->tdm_SM_last_clas[1], VOICED_TRANSITION ) ) ) ) &&
    1033             :             ( !( EQ_16( sts[0]->last_coder_type_raw, VOICED ) || EQ_16( sts[1]->last_coder_type_raw, VOICED ) ) && GT_16( hStereoTD->tdm_NOOP_cnt, 5 ) ) )
    1034             :         {
    1035         132 :             tdm_NOOP_switch_flag = 1;
    1036         132 :             move16();
    1037         132 :             hStereoTD->tdm_NOOP_cnt = 0;
    1038         132 :             move16();
    1039             :         }
    1040        3695 :         ELSE IF( ( hStereoTD->tdm_SM_last_clas[0] == UNVOICED_CLAS || hStereoTD->tdm_SM_last_clas[1] == UNVOICED_CLAS ) &&
    1041             :                  ( !( EQ_16( sts[0]->last_coder_type_raw, VOICED ) || EQ_16( sts[1]->last_coder_type_raw, VOICED ) ) ) && ( LT_32( L_shr( rms_L, q_rms_L ), 400 ) && LT_32( L_shr( rms_R, q_rms_R ), 400 ) ) && GT_16( hStereoTD->tdm_NOOP_cnt, 5 ) )
    1042             :         {
    1043          62 :             tdm_NOOP_switch_flag = 1;
    1044          62 :             move16();
    1045          62 :             hStereoTD->tdm_NOOP_cnt = 0;
    1046          62 :             move16();
    1047             :         }
    1048             :     }
    1049             :     ELSE
    1050             :     {
    1051           0 :         if ( LT_32( sts[0]->ee_old_fx, 320000 /* 5000.f in Q6 */ ) && LT_32( sts[1]->ee_old_fx, 320000 /* 5000.f in Q6 */ ) )
    1052             :         {
    1053           0 :             tdm_NOOP_switch_flag = 1;
    1054           0 :             move16();
    1055             :         }
    1056             :     }
    1057             : 
    1058        3827 :     IF( NE_16( *tdm_SM_flag_loc, tdm_NOOP_flag_loc ) )
    1059             :     {
    1060           0 :         hStereoTD->tdm_SM_flag = 1;
    1061           0 :         move16();
    1062           0 :         IF( hCPE->hCoreCoder[0]->sp_aud_decision0 == 0 )
    1063             :         {
    1064           0 :             IF( EQ_16( tdm_NOOP_switch_flag, 1 ) )
    1065             :             {
    1066           0 :                 *tdm_SM_flag_loc = tdm_NOOP_flag_loc;
    1067           0 :                 move16();
    1068           0 :                 if ( *tdm_SM_flag_loc )
    1069             :                 {
    1070           0 :                     hStereoTD->tdm_SM_reset_flag = 1;
    1071           0 :                     move16();
    1072             :                 }
    1073           0 :                 hStereoTD->tdm_SM_flag = 0;
    1074           0 :                 move16();
    1075             :             }
    1076             :         }
    1077             :         ELSE
    1078             :         {
    1079           0 :             IF( EQ_16( tdm_NOOP_switch_flag, 1 ) )
    1080             :             {
    1081           0 :                 *tdm_SM_flag_loc = tdm_NOOP_flag_loc;
    1082           0 :                 move16();
    1083           0 :                 if ( *tdm_SM_flag_loc )
    1084             :                 {
    1085           0 :                     hStereoTD->tdm_SM_reset_flag = 1;
    1086           0 :                     move16();
    1087             :                 }
    1088           0 :                 hStereoTD->tdm_SM_flag = 0;
    1089           0 :                 move16();
    1090             :             }
    1091             :         }
    1092             : 
    1093           0 :         IF( EQ_16( tdm_NOOP_flag_loc, 1 ) )
    1094             :         {
    1095           0 :             hStereoTD->tdm_hyst_cnt = 2;
    1096           0 :             move16();
    1097             :         }
    1098             :         ELSE
    1099             :         {
    1100           0 :             hStereoTD->tdm_hyst_cnt = 20;
    1101           0 :             move16();
    1102             :         }
    1103             :     }
    1104             : 
    1105        3827 :     test();
    1106        3827 :     test();
    1107        3827 :     IF( GT_16( hStereoTD->tdm_SM_flag, 0 ) && EQ_16( tdm_NOOP_switch_flag, 1 ) && NE_16( *tdm_SM_flag_loc, tmp_SM_flag ) )
    1108             :     {
    1109           0 :         *tdm_SM_flag_loc = !( *tdm_SM_flag_loc );
    1110           0 :         move16();
    1111           0 :         hStereoTD->tdm_SM_flag = 0;
    1112           0 :         move16();
    1113           0 :         if ( *tdm_SM_flag_loc )
    1114             :         {
    1115           0 :             hStereoTD->tdm_SM_reset_flag = 1;
    1116           0 :             move16();
    1117             :         }
    1118             :     }
    1119             : 
    1120        3827 :     IF( EQ_16( hStereoTD->tdm_SM_modi_flag, 1 ) )
    1121             :     {
    1122           0 :         *tdm_SM_flag_loc = 1;
    1123           0 :         move16();
    1124           0 :         hStereoTD->tdm_SM_modi_flag = 0;
    1125           0 :         move16();
    1126           0 :         hStereoTD->tdm_SM_reset_flag = 1;
    1127           0 :         move16();
    1128             :     }
    1129             :     ELSE
    1130             :     {
    1131        3827 :         IF( EQ_16( *tdm_SM_flag_loc, 1 ) && EQ_16( hStereoTD->tdm_SM_reset_flag, 1 ) && LT_32( hStereoTD->tdm_last_ratio_fx, 1073741824 /* 0.5 in Q31 */ ) )
    1132             :         {
    1133           0 :             hStereoTD->tdm_SM_reset_flag = 0;
    1134           0 :             move16();
    1135           0 :             *tdm_SM_flag_loc = 0;
    1136           0 :             move16();
    1137           0 :             hStereoTD->tdm_SM_modi_flag = 1;
    1138           0 :             move16();
    1139             :         }
    1140             :     }
    1141             : 
    1142        3827 :     return;
    1143             : }
    1144             : 
    1145             : 
    1146             : /*-------------------------------------------------------------------*
    1147             :  * Function Comp_diff_lt_corr_fx()
    1148             :  *
    1149             :  * Adjust stereo downmixing adaptation rate factor
    1150             :  * in function of the signal energy.
    1151             :  *-------------------------------------------------------------------*/
    1152             : 
    1153        3827 : static Word32 Comp_diff_lt_corr_fx(
    1154             :     CPE_ENC_HANDLE hCPE,
    1155             :     const Word16 IsSideMono, /* Q0 */
    1156             :     const Word32 rms_L,      /* q_rms_L */
    1157             :     const Word16 q_rms_L,
    1158             :     const Word32 rms_R, /* q_rms_R */
    1159             :     const Word16 q_rms_R,
    1160             :     const Word32 ener_L_dt, /* Q16 */
    1161             :     const Word32 ener_R_dt, /* Q16 */
    1162             :     Word32 corr_LM,         /* q_corr_LM */
    1163             :     Word16 q_corr_LM,
    1164             :     Word32 corr_RM, /* q_corr_RM */
    1165             :     Word16 q_corr_RM,
    1166             :     const Word32 tdm_lt_rms_L,     /* Q16 */
    1167             :     const Word32 tdm_lt_rms_R,     /* Q16 */
    1168             :     Word32 *tdm_lt_corr_LM,        /* Q24 */
    1169             :     Word32 *tdm_lt_corr_RM,        /* Q24 */
    1170             :     Word32 *tdm_last_diff_lt_corr, /* q_tdm_last_diff_lt_corr */
    1171             :     Word16 *q_tdm_last_diff_lt_corr,
    1172             :     Word32 *inst_ratio_L_out, /* Q24 */
    1173             :     Word32 *diff_lt_corr,     /* q_d_lt_corr_raw */
    1174             :     Word16 *q_d_lt_corr_raw )
    1175             : {
    1176             :     Encoder_State **sts;
    1177             :     Word32 adaprate_fx;
    1178             :     Word32 adaprate_tmp_fx;
    1179             :     Word32 madaprate_fx;
    1180             :     Word32 d_lt_corr_raw_fx;
    1181             :     Word32 L_tmp, L_tmp1, L_tmp2;
    1182             :     Word16 q_tmp, q_tmp1;
    1183             :     Word16 exp_diff;
    1184             :     Word32 inst_ratio_L_fx;
    1185             :     Word16 angle;
    1186             :     Word32 diff_lt_corr_LM_tmp_fx, diff_lt_corr_RM_tmp_fx;
    1187             :     Word16 q_diff_lt_corr_LM_tmp, q_diff_lt_corr_RM_tmp;
    1188             :     Word32 diff_lt_corr_tmp_fx;
    1189             :     Word16 q_diff_lt_corr_tmp;
    1190             :     Word32 d_lt_corr_fx;
    1191             :     Word16 q_d_lt_corr;
    1192             :     Word16 d_lt_corr_shift, shift, q_com;
    1193             : 
    1194        3827 :     sts = hCPE->hCoreCoder;
    1195             : 
    1196             :     /*----------------------------------------------------------------*
    1197             :      * Adjust stereo downmixing adaptation rate factor
    1198             :      * in function of the signal energy. If signal energy is low,
    1199             :      * adaptation rate factor is lower. This prevent stereo image
    1200             :      * move on speech offset
    1201             :      *----------------------------------------------------------------*/
    1202        3827 :     test();
    1203        3827 :     test();
    1204        3827 :     test();
    1205        3827 :     IF( IsSideMono == 0 && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && ( GT_32( L_shr( tdm_lt_rms_R, Q1 ), tdm_lt_rms_L ) || GT_32( L_shr( tdm_lt_rms_L, Q1 ), tdm_lt_rms_R ) ) )
    1206             :     {
    1207        1523 :         adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_max( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q16 ); // Q16
    1208             :     }
    1209             :     ELSE
    1210             :     {
    1211        2304 :         adaprate_fx = L_add( Mpy_32_32( M_ADAP_FX_Q31, L_min( tdm_lt_rms_R, tdm_lt_rms_L ) ), B_ADAP_FX_Q16 ); // Q16
    1212             :     }
    1213             : 
    1214        3827 :     adaprate_fx = check_bounds_l( adaprate_fx, MIN_ADAP_FAC_FX_Q16, ONE_IN_Q16 ); // Q16
    1215             : 
    1216             :     /*----------------------------------------------------------------*
    1217             :      * In case of unvoiced content (expect when it is part of an onset),
    1218             :      * the adaptation rate is minimal.
    1219             :      *----------------------------------------------------------------*/
    1220        3827 :     test();
    1221        3827 :     test();
    1222        3827 :     test();
    1223        3827 :     test();
    1224        3827 :     IF( GT_16( sts[0]->ini_frame, 2 ) &&
    1225             :         ( ( LE_16( sts[0]->last_clas, VOICED_TRANSITION ) && sts[0]->hVAD->hangover_cnt == 0 ) ||
    1226             :           ( LE_16( sts[1]->last_clas, VOICED_TRANSITION ) && sts[1]->hVAD->hangover_cnt == 0 ) ) )
    1227             :     {
    1228        2007 :         adaprate_fx = L_min( adaprate_fx, LIMIT_ADAP_FAC_FX_Q16 ); // Q16
    1229             :     }
    1230             : 
    1231        3827 :     d_lt_corr_raw_fx = 0;
    1232        3827 :     move32();
    1233             : 
    1234        3827 :     IF( IsSideMono == 0 )
    1235             :     {
    1236        3827 :         test();
    1237        3827 :         test();
    1238        3827 :         test();
    1239        3827 :         test();
    1240        3827 :         IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) || ( ( LT_32( tdm_lt_rms_R, ONE_IN_Q16 ) || LT_32( tdm_lt_rms_L, ONE_IN_Q16 ) ) && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && LT_32( L_max( tdm_lt_rms_R, tdm_lt_rms_L ), TEN_IN_Q16 ) ) )
    1241             :         {
    1242          80 :             adaprate_fx = 64225; /* 0.98f in Q16 */ /* speed up the adaptation of the long term values to the current values after coming from DFT */
    1243          80 :             move32();
    1244             :         }
    1245        3827 :         adaprate_tmp_fx = L_max( adaprate_fx, 52429 /* 0.8f in Q16 */ );                                                       // Q16
    1246        3827 :         madaprate_fx = L_sub( ONE_IN_Q16, adaprate_tmp_fx ); /* madaprate has temporary value, will updated few lines below */ // Q16
    1247             : 
    1248        3827 :         L_tmp = Mpy_32_32( adaprate_tmp_fx, corr_LM );                                                             // (Q16, q_corr_LM) -> q_corr_LM - Q15
    1249        3827 :         L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM );                                                       // (Q16, Q24) -> Q9
    1250        3827 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, sub( q_corr_LM, Q15 ) ), L_tmp1, Q31 - Q9, &exp_diff ); // Q31 - exp_diff
    1251        3827 :         q_tmp = sub( Q31, exp_diff );
    1252             : 
    1253        3827 :         L_tmp2 = Mpy_32_32( adaprate_tmp_fx, corr_RM );                                                              // (Q16, q_corr_RM) -> q_corr_RM - Q15
    1254        3827 :         L_tmp1 = Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM );                                                         // (Q16, Q24) -> Q9
    1255        3827 :         L_tmp1 = BASOP_Util_Add_Mant32Exp( L_tmp2, sub( Q31, sub( q_corr_RM, Q15 ) ), L_tmp1, Q31 - Q9, &exp_diff ); // Q31 - exp_diff
    1256        3827 :         q_tmp1 = sub( Q31, exp_diff );
    1257             : 
    1258        3827 :         d_lt_corr_raw_fx = BASOP_Util_Add_Mant32Exp( L_tmp, sub( Q31, q_tmp ), L_negate( L_tmp1 ), sub( Q31, q_tmp1 ), &exp_diff ); // Q31 - exp_diff
    1259        3827 :         *q_d_lt_corr_raw = sub( Q31, exp_diff );
    1260        3827 :         move16();
    1261        3827 :         q_com = s_min( *q_d_lt_corr_raw, Q29 );
    1262             : 
    1263        3827 :         inst_ratio_L_fx = 0;
    1264        3827 :         move32();
    1265        3827 :         inst_ratio_L_fx = L_max( L_shl( d_lt_corr_raw_fx, sub( q_com, *q_d_lt_corr_raw ) ), L_negate( L_shl( RATIO_MAX_FX_Q30, sub( q_com, Q30 ) ) ) ); // q_com
    1266        3827 :         inst_ratio_L_fx = L_min( inst_ratio_L_fx, L_shl( RATIO_MAX_FX_Q30, sub( q_com, Q30 ) ) );                                                       // q_com
    1267        3827 :         inst_ratio_L_fx = L_add( Mpy_32_32( 1432371593 /* 0.667f in Q31 */, inst_ratio_L_fx ), L_shl( 1, q_com ) );                                     // q_com
    1268        3827 :         angle = extract_l( L_shl( Mpy_32_16_1( inst_ratio_L_fx, EVS_PI_FX ), sub( sub( Q13, sub( q_com, Q2 ) ), Q1 ) ) );                               // (q_com, Q13) -> q_com - Q2 -> Q13 >> Q1
    1269        3827 :         *inst_ratio_L_out = L_shl( L_shr( L_sub( ONE_IN_Q14, L_deposit_l( getCosWord16( angle ) ) ), Q1 ), Q24 - Q14 );                                 // Q14 << Q10 -> Q24
    1270             :     }
    1271        3827 :     madaprate_fx = L_sub( ONE_IN_Q16, adaprate_fx );                                                                                                                             // Q16
    1272        3827 :     corr_RM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_RM ), sub( Q31, sub( q_corr_RM, Q15 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_RM ), Q31 - Q9, &exp_diff ); // Q31 - exp_diff
    1273        3827 :     q_corr_RM = sub( Q31, exp_diff );
    1274        3827 :     corr_LM = BASOP_Util_Add_Mant32Exp( Mpy_32_32( adaprate_fx, corr_LM ), sub( Q31, sub( q_corr_LM, Q15 ) ), Mpy_32_32( madaprate_fx, *tdm_lt_corr_LM ), Q31 - Q9, &exp_diff ); // Q31 - exp_diff
    1275        3827 :     q_corr_LM = sub( Q31, exp_diff );
    1276             : 
    1277        3827 :     L_tmp = Mpy_32_32( ALP_REF_FX_Q31, *tdm_lt_corr_LM );                                                            // Q24
    1278        3827 :     L_tmp1 = Mpy_32_32( BET_REF_FX_Q31, corr_LM );                                                                   // q_corr_LM
    1279        3827 :     diff_lt_corr_LM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); /* Q31-exp_diff */
    1280        3827 :     q_diff_lt_corr_LM_tmp = sub( Q31, exp_diff );
    1281        3827 :     L_tmp = Mpy_32_32( ALP_REF_FX_Q31, *tdm_lt_corr_RM );                                                            // Q24
    1282        3827 :     L_tmp1 = Mpy_32_32( BET_REF_FX_Q31, corr_RM );                                                                   // q_corr_RM
    1283        3827 :     diff_lt_corr_RM_tmp_fx = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); /* Q31-exp_diff */
    1284        3827 :     q_diff_lt_corr_RM_tmp = sub( Q31, exp_diff );
    1285        3827 :     diff_lt_corr_tmp_fx = BASOP_Util_Add_Mant32Exp( diff_lt_corr_LM_tmp_fx, sub( Q31, q_diff_lt_corr_LM_tmp ), L_negate( diff_lt_corr_RM_tmp_fx ), sub( Q31, q_diff_lt_corr_RM_tmp ), &exp_diff ); // (Q31 - exp_diff)
    1286        3827 :     q_diff_lt_corr_tmp = sub( Q31, exp_diff );
    1287             : 
    1288        3827 :     d_lt_corr_fx = BASOP_Util_Add_Mant32Exp( diff_lt_corr_tmp_fx, sub( Q31, q_diff_lt_corr_tmp ), L_negate( *tdm_last_diff_lt_corr ), sub( Q31, *q_tdm_last_diff_lt_corr ), &exp_diff ); // (Q31 - exp_diff)
    1289        3827 :     q_d_lt_corr = sub( Q31, exp_diff );
    1290        3827 :     IF( GT_16( q_d_lt_corr, Q31 ) )
    1291             :     {
    1292        3634 :         d_lt_corr_shift = sub( Q31, q_d_lt_corr );
    1293        3634 :         shift = 0;
    1294        3634 :         move16();
    1295             :     }
    1296             :     ELSE
    1297             :     {
    1298         193 :         d_lt_corr_shift = 0;
    1299         193 :         move16();
    1300         193 :         shift = sub( q_d_lt_corr, Q31 );
    1301             :     }
    1302        3827 :     *tdm_last_diff_lt_corr = diff_lt_corr_tmp_fx; /* q_tdm_last_diff_lt_corr */
    1303        3827 :     move32();
    1304        3827 :     *q_tdm_last_diff_lt_corr = q_diff_lt_corr_tmp;
    1305        3827 :     move16();
    1306             : 
    1307             :     /*----------------------------------------------------------------*
    1308             :      * Correct the estimation depending of channels energies evolution
    1309             :      *----------------------------------------------------------------*/
    1310        3827 :     test();
    1311        3827 :     test();
    1312        3827 :     test();
    1313        3827 :     test();
    1314        3827 :     test();
    1315        3827 :     test();
    1316        3827 :     test();
    1317        3827 :     test();
    1318        3827 :     test();
    1319        3827 :     test();
    1320        3827 :     test();
    1321        3827 :     test();
    1322        3827 :     IF( EQ_16( IsSideMono, 1 ) &&
    1323             :         ( ( LT_32( L_shl( rms_L, sub( Q21, q_rms_L ) ), RMS_MIN2_FX_Q21 ) &&
    1324             :             LT_32( L_shl( rms_R, sub( Q21, q_rms_R ) ), RMS_MIN2_FX_Q21 ) ) &&
    1325             :           ( LT_32( tdm_lt_rms_L, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_L ), sub( Q16, q_rms_L ) ) ) &&
    1326             :             LT_32( tdm_lt_rms_R, L_shl( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, rms_R ), sub( Q16, q_rms_R ) ) ) ) &&
    1327             :           ( GT_32( tdm_lt_rms_L, L_shl( tdm_lt_rms_R, Q1 ) ) ||
    1328             :             LT_32( tdm_lt_rms_L, L_shr( tdm_lt_rms_R, Q1 ) ) ) ) )
    1329             :     {
    1330           0 :         L_tmp = Mpy_32_32( ALP2_FX_Q31, *tdm_lt_corr_LM );                                              // Q24
    1331           0 :         L_tmp1 = Mpy_32_32( BET2_FX_Q31, corr_LM );                                                     // q_corr_LM
    1332           0 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); // (Q31 - exp_diff)
    1333           0 :         *tdm_lt_corr_LM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) );                             // Q24
    1334           0 :         move32();
    1335           0 :         L_tmp = Mpy_32_32( ALP2_FX_Q31, *tdm_lt_corr_RM );                                              // Q24
    1336           0 :         L_tmp1 = Mpy_32_32( BET2_FX_Q31, corr_RM );                                                     // q_corr_RM
    1337           0 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); // (Q31 - exp_diff)
    1338           0 :         *tdm_lt_corr_RM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) );                             // Q24
    1339           0 :         move32();
    1340             : 
    1341           0 :         *tdm_lt_corr_LM = L_shl( Mpy_32_32( *tdm_lt_corr_LM, 1342177280 /* 2.5f in Q29 */ ), Q24 - Q22 ); // ((Q24, Q29) -> Q22 << 2) -> Q24
    1342           0 :         move32();
    1343           0 :         *tdm_lt_corr_RM = L_shl( Mpy_32_32( *tdm_lt_corr_RM, 1342177280 /* 2.5f in Q29 */ ), Q24 - Q22 ); // ((Q24, Q29) -> Q22 << 2) -> Q24
    1344           0 :         move32();
    1345             :     }
    1346        3827 :     ELSE IF( ( !( ( GT_32( ener_R_dt, DT_ENER_THR_FX_Q16 ) && LT_32( ener_L_dt, DT_ENER_THR_FX_Q16 ) ) ||
    1347             :                   ( LT_32( ener_R_dt, DT_ENER_THR_FX_Q16 ) && GT_32( ener_L_dt, DT_ENER_THR_FX_Q16 ) ) )                                                      /* Energy are going in the same direction */
    1348             :                && ( LT_32( L_abs( L_shl( d_lt_corr_fx, d_lt_corr_shift ) ), L_shl( 665719931 /* 0.31f in Q31 */, shift ) )                                    /* small difference regarding the difference gain evolution */
    1349             :                     || GT_32( tdm_lt_rms_L, L_shl( RMS_MIN2_FX_Q21, Q16 - Q21 + Q1 ) ) || GT_32( tdm_lt_rms_R, L_shl( RMS_MIN2_FX_Q21, Q16 - Q21 + Q1 ) ) ) ) /* Energy of at least one of the channel is not low */
    1350             :     )
    1351             :     {
    1352             :         /* Use estimated results */
    1353        2976 :         *tdm_lt_corr_LM = L_shl( diff_lt_corr_LM_tmp_fx, sub( Q24, q_diff_lt_corr_LM_tmp ) ); /* Q24 */
    1354        2976 :         move32();
    1355        2976 :         *tdm_lt_corr_RM = L_shl( diff_lt_corr_RM_tmp_fx, sub( Q24, q_diff_lt_corr_RM_tmp ) ); /* Q24 */
    1356        2976 :         move32();
    1357             :     }
    1358             :     ELSE
    1359             :     {
    1360         851 :         L_tmp = Mpy_32_32( ALP1_FX_Q31, *tdm_lt_corr_LM );                                              // Q24
    1361         851 :         L_tmp1 = Mpy_32_32( BET1_FX_Q31, corr_LM );                                                     // q_corr_LM
    1362         851 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_LM ), &exp_diff ); // (Q31 - exp_diff)
    1363         851 :         *tdm_lt_corr_LM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) );                             // Q24
    1364         851 :         move32();
    1365         851 :         L_tmp = Mpy_32_32( ALP1_FX_Q31, *tdm_lt_corr_RM );                                              // Q24
    1366         851 :         L_tmp1 = Mpy_32_32( BET1_FX_Q31, corr_RM );                                                     // q_corr_RM
    1367         851 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, Q31 - Q24, L_tmp1, sub( Q31, q_corr_RM ), &exp_diff ); // (Q31 - exp_diff)
    1368         851 :         *tdm_lt_corr_RM = L_shl( L_tmp, sub( Q24, sub( Q31, exp_diff ) ) );                             // Q24
    1369         851 :         move32();
    1370             :     }
    1371             : 
    1372        3827 :     *diff_lt_corr = L_sub( *tdm_lt_corr_LM, *tdm_lt_corr_RM ); /* update the difference */ // Q24
    1373        3827 :     move32();
    1374             : 
    1375        3827 :     return d_lt_corr_raw_fx;
    1376             : }
    1377             : 
    1378             : 
    1379             : /*-------------------------------------------------------------------*
    1380             :  * Function limit_idx_Dnwmix_fx()
    1381             :  *
    1382             :  *
    1383             :  *-------------------------------------------------------------------*/
    1384             : 
    1385         129 : static Word16 limit_idx_Dwnmix_fx(
    1386             :     const Word16 idx_in,                  /* Q0 */
    1387             :     const Word16 unclr_decision,          /* Q0 */
    1388             :     const Word16 inst_idx,                /* Q0 */
    1389             :     const Word16 previous_idx,            /* Q0 */
    1390             :     const Word16 tdm_last_LRTD_PriCh_cnt, /* Q0 */
    1391             :     const Word16 tdm_last_LRTD_frame_cnt /* Q0 */ )
    1392             : {
    1393             :     Word16 idx;
    1394             : 
    1395         129 :     idx = idx_in;
    1396         129 :     move16();
    1397         129 :     idx = check_bounds_s_fx( idx, 1, 29 ); /* Q0 */
    1398             : 
    1399         129 :     test();
    1400         129 :     IF( EQ_16( unclr_decision, 1 ) && GT_16( tdm_last_LRTD_frame_cnt, 1 ) )
    1401             :     {
    1402          60 :         IF( tdm_last_LRTD_PriCh_cnt > 0 )
    1403             :         {
    1404          59 :             test();
    1405          59 :             test();
    1406          59 :             IF( LE_16( idx, LRTD_STEREO_MID_IS_PRIM ) && LT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM + 2 ) )
    1407             :             {
    1408          17 :                 idx = s_min( 1, idx );
    1409             :             }
    1410          42 :             ELSE IF( GE_16( idx, LRTD_STEREO_MID_IS_PRIM ) && GT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM - 2 ) )
    1411             :             {
    1412          37 :                 idx = s_max( 29, idx );
    1413             :             }
    1414           5 :             ELSE IF( LT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM - 4 ) )
    1415             :             {
    1416           1 :                 idx = s_min( 1, idx );
    1417             :             }
    1418           4 :             ELSE IF( GT_16( inst_idx, LRTD_STEREO_MID_IS_PRIM + 4 ) )
    1419             :             {
    1420           1 :                 idx = s_max( 29, idx );
    1421             :             }
    1422             :             ELSE
    1423             :             {
    1424           3 :                 idx = previous_idx;
    1425           3 :                 move16();
    1426             :             }
    1427             :         }
    1428             :         ELSE
    1429             :         {
    1430           1 :             idx = previous_idx;
    1431           1 :             move16();
    1432             :         }
    1433             :     }
    1434             : 
    1435         129 :     return idx; /* Q0 */
    1436             : }
    1437             : 
    1438             : 
    1439             : /*-------------------------------------------------------------------*
    1440             :  * Function limit_idx_NoDwnmix_fx()
    1441             :  *
    1442             :  *-------------------------------------------------------------------*/
    1443             : 
    1444        3598 : static Word16 limit_idx_NoDwnmix_fx(
    1445             :     const Word16 idx_in,          /* i  : Index Q0*/
    1446             :     const Word16 side_can_change, /* i  : Primary and secondary channel allowed to change ? Q0*/
    1447             :     const Word32 d_lt_corr_raw,   /* i  : Raw corrrelation differences q_d_lt_corr_raw*/
    1448             :     const Word16 q_d_lt_corr_raw  /* i  : Q-factor of Raw corrrelation differences */
    1449             : )
    1450             : {
    1451             :     Word16 idx;
    1452             : 
    1453        3598 :     idx = idx_in;
    1454        3598 :     move16();
    1455             : 
    1456        3598 :     test();
    1457        3598 :     test();
    1458        3598 :     IF( side_can_change == 0 && GT_16( idx_in, 10 ) && LT_16( idx_in, 20 ) )
    1459             :     {
    1460           0 :         idx = 30;
    1461           0 :         move16();
    1462           0 :         IF( LT_32( d_lt_corr_raw, L_negate( L_shl( 214748365 /* 0.1f in Q31 */, sub( q_d_lt_corr_raw, Q31 ) ) ) ) )
    1463             :         {
    1464           0 :             idx = 0;
    1465           0 :             move16();
    1466             :         }
    1467             :     }
    1468             :     ELSE
    1469             :     {
    1470        3598 :         IF( LE_16( idx, 15 ) )
    1471             :         {
    1472         268 :             idx = 0;
    1473         268 :             move16();
    1474             :         }
    1475             :         ELSE
    1476             :         {
    1477        3330 :             idx = 30;
    1478        3330 :             move16();
    1479             :         }
    1480             :     }
    1481             : 
    1482        3598 :     return idx; /* Q0 */
    1483             : }
    1484             : 
    1485             : 
    1486             : /*-------------------------------------------------------------------*
    1487             :  * Function stereo_tdm_ener_analysis_SM_fx()
    1488             :  *
    1489             :  *
    1490             :  *-------------------------------------------------------------------*/
    1491             : 
    1492           0 : static Word16 stereo_tdm_ener_analysis_SM_fx(
    1493             :     CPE_ENC_HANDLE hCPE,      /* i  : CPE encoder structure               */
    1494             :     Encoder_State **sts,      /* i/o: Encoder static variables structure  */
    1495             :     const Word16 input_frame, /* i  : Number of samples                   Q0*/
    1496             :     Word16 *tdm_SM_flag       /* i/o: channel combination scheme flag     Q0*/
    1497             : )
    1498             : {
    1499             :     Word32 rms_R_fx, rms_L_fx;
    1500             :     Word16 q_rms_R, q_rms_L;
    1501             :     Word32 corr_RM_fx, corr_LM_fx;
    1502             :     Word16 q_corr_LM, q_corr_RM;
    1503             :     Word32 diff_lt_corr_fx;
    1504             :     Word32 ratio_L_fx;
    1505             :     Word32 dist_fx;
    1506             :     Word16 i, side_can_change;
    1507             :     Word16 idx, tdm_SM_flag_loc;
    1508             :     Word32 es_em_fx;
    1509             :     Word32 ener_R_dt_fx, ener_L_dt_fx;
    1510             :     Word16 desired_idx;
    1511             :     STEREO_TD_ENC_DATA_HANDLE hStereoTD;
    1512             :     Word16 angle;
    1513             : 
    1514           0 :     hStereoTD = hCPE->hStereoTD;
    1515           0 :     desired_idx = 0;
    1516           0 :     move16();
    1517           0 :     es_em_fx = 20972; /* 0.01f in Q21 */
    1518           0 :     move32();
    1519             : 
    1520             :     /*----------------------------------------------------------------*
    1521             :      * set SM flag
    1522             :      *----------------------------------------------------------------*/
    1523             : 
    1524             :     /* Simple logic to set SM flag, should be done in the frequency domain for low SM correlation signal, especially for music item such as Music_1_org_s */
    1525           0 :     tdm_SM_flag_loc = hStereoTD->tdm_last_SM_flag_noop; /* Q0 */
    1526           0 :     move16();
    1527             : 
    1528             :     /*----------------------------------------------------------------*
    1529             :      * Compute L and R energy and Long term RMS of each channel
    1530             :      *----------------------------------------------------------------*/
    1531             : 
    1532           0 :     Get_LR_rms_fx( sts[0]->input_fx, sts[1]->input_fx, input_frame, &rms_L_fx, &q_rms_L, &rms_R_fx, &q_rms_R );
    1533             : 
    1534             :     /*----------------------------------------------------------------*
    1535             :      * Compute the 1st order energy difference difference
    1536             :      * Compute the gain of L&R channel compared to mono
    1537             :      * - estimate the long term evolution of the L to Mono gain
    1538             :      * - estimate the long term evolution of the R to Mono gain
    1539             :      * - estimate the long term difference between the long term
    1540             :      * - evolution of the L and R to Mono gain
    1541             :      *----------------------------------------------------------------*/
    1542             : 
    1543           0 :     Get_dt_lt_ener_fx( hCPE, 1, input_frame, hStereoTD->tdm_last_SM_flag_noop, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R,
    1544             :                        &hStereoTD->tdm_lt_rms_L_SM_fx, &hStereoTD->tdm_lt_rms_R_SM_fx, &hStereoTD->tdm_last_ener_lt_L_SM_fx, &hStereoTD->tdm_last_ener_lt_R_SM_fx, &hStereoTD->tdm_LT_es_em_SM_fx, &hStereoTD->tdm_hyst_cnt_SM, &tdm_SM_flag_loc,
    1545             :                        &ener_R_dt_fx, &ener_L_dt_fx, &corr_LM_fx, &q_corr_LM, &corr_RM_fx, &q_corr_RM );
    1546             : 
    1547           0 :     hStereoTD->tdm_SM_reset_flag = 0;
    1548           0 :     move16();
    1549             : 
    1550             :     /*----------------------------------------------------------------*
    1551             :      * Adjust stereo downmixing adaptation rate factor
    1552             :      * in function of the signal energy. If signal energy is low,
    1553             :      * adaptation rate factor is lower. This prevent stereo image
    1554             :      * move on speech offset
    1555             :      *----------------------------------------------------------------*/
    1556             : 
    1557           0 :     Comp_diff_lt_corr_fx( hCPE, 1, rms_L_fx, q_rms_L, rms_R_fx, q_rms_R, ener_L_dt_fx, ener_R_dt_fx, corr_LM_fx, q_corr_LM, corr_RM_fx, q_corr_RM, hStereoTD->tdm_lt_rms_L_SM_fx, hStereoTD->tdm_lt_rms_R_SM_fx, &hStereoTD->tdm_lt_corr_LM_SM_fx,
    1558             :                           &hStereoTD->tdm_lt_corr_RM_SM_fx, &hStereoTD->tdm_last_diff_lt_corr_SM_fx, &hStereoTD->q_tdm_last_diff_lt_corr_SM, NULL, &diff_lt_corr_fx, NULL );
    1559             : 
    1560           0 :     side_can_change = 0;
    1561           0 :     move16();
    1562             : 
    1563             :     /*----------------------------------------------------------------*
    1564             :      * When the energies of channels are low enough, compute the ratio
    1565             :      * of L and R needed to create new mono/side signals
    1566             :      *----------------------------------------------------------------*/
    1567           0 :     test();
    1568           0 :     test();
    1569           0 :     test();
    1570           0 :     IF( ( LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q20 - Q24 ), RMS_MIN_FX_Q20 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q19 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN_FX_Q20 ) ) ||
    1571             :         ( LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q20 - Q24 ), RMS_MIN_FX_Q20 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q19 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN_FX_Q20 ) ) ) /* Q20 */
    1572             :     {
    1573           0 :         test();
    1574           0 :         test();
    1575           0 :         test();
    1576           0 :         IF( ( LT_16( sts[0]->old_corr_fx, CORR_THRES_FX_Q15 ) && LT_16( sts[1]->old_corr_fx, CORR_THRES_FX_Q15 ) ) ||
    1577             :             ( LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) ) )
    1578             :         {
    1579           0 :             side_can_change = 1;
    1580           0 :             move16();
    1581             :         }
    1582             :     }
    1583             : 
    1584           0 :     test();
    1585           0 :     test();
    1586           0 :     test();
    1587           0 :     IF( ( LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q20 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN2_FX_Q21 ) ) ||
    1588             :         ( LE_32( L_shl( hStereoTD->tdm_lt_rms_R_SM_fx, Q21 - Q24 ), RMS_MIN2_FX_Q21 ) && LE_32( L_shl( hStereoTD->tdm_lt_rms_L_SM_fx, Q20 /* adjusted for 2 in RHS */ - Q24 ), RMS_MIN2_FX_Q21 ) ) ) /* Q21 */
    1589             :     {
    1590           0 :         test();
    1591           0 :         test();
    1592           0 :         test();
    1593           0 :         IF( ( ( NE_16( hStereoTD->tdm_last_SM_flag_noop, tdm_SM_flag_loc ) ) && hStereoTD->tdm_noop_cnt == 0 ) ||
    1594             :             EQ_16( hStereoTD->tdm_noop_mov_flag, 1 ) || NE_16( hStereoTD->tdm_prev_desired_idx_SM, hStereoTD->tdm_prev_stable_idx_SM ) )
    1595             :         {
    1596           0 :             hStereoTD->tdm_noop_mov_flag = 1;
    1597           0 :             move16();
    1598           0 :             IF( hStereoTD->tdm_last_ratio_idx_SM != 0 && NE_16( hStereoTD->tdm_last_ratio_idx_SM, ( TDM_NQ - 1 ) ) )
    1599             :             {
    1600           0 :                 side_can_change = 1;
    1601           0 :                 move16();
    1602             :             }
    1603             :         }
    1604             :     }
    1605             : 
    1606           0 :     test();
    1607           0 :     IF( side_can_change == 0 && EQ_16( tdm_SM_flag_loc, 1 ) && GT_32( es_em_fx, 31457280 /* 15.0f in Q21 */ ) )
    1608             :     {
    1609           0 :         side_can_change = 1;
    1610           0 :         move16();
    1611             :     }
    1612             : 
    1613           0 :     IF( side_can_change )
    1614             :     {
    1615           0 :         ratio_L_fx = L_max( diff_lt_corr_fx, -RATIO_MAX_FX_Q24 ); // Q24
    1616           0 :         ratio_L_fx = L_min( ratio_L_fx, RATIO_MAX_FX_Q24 );       // Q24
    1617             : 
    1618           0 :         IF( GT_32( ratio_L_fx, RATIO_MAX_FX_Q23 ) )
    1619             :         {
    1620           0 :             ratio_L_fx = L_add( Mpy_32_32( 1159641170 /* 1.08f in Q30 */, ratio_L_fx ), 3187671 /* 0.38f in Q23 */ ); // (Q30, Q24) -> Q23
    1621             :         }
    1622           0 :         ELSE IF( LT_32( ratio_L_fx, -RATIO_MAX_FX_Q23 ) )
    1623             :         {
    1624           0 :             ratio_L_fx = L_add( Mpy_32_32( 687194767 /* 0.64f in Q30 */, ratio_L_fx ), 10737418 /* 1.28f in Q23 */ ); // (Q30, Q24) -> Q23
    1625             :         }
    1626             :         ELSE
    1627             :         {
    1628           0 :             ratio_L_fx = L_add( Mpy_32_32( 279172874 /* 0.26f in Q30 */, ratio_L_fx ), 8346665 /* 0.995f in Q23 */ ); // (Q30, Q24) -> Q23
    1629             :         }
    1630             : 
    1631           0 :         angle = extract_l( L_shl( Mpy_32_16_1( ratio_L_fx, EVS_PI_FX ), Q13 - Q21 - Q1 ) );                      // (Q23, Q13) -> Q21 >> Q1 -> Q22 -> Q13
    1632           0 :         ratio_L_fx = L_shl( L_shr( L_sub( ONE_IN_Q14, L_deposit_l( getCosWord16( angle ) ) ), Q1 ), Q24 - Q14 ); // Q14 << Q10 -> Q24
    1633             : 
    1634           0 :         dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx_Q24[0] ) ); // Q24
    1635             : 
    1636           0 :         desired_idx = 0;
    1637           0 :         move16();
    1638           0 :         FOR( i = 1; i < TDM_NQ; i++ )
    1639             :         {
    1640           0 :             IF( LE_32( L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx_Q24[i] ) ), dist_fx ) )
    1641             :             {
    1642           0 :                 dist_fx = L_abs( L_sub( ratio_L_fx, tdm_ratio_tabl_fx_Q24[i] ) ); // Q24
    1643           0 :                 desired_idx = i;
    1644           0 :                 move16();
    1645             :             }
    1646             :         }
    1647             : 
    1648           0 :         idx = stereo_smooth_LR_transition_fx( &hStereoTD->tdm_prev_stable_idx_SM, &hStereoTD->tdm_noop_mov_flag, hStereoTD->tdm_last_ratio_idx_SM, &hStereoTD->tdm_prev_desired_idx_SM, &hStereoTD->tdm_noop_cnt, tdm_SM_flag_loc, desired_idx ); /* Q0 */
    1649             : 
    1650           0 :         idx = extract_l( L_add( Mpy_32_32( 1717986918 /* 0.8f in Q31 */, idx ), Mpy_32_32( 429496729 /* 0.2f in Q31 */, hStereoTD->tdm_last_ratio_idx_SM ) ) ); // (Q31, Q0) -> Q0
    1651             : 
    1652           0 :         ratio_L_fx = tdm_ratio_tabl_fx_Q24[idx];
    1653           0 :         move32();
    1654             :     }
    1655             :     ELSE
    1656             :     {
    1657           0 :         ratio_L_fx = L_shl( hStereoTD->tdm_last_ratio_SM_fx, Q24 - Q31 ); // Q31 -> Q24
    1658           0 :         idx = hStereoTD->tdm_last_ratio_idx_SM;
    1659           0 :         move16();
    1660             :     }
    1661             : 
    1662           0 :     test();
    1663           0 :     test();
    1664           0 :     test();
    1665           0 :     IF( ( EQ_16( hStereoTD->tdm_noop_mov_flag, 1 ) && GE_16( hStereoTD->tdm_noop_cnt, 31 ) ) || ( ( EQ_16( hStereoTD->tdm_last_SM_flag_noop, tdm_SM_flag_loc ) ) && ( EQ_16( idx, hStereoTD->tdm_prev_stable_idx_SM ) ) ) )
    1666             :     {
    1667           0 :         hStereoTD->tdm_noop_cnt = 0;
    1668           0 :         move16();
    1669           0 :         hStereoTD->tdm_noop_mov_flag = 0;
    1670           0 :         move16();
    1671             :     }
    1672             : 
    1673           0 :     test();
    1674           0 :     if ( hStereoTD->tdm_noop_mov_flag == 0 || tdm_SM_flag_loc == 0 )
    1675             :     {
    1676           0 :         hStereoTD->tdm_prev_stable_idx_SM = idx;
    1677           0 :         move16();
    1678             :     }
    1679             : 
    1680           0 :     hStereoTD->tdm_last_SM_flag_noop = tdm_SM_flag_loc;
    1681           0 :     move16();
    1682           0 :     *tdm_SM_flag = tdm_SM_flag_loc;
    1683           0 :     move16();
    1684             : 
    1685           0 :     return ( idx );
    1686             : }
    1687             : 
    1688             : 
    1689             : /*-------------------------------------------------------------------*
    1690             :  * tdm_lp_comparison()
    1691             :  *
    1692             :  * Perform the comparison of the 2 sets of LP coefficients
    1693             :  *-------------------------------------------------------------------*/
    1694             : /*! r: replication decision; 1 = Use old LP */
    1695        3827 : Word16 tdm_lp_comparison_fx(
    1696             :     STEREO_TD_ENC_DATA_HANDLE hStereoTD,  /* i/o: TD stereo encoder handle        */
    1697             :     STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure     */
    1698             :     Encoder_State *st,                    /* i/o: Encoder structure               */
    1699             :     Word32 *speech_buff,                  /* i  : Current speech frame          Q_speech  */
    1700             :     const Word16 *A_PCh_fx,               /* i  : primary channel LP coefficients Q12*/
    1701             :     const Word16 *A_SCh_fx,               /* i  : secondary channel LP coeff.     Q12*/
    1702             :     const Word16 m,                       /* i  : filter length                   Q0*/
    1703             :     const Word16 *isp_PCh_fx,             /* i  : primary channel LSPs           Q15 */
    1704             :     const Word16 *isp_SCh_fx,             /* i  : secondary channel LSPs         Q15 */
    1705             :     const Word16 L_frame,                 /* i  : frame length                    Q0*/
    1706             :     const Word32 element_brate_wo_meta,   /* i  : element bitrate without metadata Q0*/
    1707             :     Word16 Q_speech )
    1708             : {
    1709             :     Word32 ener_sig_fx, pred_gain_reuse_PCh_fx, log10_fx, predgain_SCh_fx;
    1710             :     Word16 LP_mode;
    1711             :     Word32 dist_fx, ftmp_fx;
    1712             :     Word16 i;
    1713             :     Word32 res_fx[L_FRAME16k];
    1714             : 
    1715             :     Word16 Q_A_SCh;
    1716        3827 :     Word32 *speech_fx = &speech_buff[M];
    1717        3827 :     Q_A_SCh = sub( 14, norm_s( A_SCh_fx[0] ) );
    1718        3827 :     residu_ivas_fx( A_SCh_fx, Q_A_SCh, m, speech_fx, res_fx, L_frame );
    1719             : 
    1720             :     /* Find prediction gain for current LP filter */
    1721             :     // residu( A_SCh, m, speech, res, L_frame );
    1722             : 
    1723        3827 :     Word16 gb = find_guarded_bits_fx( L_frame );
    1724        3827 :     scale_sig32( speech_buff, L_FRAME + M, Q4 ); /* Q_speech + 4 */
    1725        3827 :     Word16 exp = sub( Q27, Q_speech );
    1726        3827 :     Word32 sum2_value = sum2_32_exp_fx( speech_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb
    1727        3827 :     IF( LT_16( exp, -5 ) )                                              /*maximum q to prevent 0.01 from saturating is 37, since we are adding it headroom of 1 is required*/
    1728             :     {
    1729           0 :         sum2_value = L_shl( sum2_value, add( 5, exp ) ); // sum2_value>>(-5-exp)=>sum2_value<<(5+exp)
    1730           0 :         exp = -5;
    1731           0 :         move16();
    1732             :     }
    1733        3827 :     sum2_value = BASOP_Util_Add_Mant32Exp( sum2_value, exp, 328, Q16, &exp );                             /* Q31-exp */
    1734        3827 :     Word32 temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); /* Q25 */
    1735        3827 :     ener_sig_fx = Mpy_32_32( temp32_log, 646456623 );                                                     // Q25
    1736             :     // ener_sig = log10f( sum2_f( speech, L_frame ) + 0.01f );
    1737        3827 :     exp = sub( Q31, Q_speech );
    1738        3827 :     sum2_value = sum2_32_exp_fx( res_fx, L_frame, &exp, gb );                                      // 2*Q_speech -31-gb
    1739        3827 :     sum2_value = BASOP_Util_Add_Mant32Exp( sum2_value, exp, 328, Q16, &exp );                      /* Q31-exp */
    1740        3827 :     temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); /* Q25 */
    1741        3827 :     log10_fx = Mpy_32_32( temp32_log, 646456623 );                                                 // Q25
    1742        3827 :     predgain_SCh_fx = Mpy_32_32( L_sub( ener_sig_fx, log10_fx ), 1342177280 );                     // Q27+Q25-31 = Q21
    1743             :     // pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
    1744             :     // predgain_SCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
    1745             : 
    1746             :     /* Find prediction gain when resuing the Primary Channel LP filter */
    1747             :     // residu( A_PCh, m, speech, res, L_frame );
    1748        3827 :     scale_sig32( speech_buff, L_FRAME + M, -4 ); /* Q_speech */
    1749        3827 :     residu_ivas_fx( A_PCh_fx, sub( 14, norm_s( A_PCh_fx[0] ) ), m, speech_fx, res_fx, L_frame );
    1750        3827 :     exp = sub( Q31, Q_speech );
    1751        3827 :     sum2_value = sum2_32_exp_fx( res_fx, L_frame, &exp, gb ); // 2*Q_speech -31-gb
    1752        3827 :     sum2_value = BASOP_Util_Add_Mant32Exp( sum2_value, exp, 328, Q16, &exp );
    1753        3827 :     temp32_log = L_add( BASOP_Util_Log2( sum2_value ), L_shl( sub( Q31, sub( 31, exp ) ), Q25 ) ); /* Q25 */
    1754        3827 :     log10_fx = Mpy_32_32( temp32_log, 646456623 );                                                 // Q25
    1755             : 
    1756        3827 :     pred_gain_reuse_PCh_fx = Mpy_32_32( L_sub( ener_sig_fx, log10_fx ), 1342177280 ); // Q27+Q25-31 = Q21
    1757             :     // pred_gain_reuse_PCh = 10.0f * ( ener_sig - log10f( sum2_f( res, L_frame ) + 0.01f ) );
    1758             : 
    1759             :     /* Find Euclidian distance between the 2 filters */
    1760        3827 :     dist_fx = 0;
    1761        3827 :     move16();
    1762        3827 :     gb = 4;
    1763        3827 :     move16();
    1764       65059 :     FOR( i = 0; i < m; i++ )
    1765             :     {
    1766             :         // ftmp = isp_SCh[i] - isp_PCh[i];
    1767       61232 :         ftmp_fx = L_deposit_h( sub( isp_SCh_fx[i], isp_PCh_fx[i] ) ); /* Q31 */
    1768             :         // dist += ftmp * ftmp;
    1769       61232 :         dist_fx = L_add( dist_fx, L_shr( Mpy_32_32( ftmp_fx, ftmp_fx ), gb ) ); // Q31-gb
    1770             :     }
    1771             :     //   ener_sig *= 10.0f;
    1772        3827 :     ener_sig_fx = Mpy_32_32( ener_sig_fx, 1342177280 ); // Q27+Q25-31 = Q21
    1773             : 
    1774             :     /* Verification of the filters similartiies and prediction gain obtained for each channel */
    1775             :     /* Threshold are more relax if alpha is close to 0.5  (Valid if ICA is used )             */
    1776        3827 :     test();
    1777        3827 :     test();
    1778        3827 :     test();
    1779        3827 :     test();
    1780        3827 :     test();
    1781        3827 :     test();
    1782        3827 :     test();
    1783        3827 :     test();
    1784        3827 :     test();
    1785        3827 :     IF( ( ( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb ) ) )                                                   /* Prediction gain are close & Euclidian dist is small */
    1786             :           || ( LT_32( predgain_SCh_fx, PG2ND_FX ) && LT_32( dist_fx, L_shr( EUCLDST2_FX, gb ) ) ) )                                                                                     /* Prediction gain if the secondary channel is low  & Euclidian dist is not too large */
    1787             :         || ( GE_16( hStereoTD->tdm_last_ratio_idx, ( LRTD_STEREO_MID_IS_PRIM - 2 ) ) && LE_16( hStereoTD->tdm_last_ratio_idx, ( LRTD_STEREO_MID_IS_PRIM + 2 ) ) &&                      /* ratio between 0.4 and 0.6 */
    1788             :              ( ( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG2_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST2_FX, gb ) ) ) || LT_32( predgain_SCh_fx, PG2ND2_FX ) ) ) /* Prediction gain are not far  & Euclidian dist is not too large or  Prediction gain if the secondary channel is low  */
    1789             :         || LE_32( ener_sig_fx, 62914560 )                                                                                                                                               // 30.0f  in Q21
    1790             :                                                                                                                                                                                         /* secondary channel has low energy */
    1791             :     )
    1792             :     {
    1793        1119 :         LP_mode = 1;
    1794        1119 :         move16();
    1795        1119 :         test();
    1796        1119 :         test();
    1797        1119 :         test();
    1798        1119 :         test();
    1799        1119 :         test();
    1800        1119 :         test();
    1801        1119 :         test();
    1802        1119 :         test();
    1803        1119 :         test();
    1804        1119 :         test();
    1805             : 
    1806        1119 :         IF( ( GE_32( element_brate_wo_meta, IVAS_48k ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_HR_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb ) ) ) ) ||
    1807             :             ( EQ_16( hStereoClassif->lrtd_mode, 1 ) && LT_32( element_brate_wo_meta, IVAS_16k4 ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_HR_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, add( gb, 1 ) ) ) ) ) ||
    1808             :             ( EQ_16( hStereoClassif->lrtd_mode, 1 ) && GE_32( element_brate_wo_meta, IVAS_16k4 ) && !( GE_32( pred_gain_reuse_PCh_fx, Mpy_32_32( RATIO_PG_LRTD_FX, predgain_SCh_fx ) ) && LT_32( dist_fx, L_shr( EUCLDST_FX, gb + 2 ) ) ) ) || st->tc_cnt > 0 )
    1809             :         {
    1810         988 :             LP_mode = 0;
    1811         988 :             move16();
    1812             :         }
    1813             :     }
    1814             :     ELSE
    1815             :     {
    1816             :         /* Prediction or and filters are too different -> quantize the difference*/
    1817        2708 :         LP_mode = 0;
    1818        2708 :         move16();
    1819             :     }
    1820             : 
    1821        3827 :     return LP_mode;
    1822             : }
    1823             : /*-------------------------------------------------------------------*
    1824             :  * tdm_ol_pitch_comparison()
    1825             :  *
    1826             :  * Perform the comparison of the 2 sets of OL pitch
    1827             :  *-------------------------------------------------------------------*/
    1828             : 
    1829             : /*! r: replication decision; 1 = Use old LP */
    1830        3827 : void tdm_ol_pitch_comparison_fx(
    1831             :     CPE_ENC_HANDLE hCPE,                      /* i  : CPE encoder structure                  */
    1832             :     Word16 pitch_fr[CPE_CHANNELS][NB_SUBFR],  /* i/o: fractional pitch values, Q6            */
    1833             :     Word16 voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains, Q15            */
    1834             : )
    1835             : {
    1836             :     Word16 tmp_diff;
    1837        3827 :     Word16 diff_thr = 6;
    1838             :     Encoder_State *st0, *st1;
    1839        3827 :     move16();
    1840             : 
    1841        3827 :     st0 = hCPE->hCoreCoder[0]; /* Encoder structure - primary channel     */
    1842        3827 :     st1 = hCPE->hCoreCoder[1]; /* Encoder structure - secondary channel   */
    1843             : 
    1844        3827 :     IF( GT_32( hCPE->element_brate, IVAS_13k2 ) )
    1845             :     {
    1846        3827 :         diff_thr = 3;
    1847        3827 :         move16();
    1848             :     }
    1849             : 
    1850        3827 :     test();
    1851        3827 :     IF( GE_32( hCPE->element_brate, IVAS_48k ) || EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) )
    1852             :     {
    1853        3698 :         diff_thr = 1;
    1854        3698 :         move16();
    1855             :     }
    1856             : 
    1857        3827 :     hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0;
    1858        3827 :     move16();
    1859             : 
    1860        3827 :     test();
    1861        3827 :     test();
    1862        3827 :     test();
    1863        3827 :     test();
    1864        3827 :     test();
    1865        3827 :     test();
    1866        3827 :     IF( ( ( st0->sp_aud_decision1 == 0 && st0->sp_aud_decision2 == 0 ) && /* Pitch is not recycled in case of music coding*/
    1867             :           ( LE_32( hCPE->element_brate, IVAS_16k4 ) || ( LE_32( hCPE->element_brate, IVAS_24k4 ) && EQ_16( st0->coder_type, VOICED ) && EQ_16( st1->coder_type, VOICED ) ) ) ) ||
    1868             :         LT_32( hCPE->element_brate, IVAS_13k2 ) )
    1869             :     {
    1870         719 :         IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) )
    1871             :         {
    1872             :             Word16 voicmin[4];
    1873             : 
    1874         719 :             minimum_fx( st0->voicing_fx, 3, voicmin );
    1875         719 :             minimum_fx( st1->voicing_fx, 3, voicmin + 1 );
    1876         719 :             minimum_fx( voicing_fr[0], 4, voicmin + 2 );
    1877         719 :             minimum_fx( voicing_fr[1], 4, voicmin + 3 );
    1878             : 
    1879         719 :             tmp_diff = 10;
    1880         719 :             move16();
    1881             : 
    1882         719 :             test();
    1883         719 :             test();
    1884         719 :             test();
    1885         719 :             IF( GE_16( voicmin[0], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[1], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[2], 27853 /* 0.85f in Q15 */ ) && GE_16( voicmin[3], 27853 /* 0.85f in Q15 */ ) )
    1886             :             {
    1887          44 :                 tmp_diff = add( abs_s( sub( st0->pitch[0], st1->pitch[0] ) ), add( abs_s( sub( st0->pitch[1], st1->pitch[1] ) ), abs_s( sub( st0->pitch[2], st1->pitch[2] ) ) ) ); /* Q0 */
    1888             :             }
    1889             :         }
    1890             :         ELSE
    1891             :         {
    1892           0 :             tmp_diff = abs_s( sub( add( st0->pitch[0], add( st0->pitch[1], st0->pitch[2] ) ), add( st1->pitch[0], add( st1->pitch[1], st1->pitch[2] ) ) ) ); /* Q0 */
    1893             :         }
    1894             : 
    1895         719 :         IF( LE_16( tmp_diff, diff_thr ) )
    1896             :         {
    1897          35 :             hCPE->hStereoTD->tdm_Pitch_reuse_flag = 1;
    1898          35 :             move16();
    1899             : 
    1900             :             /* 1/4 pitch precision update*/
    1901          35 :             Copy( st0->pitch, st1->pitch, 3 );           /* Q0 */
    1902          35 :             Copy( st0->voicing_fx, st1->voicing_fx, 3 ); /* Q15 */
    1903             : 
    1904             :             /* Update some parameters accordingly */
    1905          35 :             st1->old_corr_fx = st0->old_corr_fx;   /* Q15 */
    1906          35 :             st1->old_thres_fx = st0->old_thres_fx; /* Q15 */
    1907          35 :             st1->delta_pit = st0->delta_pit;       /* Q0 */
    1908          35 :             move16();
    1909          35 :             move16();
    1910          35 :             move16();
    1911             : 
    1912             :             /* Updates for adaptive lag window memory */
    1913          35 :             st1->old_pitch_la = st0->old_pitch_la; /* Q0 */
    1914          35 :             move16();
    1915             :             /* 1/4 pitch precision update*/
    1916          35 :             Copy( pitch_fr[0], pitch_fr[1], NB_SUBFR );     /* Q6 */
    1917          35 :             Copy( voicing_fr[0], voicing_fr[1], NB_SUBFR ); /* Q15 */
    1918             :         }
    1919             :     }
    1920             : 
    1921        3827 :     return;
    1922             : }
    1923             : 
    1924             : /*-------------------------------------------------------------------*
    1925             :  * Function Get_corr_n_fx()
    1926             :  *
    1927             :  *
    1928             :  *-------------------------------------------------------------------*/
    1929             : 
    1930        3827 : static void Get_corr_n_fx(
    1931             :     const Word16 L[],             /* i  : Left signal                                            q_in*/
    1932             :     const Word16 R[],             /* i  : Right signal                                           q_in*/
    1933             :     Word32 *ic_Lm,                /* o  : Left signal                                            q_ic_Lm*/
    1934             :     Word16 *q_ic_Lm,              /* o  : Q factor of Left signal                                */
    1935             :     Word32 *ic_Rm,                /* o  : Right signal                                           q_ic_Rm*/
    1936             :     Word16 *q_ic_Rm,              /* o  : Q factor of Right signal                               */
    1937             :     const Word16 len,             /* i  : segment length                                         Q0*/
    1938             :     Word32 *es_em,                /* o  : return the difference between the side and mono energy */
    1939             :     const Word16 tdm_SM_calc_flag /* i  : Flag that indicates that it is for SM mode             Q0*/
    1940             : )
    1941             : {
    1942             :     Word32 corrL, corrR, ener;
    1943             :     Word16 mono_i;
    1944             :     Word16 i;
    1945             :     Word32 ener_side;
    1946             :     Word16 side_i;
    1947             :     Word16 exp_diff;
    1948             :     Word32 L_tmp;
    1949             :     Word16 guard_bits;
    1950             :     Word64 W_corrL, W_corrR, W_ener, W_ener_side;
    1951             : 
    1952        3827 :     W_corrL = 0;
    1953        3827 :     move64();
    1954        3827 :     W_corrR = 0;
    1955        3827 :     move64();
    1956        3827 :     W_ener = EPSILON_FX;
    1957        3827 :     move64();
    1958        3827 :     W_ener_side = EPSILON_FX;
    1959        3827 :     move64();
    1960        3827 :     guard_bits = sub( 32, find_guarded_bits_fx( len ) ); /* Q0 */
    1961             : 
    1962             :     /*----------------------------------------------------------------*
    1963             :      * Find the normalized correlation between: left/mono and right/mono based
    1964             :      *----------------------------------------------------------------*/
    1965             : 
    1966        3827 :     IF( tdm_SM_calc_flag )
    1967             :     {
    1968           0 :         FOR( i = 0; i < len; i++ )
    1969             :         {
    1970           0 :             mono_i = extract_h( L_msu( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
    1971           0 :             W_corrL = W_mac0_16_16( W_corrL, abs_s( L[i] ), abs_s( mono_i ) );           // (q_in + q_in )
    1972           0 :             W_corrR = W_mac0_16_16( W_corrR, abs_s( R[i] ), abs_s( mono_i ) );           // (q_in + q_in )
    1973           0 :             W_ener = W_mac0_16_16( W_ener, mono_i, mono_i );                             // (q_in + q_in )
    1974           0 :             side_i = extract_h( L_mac( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
    1975           0 :             W_ener_side = W_mac0_16_16( W_ener_side, side_i, side_i );                   // (q_in + q_in )
    1976             :         }
    1977             :         /* Scaling back to the original proposal */
    1978           0 :         corrL = W_extract_h( W_shl( W_corrL, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
    1979           0 :         corrR = W_extract_h( W_shl( W_corrR, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
    1980           0 :         ener = W_extract_h( W_shl( W_ener, guard_bits ) );
    1981           0 :         ener_side = W_extract_h( W_shl( W_ener_side, guard_bits ) );
    1982             :     }
    1983             :     ELSE
    1984             :     {
    1985     2507827 :         FOR( i = 0; i < len; i++ )
    1986             :         {
    1987     2504000 :             mono_i = extract_h( L_mac( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
    1988     2504000 :             W_corrL = W_mac0_16_16( W_corrL, L[i], mono_i );                             // (q_in + q_in )
    1989     2504000 :             W_corrR = W_mac0_16_16( W_corrR, R[i], mono_i );                             // (q_in + q_in )
    1990     2504000 :             W_ener = W_mac0_16_16( W_ener, mono_i, mono_i );                             // (q_in + q_in )
    1991     2504000 :             side_i = extract_h( L_msu( L_mult( L[i], ONE_IN_Q14 ), R[i], ONE_IN_Q14 ) ); // q_in
    1992     2504000 :             W_ener_side = W_mac0_16_16( W_ener_side, side_i, side_i );                   // (q_in + q_in )
    1993             :         }
    1994             :         /* Scaling back to the original proposal */
    1995        3827 :         corrL = W_extract_h( W_shl( W_corrL, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
    1996        3827 :         corrR = W_extract_h( W_shl( W_corrR, guard_bits ) ); /* 2*q_in + guard_bits - 32 */
    1997        3827 :         ener = W_extract_h( W_shl( W_ener, guard_bits ) );
    1998        3827 :         ener_side = W_extract_h( W_shl( W_ener_side, guard_bits ) );
    1999             :     }
    2000             : 
    2001        3827 :     IF( ener == 0 )
    2002             :     {
    2003           0 :         *ic_Lm = 0;
    2004           0 :         move32();
    2005           0 :         *q_ic_Lm = Q31;
    2006           0 :         move16();
    2007           0 :         *ic_Rm = 0;
    2008           0 :         move32();
    2009           0 :         *q_ic_Rm = Q31;
    2010           0 :         move16();
    2011           0 :         *es_em = 0;
    2012           0 :         move32();
    2013             :     }
    2014             :     ELSE
    2015             :     {
    2016        3827 :         *ic_Lm = BASOP_Util_Divide3232_Scale_newton( corrL, ener, &exp_diff ); // (Q31 - exp_diff)
    2017        3827 :         move32();
    2018        3827 :         IF( *ic_Lm == 0 )
    2019             :         {
    2020           0 :             *q_ic_Lm = Q31;
    2021           0 :             move16();
    2022             :         }
    2023             :         ELSE
    2024             :         {
    2025        3827 :             *q_ic_Lm = sub( Q31, exp_diff );
    2026        3827 :             move16();
    2027             :         }
    2028        3827 :         *ic_Rm = BASOP_Util_Divide3232_Scale_newton( corrR, ener, &exp_diff ); // (Q31 - exp_diff)
    2029        3827 :         move16();
    2030        3827 :         IF( *ic_Rm == 0 )
    2031             :         {
    2032           0 :             *q_ic_Rm = Q31;
    2033           0 :             move16();
    2034             :         }
    2035             :         ELSE
    2036             :         {
    2037        3827 :             *q_ic_Rm = sub( Q31, exp_diff );
    2038        3827 :             move16();
    2039             :         }
    2040             : 
    2041             :         /* *es_em = 10 * ( log10f( sqrtf( ener_side / len ) ) - log10f( sqrtf( ener / len ) ) );
    2042             :         is simplified to
    2043             :         *es_em = 10 * ( log10f( sqrtf( ener_side / ener ) ) ); */
    2044        3827 :         L_tmp = BASOP_Util_Divide3232_Scale_newton( ener_side, ener, &exp_diff );                           // (Q31 - exp_diff)
    2045        3827 :         L_tmp = Sqrt32( L_tmp, &exp_diff );                                                                 /* (Q31 - exp_diff) */
    2046        3827 :         L_tmp = BASOP_Util_Log2( L_tmp );                                                                   /* Q25 */
    2047        3827 :         *es_em = Mpy_32_32( Mpy_32_32( L_add( L_tmp, L_shl( exp_diff, Q25 ) ), LOG10_2_Q31 ), TEN_IN_Q27 ); // (Q25, Q27) -> Q21
    2048        3827 :         move32();
    2049             :     }
    2050             : 
    2051        3827 :     return;
    2052             : }
    2053             : 
    2054             : 
    2055             : /*-------------------------------------------------------------------*
    2056             :  * Function stereo_smooth_LR_transition_fx()
    2057             :  *
    2058             :  *-------------------------------------------------------------------*/
    2059             : 
    2060             : /*! r: smoothed position */
    2061         121 : static Word16 stereo_smooth_LR_transition_fx(
    2062             :     Word16 *tdm_prev_stable_idx,           /* i/o: Previous Transmitted ratio index                Q0*/
    2063             :     Word16 *tdm_ratio_transition_mov_flag, /* i/o: Flag that indicates that L-R energy is changing Q0*/
    2064             :     Word16 tdm_last_ratio_idx,             /* i  : last TDM ratio index                            Q0*/
    2065             :     Word16 *tdm_prev_desired_idx,          /* i/o: Previous Transmitted ratio index                Q0*/
    2066             :     Word16 *tdm_ratio_transition_cnt,      /* i/o: Counter                                         Q0*/
    2067             :     const Word16 tdm_SM_flag,              /* i  : channel combination scheme flag for current frame Q0*/
    2068             :     Word16 desired_idx                     /* i  : desired final position                          Q0*/
    2069             : )
    2070             : {
    2071             :     Word16 idx;
    2072             : 
    2073         121 :     IF( EQ_16( tdm_SM_flag, 1 ) )
    2074             :     {
    2075           0 :         desired_idx = 15;
    2076           0 :         move16();
    2077             :     }
    2078             : 
    2079         121 :     IF( NE_16( desired_idx, *tdm_prev_stable_idx ) )
    2080             :     {
    2081         121 :         *tdm_ratio_transition_mov_flag = 1;
    2082         121 :         move16();
    2083             :     }
    2084             : 
    2085         121 :     IF( EQ_16( *tdm_ratio_transition_mov_flag, 1 ) )
    2086             :     {
    2087         121 :         IF( NE_16( desired_idx, *tdm_prev_desired_idx ) )
    2088             :         {
    2089         121 :             *tdm_prev_stable_idx = tdm_last_ratio_idx;
    2090         121 :             move16();
    2091         121 :             *tdm_ratio_transition_cnt = 0;
    2092         121 :             move16();
    2093             :         }
    2094             : 
    2095         121 :         *tdm_ratio_transition_cnt = add( *tdm_ratio_transition_cnt, 4 );
    2096         121 :         move16();
    2097         121 :         IF( LT_16( desired_idx, sub( *tdm_prev_stable_idx, 2 ) ) )
    2098             :         {
    2099          52 :             idx = sub( *tdm_prev_stable_idx, *tdm_ratio_transition_cnt );
    2100          52 :             idx = s_max( desired_idx, idx );
    2101             :         }
    2102          69 :         ELSE IF( GT_16( desired_idx, add( *tdm_prev_stable_idx, 2 ) ) )
    2103             :         {
    2104          69 :             idx = add( *tdm_prev_stable_idx, *tdm_ratio_transition_cnt );
    2105          69 :             idx = s_min( desired_idx, idx );
    2106             :         }
    2107             :         ELSE
    2108             :         {
    2109           0 :             idx = desired_idx;
    2110           0 :             move16();
    2111             :         }
    2112             :     }
    2113             :     ELSE
    2114             :     {
    2115           0 :         idx = desired_idx;
    2116           0 :         move16();
    2117             :     }
    2118             : 
    2119         121 :     *tdm_prev_desired_idx = desired_idx;
    2120         121 :     move16();
    2121             : 
    2122         121 :     return idx;
    2123             : }

Generated by: LCOV version 1.14