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

Generated by: LCOV version 1.14