LCOV - code coverage report
Current view: top level - lib_enc - ivas_stereo_classifier_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 827 875 94.5 %
Date: 2025-05-03 01:55:50 Functions: 10 10 100.0 %

          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 <math.h>
      35             : #include "options.h"
      36             : #ifdef DEBUGGING
      37             : #include "debug.h"
      38             : #endif
      39             : #include "cnst.h"
      40             : #include "rom_com.h"
      41             : #include "prot_fx.h"
      42             : #include "ivas_rom_com.h"
      43             : #include "ivas_rom_enc.h"
      44             : #include "ivas_cnst.h"
      45             : #include "wmc_auto.h"
      46             : #include "ivas_prot_fx.h"
      47             : 
      48             : /*-------------------------------------------------------------------*
      49             :  * Local constants
      50             :  *-------------------------------------------------------------------*/
      51             : 
      52             : #define RC_FACT_UP                       0.3f
      53             : #define RC_FACT_UP_Q31                   644245094
      54             : #define RC_FACT_DOWN                     0.7f
      55             : #define RC_FACT_DOWN_Q31                 1503238554
      56             : #define UNCLR_SCORE_THR                  4.0f
      57             : #define UNCLR_SCORE_THR_Q28              ( 1073741824 )
      58             : #define XTALK_SCORE_THR_DFT              4.0f
      59             : #define XTALK_SCORE_THR_DFT_Q27          ( 1 << 29 )
      60             : #define XTALK_SCORE_THR_TD_UP            3.0f
      61             : #define XTALK_SCORE_THR_TD_UP_Q28        ( 805306368 )
      62             : #define ONE_BY_XTALK_SCORE_THR_TD_UP_Q31 ( 715827882 )
      63             : #define XTALK_SCORE_THR_TD_DN            4.0f
      64             : #define XTALK_SCORE_THR_TD_DN_Q28        ( 1073741824 )
      65             : #define ONE_BY_XTALK_SCORE_THR_TD_DN_Q31 ( 536870912 )
      66             : 
      67             : #define UNCLR_INTERCEPT_TD      0.780313f
      68             : #define UNCLR_INTERCEPT_TD_Q28  ( 209463676 )
      69             : #define UNCLR_INTERCEPT_DFT     1.226513f
      70             : #define UNCLR_INTERCEPT_DFT_Q30 1316958306
      71             : #define XTALK_INTERCEPT_TD      -1.770983f
      72             : #define XTALK_INTERCEPT_TD_Q28  ( -475394629 )
      73             : #define XTALK_INTERCEPT_DFT     -0.758556f
      74             : #define XTALK_INTERCEPT_DFT_Q31 -1628986606
      75             : #define XTALK_INTERCEPT_DFT_Q27 -101811663
      76             : 
      77             : #define EDGE_MAX_LEN  30 /* maximum length of buffer for edge detection */
      78             : #define REDGE_MAX_LEN 30 /* maximum length of buffer for rising edge detection */
      79             : 
      80             : #define CLASSIFIER_ITD_THRES 8 /* ITD threshold in samples that enables classifier to switch */
      81             : 
      82             : 
      83             : /*-------------------------------------------------------------------*
      84             :  * Local function prototypes
      85             :  *-------------------------------------------------------------------*/
      86             : static void rc_filter_fx( const Word32 x, Word32 *y, const Word16 order, const Word32 tau );
      87             : static void edge_detect_fx( const Word32 *inp, const Word16 len, const Word32 inp_min, const Word32 inp_max, Word16 *edge_str, Word16 *edge_type );
      88             : 
      89             : static Word32 redge_detect_fx( const Word32 *inp, const Word16 len, const Word32 inp_min, const Word32 inp_max, Word16 *edge_min_e );
      90             : 
      91             : /*-------------------------------------------------------------------*
      92             :  * Function select_stereo_mode_fx()
      93             :  *
      94             :  * Select stereo technology based on output of stereo classifiers
      95             :  *-------------------------------------------------------------------*/
      96             : 
      97             : /*! r: element mode */
      98      148636 : Word16 select_stereo_mode_fx(
      99             :     CPE_ENC_HANDLE hCPE,          /* i/o: CPE encoder structure       */
     100             :     const IVAS_FORMAT ivas_format /* i  : IVAS format                 */
     101             : )
     102             : {
     103             :     Word16 element_mode;
     104             :     STEREO_CLASSIF_HANDLE hStereoClassif;
     105             :     Word16 is_speech;
     106             :     Word16 stereo_switching_flag;
     107             : 
     108             :     /* initialization */
     109      148636 :     element_mode = hCPE->element_mode;
     110      148636 :     hStereoClassif = hCPE->hStereoClassif;
     111             : 
     112             :     /* set binary flag to prevent LRTD mode on music */
     113      148636 :     hStereoClassif->is_speech_fx = L_add( Mpy_32_32( hStereoClassif->is_speech_fx, 2083059139 ), Mpy_32_16_1( 64424509, hCPE->hCoreCoder[0]->hSpMusClas->past_dlp_fx[0] ) ); /* (((Q25*Q31) << 1) >> 32) -> Q25 + (((Q31*Q9) << 1) >> 16) -> Q25*/
     114      148636 :     move32();
     115      148636 :     is_speech = ( LT_32( hStereoClassif->is_speech_fx, ONE_IN_Q25 ) && hCPE->hCoreCoder[0]->hSpMusClas->wdlp_xtalk_fx < 0 );
     116      148636 :     move16();
     117             : 
     118             :     /* set binary flag indicating LRTD mode based on unclr/xtalk classifiers' decisions */
     119      148636 :     hStereoClassif->prev_lrtd_mode = hStereoClassif->lrtd_mode;
     120      148636 :     move16();
     121      148636 :     hStereoClassif->unclr_decision = ( hStereoClassif->unclr_decision && hCPE->hCoreCoder[0]->flag_noisy_speech_snr == 0 && GT_32( hCPE->element_brate, IVAS_16k4 ) );
     122      148636 :     move16();
     123      148636 :     hStereoClassif->lrtd_mode = ( ( hStereoClassif->unclr_decision | hStereoClassif->xtalk_decision ) && is_speech );
     124      148636 :     move16();
     125             : 
     126      148636 :     stereo_switching_flag = 1;
     127      148636 :     move16();
     128             : 
     129      148636 :     test();
     130      148636 :     test();
     131      148636 :     test();
     132             : #ifdef DEBUGGING
     133             :     IF( GE_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) || ( ( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && LT_32( hCPE->element_brate, MASA_STEREO_MIN_BITRATE ) ) ) || ( hCPE->stereo_mode_cmdl == IVAS_CPE_DFT || hCPE->stereo_mode_cmdl == IVAS_CPE_TD ) )
     134             : #else
     135      160571 :     if ( GE_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) || ( ( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) &&
     136       11935 :                                                                     LT_32( hCPE->element_brate, MASA_STEREO_MIN_BITRATE ) ) ) )
     137             : #endif
     138             :     {
     139       91141 :         stereo_switching_flag = 0;
     140       91141 :         move16();
     141             :     }
     142      148636 :     test();
     143      148636 :     IF( GE_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) )
     144             :     {
     145       85265 :         hStereoClassif->prev_lrtd_mode = 0;
     146       85265 :         move16();
     147       85265 :         hStereoClassif->lrtd_mode = 0;
     148       85265 :         move16();
     149       85265 :         element_mode = IVAS_CPE_MDCT;
     150       85265 :         move16();
     151             :     }
     152       63371 :     ELSE IF( LT_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) && EQ_16( hCPE->last_element_mode, IVAS_CPE_MDCT ) )
     153             :     {
     154         732 :         hStereoClassif->lrtd_mode = 0;
     155         732 :         move16();
     156         732 :         element_mode = IVAS_CPE_DFT;
     157         732 :         move16();
     158         732 :         test();
     159         732 :         test();
     160         732 :         test();
     161         732 :         test();
     162         732 :         test();
     163         732 :         test();
     164         732 :         IF( EQ_16( stereo_switching_flag, 1 ) && GT_32( hCPE->element_brate, IVAS_13k2 ) && LT_16( hCPE->hCoreCoder[0]->hSpMusClas->past_dlp_fx[0], ONE_IN_Q9 ) && LT_32( hCPE->hCoreCoder[0]->hSpMusClas->wdlp_xtalk_fx, -335544 /* -0.01 in Q25 */ ) && EQ_16( hCPE->hCoreCoder[0]->vad_flag, 1 ) && ( hCPE->hStereoMdct->sw_uncorr || hStereoClassif->xtalk_decision ) )
     165             :         {
     166           8 :             hStereoClassif->lrtd_mode = 1;
     167           8 :             move16();
     168           8 :             element_mode = IVAS_CPE_TD;
     169           8 :             move16();
     170             :         }
     171             :     }
     172             : 
     173             :     /* set the element mode */
     174      148636 :     test();
     175      148636 :     IF( EQ_16( hStereoClassif->lrtd_mode, 1 ) && EQ_16( stereo_switching_flag, 1 ) )
     176             :     {
     177        4038 :         element_mode = IVAS_CPE_TD;
     178        4038 :         move16();
     179             :     }
     180      144598 :     ELSE IF( LT_16( element_mode, IVAS_CPE_MDCT ) )
     181             :     {
     182       59333 :         IF( EQ_16( stereo_switching_flag, 0 ) )
     183             :         {
     184        5876 :             test();
     185        5876 :             test();
     186        5876 :             if ( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && LT_32( hCPE->element_brate, MASA_STEREO_MIN_BITRATE ) )
     187             :             {
     188        5876 :                 element_mode = IVAS_CPE_DFT;
     189        5876 :                 move16();
     190             :             }
     191             : #ifdef DEBUGGING
     192             :             if ( hCPE->stereo_mode_cmdl > 1 )
     193             :             {
     194             :                 element_mode = hCPE->stereo_mode_cmdl;
     195             :             }
     196             : #endif
     197             :         }
     198       53457 :         ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) )
     199             :         {
     200          21 :             test();
     201          21 :             IF( hCPE->hStereoTD->prev_fr_LRTD_TD_dec > 0 && is_speech )
     202             :             {
     203             :                 /* if unclr_decision goes from 1->0 on active content, continue in LRTD mode */
     204          19 :                 hStereoClassif->lrtd_mode = 1;
     205          19 :                 move16();
     206             :             }
     207           2 :             ELSE IF( EQ_16( stereo_switching_flag, 1 ) )
     208             :             {
     209           2 :                 element_mode = IVAS_CPE_DFT;
     210           2 :                 move16();
     211             :             }
     212             :         }
     213       53436 :         ELSE IF( EQ_16( stereo_switching_flag, 1 ) )
     214             :         {
     215       53436 :             element_mode = IVAS_CPE_DFT;
     216       53436 :             move16();
     217             :         }
     218             :     }
     219             : 
     220             :     /* switch from LRTD to DFT when xtalk_decision goes from 0->1 (note: this special case is not handled in the xtalk classifier) */
     221      148636 :     test();
     222      148636 :     test();
     223      148636 :     IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) && EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( hStereoClassif->xtalk_decision, 1 ) )
     224             :     {
     225        2094 :         test();
     226        2094 :         test();
     227        2094 :         test();
     228        2094 :         test();
     229        2094 :         test();
     230        2094 :         IF( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 && GT_16( hCPE->hStereoTD->tdm_FD2LRTD_SW_cnt, 15 ) && GT_16( hCPE->hStereoTD->tdm_last_LRTD_frame_cnt, 3 ) && LT_16( hCPE->hCoreCoder[0]->clas, VOICED_CLAS ) && ( GE_32( hCPE->element_brate, IVAS_16k4 ) || LT_32( hStereoClassif->xtalk_wscore_fx, 21474836 /*0.01f in Q31*/ ) ) )
     231             :         {
     232          19 :             if ( EQ_16( stereo_switching_flag, 1 ) )
     233             :             {
     234          19 :                 element_mode = IVAS_CPE_DFT;
     235          19 :                 move16();
     236             :             }
     237          19 :             hStereoClassif->xtalk_decision = 0;
     238          19 :             move16();
     239          19 :             hStereoClassif->lrtd_mode = 0;
     240          19 :             move16();
     241             :         }
     242             :     }
     243             : 
     244             : #ifdef DEBUG_FORCE_DIR
     245             :     if ( hCPE->hCoreCoder[0]->force_dir[0] != '\0' )
     246             :     {
     247             :         dbgread( &element_mode, sizeof( int16_t ), 1, fname( hCPE->hCoreCoder[0]->force_dir, "force_element_mode.enf", -1, -1, -1 ) );
     248             :     }
     249             :     else
     250             :     {
     251             :         dbgwrite( &element_mode, sizeof( int16_t ), 1, 1, "res/force_element_mode.enf" );
     252             :     }
     253             : #endif
     254             : 
     255      148636 :     IF( NE_16( hCPE->last_element_mode, element_mode ) )
     256             :     {
     257        1742 :         test();
     258        1742 :         IF( NE_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) )
     259         732 :         {
     260         732 :             Word16 lrtd_mode = hStereoClassif->lrtd_mode;
     261         732 :             move16();
     262             : 
     263             :             /* reset stereo classifier when switching from MDCT stereo to Unified stereo */
     264         732 :             stereo_classifier_init_fx( hCPE->hStereoClassif );
     265         732 :             hStereoClassif->lrtd_mode = lrtd_mode;
     266         732 :             move16();
     267             :         }
     268             :         ELSE
     269             :         {
     270             :             /* reset UNCLR classifier parameters */
     271        1010 :             set32_fx( hStereoClassif->unclr_fv_fx, -MAX_16, SSC_MAX_NFEA );
     272        1010 :             hStereoClassif->unclr_corrLagMax_prev = 0;
     273        1010 :             move16();
     274             : 
     275             :             /* reset xtalk classifier parameters */
     276        1010 :             set32_fx( hStereoClassif->xtalk_fv_fx, -MAX_16, SSC_MAX_NFEA );
     277             :         }
     278             :     }
     279      148636 :     test();
     280      148636 :     IF( EQ_16( element_mode, IVAS_CPE_TD ) && hCPE->hCoreCoder[0]->Opt_DTX_ON )
     281             :     {
     282        1880 :         hCPE->hStereoCng->td_active = 1;
     283        1880 :         move16();
     284        1880 :         hCPE->hStereoCng->first_SID_after_TD = 1;
     285        1880 :         move16();
     286             :     }
     287             : 
     288      148636 :     return ( element_mode );
     289             : }
     290             : 
     291             : /*-------------------------------------------------------------------*
     292             :  * Function stereo_classifier_init_fx()
     293             :  *
     294             :  * Initialize stereo classifier handle
     295             :  *-------------------------------------------------------------------*/
     296             : 
     297        3344 : void stereo_classifier_init_fx(
     298             :     STEREO_CLASSIF_HANDLE hStereoClassif /* i/o: stereo classifier structure */
     299             : )
     300             : {
     301             :     /* initialization of features for xtalk classifier and UNCLR classifier */
     302        3344 :     hStereoClassif->clas_ch1 = 0;
     303        3344 :     move16();
     304        3344 :     set16_fx( hStereoClassif->pitch_ch1, 0, 3 );
     305        3344 :     set16_fx( hStereoClassif->voicing_ch1_fx, 0, 3 );
     306        3344 :     hStereoClassif->cor_map_sum_ch1_fx = 0;
     307        3344 :     move32();
     308        3344 :     set16_fx( hStereoClassif->lsf_ch1_fx, 0, M );
     309        3344 :     hStereoClassif->lepsP_ch1_fx = 0;
     310        3344 :     move32();
     311        3344 :     hStereoClassif->dE1_ch1_fx = 0;
     312        3344 :     move32();
     313        3344 :     hStereoClassif->dE1_ch1_e = 0;
     314        3344 :     move16();
     315        3344 :     hStereoClassif->dE1_ch2_fx = 0;
     316        3344 :     move32();
     317        3344 :     hStereoClassif->dE1_ch2_e = 0;
     318        3344 :     move16();
     319        3344 :     hStereoClassif->nchar_ch1_fx = 0;
     320        3344 :     move32();
     321        3344 :     hStereoClassif->nchar_ch1_e = 0;
     322        3344 :     move16();
     323        3344 :     hStereoClassif->nchar_ch2_fx = 0;
     324        3344 :     move32();
     325        3344 :     hStereoClassif->nchar_ch2_e = 0;
     326        3344 :     move16();
     327        3344 :     hStereoClassif->non_sta_ch1_fx = 0;
     328        3344 :     move32();
     329        3344 :     hStereoClassif->non_sta_ch1_e = 0;
     330        3344 :     move16();
     331        3344 :     hStereoClassif->sp_div_ch1_fx = 0;
     332        3344 :     move32();
     333        3344 :     hStereoClassif->ps_diff_ch1_fx = 0;
     334        3344 :     move32();
     335        3344 :     hStereoClassif->ps_diff_ch1_e = 0;
     336        3344 :     move16();
     337        3344 :     hStereoClassif->ps_diff_ch2_fx = 0;
     338        3344 :     move32();
     339        3344 :     hStereoClassif->ps_diff_ch2_e = 0;
     340        3344 :     move16();
     341        3344 :     hStereoClassif->ps_sta_ch1_fx = 0;
     342        3344 :     move32();
     343        3344 :     hStereoClassif->ps_sta_ch1_e = 0;
     344        3344 :     move16();
     345        3344 :     hStereoClassif->ps_sta_ch2_fx = 0;
     346        3344 :     move32();
     347        3344 :     hStereoClassif->ps_sta_ch2_e = 0;
     348        3344 :     move16();
     349        3344 :     hStereoClassif->prev_g_IPD_fx = ONE_IN_Q28; // 0.5f in Q29
     350        3344 :     move32();
     351        3344 :     hStereoClassif->prev_IPD_fx = 0; // Q29
     352        3344 :     move32();
     353        3344 :     hStereoClassif->prev_ratio_m1_m2_fx = 0; // Q31
     354        3344 :     move32();
     355        3344 :     set_zero_fx( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN );
     356        3344 :     hStereoClassif->ratio_L_fx = ONE_IN_Q30; // 0.5f in Q31
     357        3344 :     move32();
     358        3344 :     hStereoClassif->ratio_L_e = 0; // Q31
     359        3344 :     move16();
     360        3344 :     hStereoClassif->vad_flag_glob = 0;
     361        3344 :     move16();
     362        3344 :     hStereoClassif->vad_relE = 0;
     363        3344 :     move16();
     364        3344 :     hStereoClassif->is_speech_fx = 0; // Q25
     365        3344 :     move32();
     366             : 
     367        3344 :     set16_fx( hStereoClassif->aEn_raw, 0, CPE_CHANNELS );
     368             : 
     369        3344 :     hStereoClassif->Etot_dn_fx = 0;
     370        3344 :     move32();
     371        3344 :     hStereoClassif->Etot_dn_e = 0;
     372        3344 :     move16();
     373        3344 :     hStereoClassif->Etot_up_fx = 0;
     374        3344 :     move32();
     375        3344 :     hStereoClassif->Etot_up_e = 0;
     376        3344 :     move16();
     377             : 
     378        3344 :     set_zero_fx( hStereoClassif->relE_buf_fx, UNCLR_L_RELE );
     379        3344 :     set_zero_fx( hStereoClassif->Etot_buf_fx, UNCLR_L_ETOT );
     380        3344 :     hStereoClassif->e_Etot_buf_fx = 0;
     381        3344 :     move16();
     382        3344 :     set_zero_fx( hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER );
     383             : 
     384        3344 :     hStereoClassif->unclr_sw_enable_cnt[0] = 0;
     385        3344 :     move16();
     386        3344 :     hStereoClassif->unclr_sw_enable_cnt[1] = 0;
     387        3344 :     move16();
     388             : 
     389        3344 :     hStereoClassif->unclr_decision = 0;
     390        3344 :     move16();
     391        3344 :     hStereoClassif->unclr_wscore_fx = 0;
     392        3344 :     move32();
     393             : 
     394        3344 :     set32_fx( hStereoClassif->unclr_fv_fx, -ONE_IN_Q15, SSC_MAX_NFEA ); // Q15
     395        3344 :     hStereoClassif->unclr_corrLagMax_prev = 0;
     396        3344 :     move16();
     397        3344 :     hStereoClassif->ave_ener_L_fx = 0;
     398        3344 :     move32();
     399        3344 :     hStereoClassif->ave_ener_L_fx_e = 0;
     400        3344 :     move16();
     401        3344 :     hStereoClassif->ave_ener_R_fx = 0;
     402        3344 :     move32();
     403        3344 :     hStereoClassif->ave_ener_R_fx_e = 0;
     404        3344 :     move16();
     405        3344 :     hStereoClassif->relE_0_1_fx = 21474836; // 0.01f in Q31
     406        3344 :     move32();
     407        3344 :     hStereoClassif->relE_0_1_LT_fx = 21474836; // 0.01f in Q31
     408        3344 :     move32();
     409             : 
     410        3344 :     set32_fx( hStereoClassif->xtalk_fv_fx, -ONE_IN_Q15, SSC_MAX_NFEA ); // Q15
     411        3344 :     hStereoClassif->xtalk_wscore_fx = 0;                                // Q31
     412        3344 :     move32();
     413        3344 :     hStereoClassif->xtalk_decision = 0;
     414        3344 :     move16();
     415        3344 :     hStereoClassif->xtalk_score_wrelE_fx = 0; // Q31
     416        3344 :     move32();
     417             : 
     418        3344 :     hStereoClassif->lrtd_mode = 0;
     419        3344 :     move16();
     420        3344 :     hStereoClassif->prev_lrtd_mode = 0;
     421        3344 :     move16();
     422             : 
     423        3344 :     hStereoClassif->silence_flag = 0;
     424        3344 :     move16();
     425             : 
     426        3344 :     return;
     427             : }
     428             : 
     429             : 
     430             : /*-----------------------------------------------------------------*
     431             :  * stereo_classifier_features()
     432             :  *
     433             :  * Collect features for stereo classifiers
     434             :  *-----------------------------------------------------------------*/
     435             : /* Information on ouputs:
     436             : hStereoClassif->Etot_buf_fx has expoenent hStereoClassif->e_Etot_buf_fx
     437             : hStereoClassif->lsf_ch1_fx  has Q1*1.28
     438             : hStereoClassif->xtalk_fv_fx has exponent 16
     439             : hStereoClassif->voicing_ch1_fx has Q-factor Q15
     440             : hStereoClassif->lepsP_ch1_fx has exponent 16
     441             : hStereoClassif->Etot_up_fx has exponent hStereoClassif->Etot_up_e
     442             : hStereoClassif->Etot_dn_fx has exponent hStereoClassif->Etot_dn_e
     443             : hStereoClassif->cor_map_sum_ch1_fx has exponent hStereoClassif->cor_map_sum_ch1_e
     444             : hStereoClassif->non_sta_ch1_fx has exponent hStereoClassif->non_sta_ch1_e
     445             : hStereoClassif->sp_div_ch1_fx has exponent sp_div_e
     446             : hStereoClassif->nchar_ch1_fx has exponent hStereoClassif->nchar_ch1_e
     447             : hStereoClassif->nchar_ch2_fx has exponent hStereoClassif->nchar_ch2_e
     448             : hStereoClassif->dE1_ch1_fx has exponent hStereoClassif->dE1_ch1_e
     449             : hStereoClassif->dE1_ch2_fx has exponent hStereoClassif->dE1_ch2_e
     450             : hStereoClassif->ps_diff_ch1_fx has exponent hStereoClassif->ps_diff_ch1_e
     451             : hStereoClassif->ps_sta_ch1_fx has exponent hStereoClassif->ps_sta_ch1_e
     452             : hStereoClassif->ps_diff_ch2_fx has exponent hStereoClassif->ps_diff_ch2_e
     453             : hStereoClassif->ps_sta_ch2_fx has exponent hStereoClassif->ps_sta_ch2_e
     454             : */
     455      760867 : void stereo_classifier_features_ivas_fx(
     456             :     STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure                     */
     457             :     const Word16 idchan,                  /* i  : channel ID                                      */
     458             :     const Word16 element_mode,            /* i  : element mode                                    */
     459             :     const Word16 vad_flag,                /* i  : VAD flag                                        */
     460             :     Word16 lsf_new_fx[],                  /* i  : LSFs at the end of the frame            Q1*1.28 */
     461             :     Word32 epsP_fx[],                     /* i  : LP analysis residual energies for each iteration*/
     462             :     Word16 pitch[],                       /* i  : open-loop pitch values for quantiz.         Q0  */
     463             :     Word16 voicing_fx[],                  /* i  : OL maximum normalized correlation           Q15 */
     464             :     Word32 cor_map_sum_fx,                /* i  : speech/music clasif. parameter      Q(31-cor_map_sum_e)            */
     465             :     Word32 non_staX_fx,                   /* i  : unbound non-stationarity for sp/mu clas.  Q(31-non_staX_e)      */
     466             :     Word16 sp_div_fx,                     /* i  : spectral diversity feature   Q(15-sp_div_e)                   */
     467             :     const Word16 clas,                    /* i  : signal class                                    */
     468             :     Word16 epsP_e,                        /*exponent for epsP_fx                                  */
     469             :     Word16 cor_map_sum_e,                 /*exponent for cor_map_sum_fx                           */
     470             :     Word16 non_staX_e,                    /*exponent for non_staX_fx                              */
     471             :     Word16 sp_div_e                       /*exponent for sp_div_fx                                */
     472             : )
     473             : {
     474             :     Word16 i, clas_ch2;
     475             :     Word16 ener_e;
     476             : 
     477             :     Word32 lepsP_ch2_fx, ener_l_fx, ener_r_fx;
     478             :     Word32 L_tmp;
     479             :     Word16 exp;
     480             :     /* combine VAD flags from both channels */
     481      760867 :     IF( idchan == 0 )
     482             :     {
     483      410255 :         hStereoClassif->vad_flag_glob = vad_flag;
     484             :     }
     485             :     ELSE
     486             :     {
     487      350612 :         hStereoClassif->vad_flag_glob = s_or( hStereoClassif->vad_flag_glob, vad_flag );
     488             :     }
     489      760867 :     move16();
     490             : 
     491      760867 :     test();
     492      760867 :     test();
     493      760867 :     test();
     494      760867 :     IF( ( EQ_16( element_mode, IVAS_CPE_DFT ) && idchan == 0 ) || ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( idchan, 1 ) ) )
     495             :     {
     496             :         /* making negative exponent zero as we are using this exponent to scale 1 in next block*/
     497       63470 :         IF( hStereoClassif->ave_ener_L_fx_e < 0 )
     498             :         {
     499         467 :             hStereoClassif->ave_ener_L_fx = L_shl( hStereoClassif->ave_ener_L_fx, hStereoClassif->ave_ener_L_fx_e );
     500         467 :             hStereoClassif->ave_ener_L_fx_e = 0;
     501             :         }
     502       63470 :         IF( hStereoClassif->ave_ener_R_fx_e < 0 )
     503             :         {
     504         468 :             hStereoClassif->ave_ener_R_fx = L_shl( hStereoClassif->ave_ener_R_fx, hStereoClassif->ave_ener_R_fx_e );
     505         468 :             hStereoClassif->ave_ener_R_fx_e = 0;
     506             :         }
     507       63470 :         move32();
     508       63470 :         move16();
     509             :         /* update Etot_up and Etot_dn based on aEn */
     510       63470 :         exp = norm_l( hStereoClassif->ave_ener_L_fx );
     511       63470 :         if ( sub( hStereoClassif->ave_ener_L_fx_e, exp ) < 0 )
     512             :         {
     513         774 :             exp = hStereoClassif->ave_ener_L_fx_e;
     514         774 :             move16();
     515             :         }
     516       63470 :         hStereoClassif->ave_ener_L_fx = L_shl( hStereoClassif->ave_ener_L_fx, exp );
     517       63470 :         move32();
     518       63470 :         hStereoClassif->ave_ener_L_fx_e = sub( hStereoClassif->ave_ener_L_fx_e, exp );
     519       63470 :         move16();
     520       63470 :         exp = norm_l( hStereoClassif->ave_ener_R_fx );
     521       63470 :         if ( sub( hStereoClassif->ave_ener_R_fx_e, exp ) < 0 )
     522             :         {
     523         656 :             exp = hStereoClassif->ave_ener_R_fx_e;
     524         656 :             move16();
     525             :         }
     526       63470 :         hStereoClassif->ave_ener_R_fx = L_shl( hStereoClassif->ave_ener_R_fx, exp );
     527       63470 :         move32();
     528       63470 :         hStereoClassif->ave_ener_R_fx_e = sub( hStereoClassif->ave_ener_R_fx_e, exp );
     529       63470 :         move16();
     530       63470 :         ener_l_fx = Mpy_32_16_1( BASOP_Util_Log10( L_add( L_shr( hStereoClassif->ave_ener_L_fx, 1 ), L_shr( ONE_IN_Q30, hStereoClassif->ave_ener_L_fx_e ) ), hStereoClassif->ave_ener_L_fx_e + 1 ), 10 << 11 ); /*q21*/
     531       63470 :         ener_r_fx = Mpy_32_16_1( BASOP_Util_Log10( L_add( L_shr( hStereoClassif->ave_ener_R_fx, 1 ), L_shr( ONE_IN_Q30, hStereoClassif->ave_ener_R_fx_e ) ), hStereoClassif->ave_ener_R_fx_e + 1 ), 10 << 11 ); /*q21*/
     532       63470 :         ener_e = 10;
     533       63470 :         move16();
     534             : 
     535             :         /*scaling Etot_buf_fx,Etot_up_fx and Etot_dn_fx to exponent ener_e*/
     536       63470 :         exp = L_norm_arr( hStereoClassif->Etot_buf_fx, 3 );
     537       63470 :         exp = s_min( exp, L_norm_arr( &hStereoClassif->Etot_up_fx, 1 ) );
     538       63470 :         exp = s_min( exp, L_norm_arr( &hStereoClassif->Etot_dn_fx, 1 ) );
     539             : 
     540       63470 :         Copy32( &hStereoClassif->Etot_buf_fx[0], &hStereoClassif->Etot_buf_fx[1], UNCLR_L_ETOT - 1 );
     541       63470 :         IF( GE_16( sub( hStereoClassif->e_Etot_buf_fx, exp ), ener_e ) )
     542             :         {
     543           0 :             hStereoClassif->Etot_buf_fx[0] = L_shl( L_max( 0, L_max( ener_l_fx, ener_r_fx ) ), sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); /*scaling from q25 to 31-e_Etot_buf_fx*/
     544           0 :             move32();
     545             :         }
     546             :         ELSE
     547             :         {
     548             :             /*scaling Etot_buf_fx,Etot_up_fx and Etot_dn_fx to exponent ener_e*/
     549       63470 :             hStereoClassif->Etot_buf_fx[0] = L_max( 0, L_max( ener_l_fx, ener_r_fx ) );
     550       63470 :             hStereoClassif->Etot_buf_fx[1] = L_shr( hStereoClassif->Etot_buf_fx[1], sub( ener_e, hStereoClassif->e_Etot_buf_fx ) );
     551       63470 :             hStereoClassif->Etot_buf_fx[2] = L_shr( hStereoClassif->Etot_buf_fx[2], sub( ener_e, hStereoClassif->e_Etot_buf_fx ) );
     552       63470 :             hStereoClassif->Etot_up_fx = L_shr( hStereoClassif->Etot_up_fx, sub( ener_e, hStereoClassif->e_Etot_buf_fx ) );
     553       63470 :             hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, sub( ener_e, hStereoClassif->e_Etot_buf_fx ) );
     554       63470 :             hStereoClassif->e_Etot_buf_fx = ener_e;
     555       63470 :             move32();
     556       63470 :             move32();
     557       63470 :             move32();
     558       63470 :             move32();
     559       63470 :             move32();
     560       63470 :             move16();
     561             :         }
     562             : 
     563       63470 :         test();
     564       63470 :         test();
     565       63470 :         test();
     566       63470 :         test();
     567       63470 :         test();
     568       63470 :         test();
     569       63470 :         IF( EQ_16( hStereoClassif->aEn_raw[0], 6 ) || ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( hStereoClassif->aEn_raw[1], 6 ) ) )
     570             :         {
     571             :             /* active signal, update upper bound */
     572       40053 :             IF( LT_32( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_up_fx ) )
     573             :             {
     574             :                 /* energy decreases -> slower update */
     575       27567 :                 hStereoClassif->Etot_up_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_up_fx, /*0.99f Q15*/ 32440 ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 328 /*0.01f*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/
     576             :             }
     577             :             ELSE
     578             :             {
     579             :                 /* energy increases -> faster update */
     580       12486 :                 hStereoClassif->Etot_up_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_up_fx, 31130 /*0.95f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 1638 /*0.05f*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/
     581             :             }
     582       40053 :             move32();
     583             :         }
     584       23417 :         ELSE IF( ( EQ_16( element_mode, IVAS_CPE_DFT ) && hStereoClassif->aEn_raw[0] == 0 ) ||
     585             :                  ( EQ_16( element_mode, IVAS_CPE_TD ) && hStereoClassif->aEn_raw[0] == 0 && hStereoClassif->aEn_raw[1] == 0 ) )
     586             :         {
     587             :             /* inactive signal, update lower bound */
     588       16176 :             IF( LT_32( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_dn_fx ) )
     589             :             {
     590             :                 /* energy decreases -> faster update */
     591        6185 :                 hStereoClassif->Etot_dn_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_dn_fx, 29491 /*0.9f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 3277 /*0.1f q15*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/
     592             :             }
     593             :             ELSE
     594             :             {
     595             :                 /* energy increases -> slower update */
     596        9991 :                 hStereoClassif->Etot_dn_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_dn_fx, 31130 /*0.95f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 1638 /*0.05f q15*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/
     597             :             }
     598       16176 :             move32();
     599             : 
     600       16176 :             IF( LT_32( hStereoClassif->Etot_dn_fx, L_shl( 30, sub( 31, hStereoClassif->e_Etot_buf_fx ) ) ) )
     601             :             {
     602             :                 /* do not decrease below lower bound threshold */
     603        2606 :                 hStereoClassif->Etot_dn_fx = L_shl( 30, sub( 31, hStereoClassif->e_Etot_buf_fx ) );
     604        2606 :                 move32();
     605             :             }
     606             :         }
     607             : 
     608             :         /* upper bound is too low and close to lower bound -> update it */
     609       63470 :         IF( LT_32( L_shr( hStereoClassif->Etot_up_fx, 1 ), L_add( L_shr( hStereoClassif->Etot_dn_fx, 1 ), L_shl( 20, sub( 30, hStereoClassif->e_Etot_buf_fx ) ) ) ) ) /*right shifted by 1 to avoid avoid overflow in addition*/
     610             :         {
     611       14506 :             hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, 1 );
     612       14506 :             scale_sig32( hStereoClassif->Etot_buf_fx, 3, -1 ); // Q(31-(e_Etot_buf_fx+1))
     613       14506 :             hStereoClassif->e_Etot_buf_fx = add( hStereoClassif->e_Etot_buf_fx, 1 );
     614       14506 :             hStereoClassif->Etot_up_fx = L_add( hStereoClassif->Etot_dn_fx, L_shl( 20, sub( 31, hStereoClassif->e_Etot_buf_fx ) ) );
     615       14506 :             move32();
     616       14506 :             move32();
     617       14506 :             move16();
     618             :         }
     619             : 
     620             :         /* normalize Etot to (0,1) */
     621       63470 :         hStereoClassif->relE_0_1_fx = lin_interp32_fx( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_dn_fx, 0, hStereoClassif->Etot_up_fx, 1932735283 /* 0.9 in Q31 */, 1 );
     622       63470 :         move32();
     623             : 
     624             :         /* update relE_buf */
     625       63470 :         Copy32( &hStereoClassif->relE_buf_fx[0], &hStereoClassif->relE_buf_fx[1], UNCLR_L_RELE - 1 );
     626       63470 :         hStereoClassif->relE_buf_fx[0] = hStereoClassif->relE_0_1_fx;
     627       63470 :         move32();
     628             : 
     629       63470 :         IF( GE_32( hStereoClassif->relE_0_1_fx, hStereoClassif->relE_buf_fx[1] ) )
     630             :         {
     631       39513 :             hStereoClassif->relE_0_1_LT_fx = L_add( Mpy_32_16_1( hStereoClassif->relE_0_1_LT_fx, 29491 /* 0.9f in Q15 */ ), Mpy_32_16_1( hStereoClassif->relE_0_1_fx, 3277 /* 0.1f in Q15 */ ) );
     632             :         }
     633             :         ELSE
     634             :         {
     635       23957 :             hStereoClassif->relE_0_1_LT_fx = L_add( Mpy_32_16_1( hStereoClassif->relE_0_1_LT_fx, 31129 /* 0.95f in Q15 */ ), Mpy_32_16_1( hStereoClassif->relE_0_1_fx, 1638 /* 0.05f in Q15 */ ) );
     636             :         }
     637       63470 :         move32();
     638             : 
     639             :         /* estimate VAD flag based on relative energy */
     640             : 
     641       63470 :         IF( LT_32( hStereoClassif->relE_0_1_LT_fx, 214748365 /* 0.1f in Q31 */ ) )
     642             :         {
     643       14852 :             hStereoClassif->vad_relE = 0;
     644             :         }
     645             :         ELSE
     646             :         {
     647       48618 :             hStereoClassif->vad_relE = 1;
     648             :         }
     649       63470 :         move16();
     650             : 
     651             :         /* combine classical VAD flag with VAD flag based on relative energy */
     652       63470 :         hStereoClassif->vad_flag_glob = s_and( hStereoClassif->vad_flag_glob, hStereoClassif->vad_relE );
     653       63470 :         move16();
     654             :     }
     655             : 
     656      760867 :     IF( idchan == 0 )
     657             :     {
     658      410255 :         Copy( lsf_new_fx, hStereoClassif->lsf_ch1_fx, M );
     659      410255 :         hStereoClassif->lepsP_ch1_fx = L_shr( L_sub( BASOP_Util_Loge( L_add( epsP_fx[13], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ), BASOP_Util_Loge( L_add( epsP_fx[0], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ) ), 10 ); /*q15*/
     660      410255 :         move32();
     661             : 
     662      410255 :         hStereoClassif->xtalk_fv_fx[E_lsf_1] = Mpy_32_16_1( 419430400 /* 1/2.56f in Q30 */, lsf_new_fx[0] );   /*q15*/
     663      410255 :         hStereoClassif->xtalk_fv_fx[E_lsf_4] = Mpy_32_16_1( 419430400 /* 1/2.56f in Q30 */, lsf_new_fx[3] );   /*q15*/
     664      410255 :         hStereoClassif->xtalk_fv_fx[E_lsf_9] = Mpy_32_16_1( 419430400 /* 1/2.56f in Q30 */, lsf_new_fx[8] );   /*q15*/
     665      410255 :         hStereoClassif->xtalk_fv_fx[E_lsf_14] = Mpy_32_16_1( 419430400 /* 1/2.56f in Q30 */, lsf_new_fx[13] ); /*q15*/
     666      410255 :         hStereoClassif->xtalk_fv_fx[E_lepsP_13] = hStereoClassif->lepsP_ch1_fx;                                /*q15*/
     667      410255 :         move32();
     668      410255 :         move32();
     669      410255 :         move32();
     670      410255 :         move32();
     671      410255 :         move32();
     672             :     }
     673             :     ELSE
     674             :     {
     675      350612 :         hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = 0;
     676      350612 :         move32();
     677             :         /* making negative exponent zero as we are using this exponent to scale 1 in next block*/
     678      350612 :         IF( hStereoClassif->ratio_L_e < 0 )
     679             :         {
     680           0 :             hStereoClassif->ratio_L_fx = L_shl( hStereoClassif->ratio_L_fx, hStereoClassif->ratio_L_e );
     681           0 :             hStereoClassif->ratio_L_e = 0;
     682           0 :             move32();
     683           0 :             move16();
     684             :         }
     685     5960404 :         FOR( i = 0; i < M; i++ )
     686             :         {
     687     5609792 :             hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = L_add( hStereoClassif->xtalk_fv_fx[E_sum_d_LSF], L_abs( Mpy_32_16_1( 419430400 /* 1/2.56f in Q30 */, sub( lsf_new_fx[i], hStereoClassif->lsf_ch1_fx[i] ) ) ) ); /*q15*/
     688     5609792 :             move32();
     689             :         }
     690             : 
     691      350612 :         test();
     692      350612 :         test();
     693      350612 :         IF( hStereoClassif->vad_flag_glob && ( hStereoClassif->ratio_L_fx > 0 && LT_32( L_shr( hStereoClassif->ratio_L_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->ratio_L_e ) ) ) ) )
     694             :         {
     695      327759 :             hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = 0;
     696      327759 :             move32();
     697             :         }
     698      350612 :         lepsP_ch2_fx = L_shr( L_sub( BASOP_Util_Loge( L_add( epsP_fx[13], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ), BASOP_Util_Loge( L_add( epsP_fx[0], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ) ), 10 ); /*q15*/
     699      350612 :         hStereoClassif->xtalk_fv_fx[E_d_lepsP_13] = L_abs( L_sub( hStereoClassif->lepsP_ch1_fx, lepsP_ch2_fx ) );                                                                                                         /*q15*/
     700      350612 :         move32();
     701             :     }
     702             : 
     703      760867 :     IF( idchan == 0 )
     704             :     {
     705      410255 :         Copy( pitch, hStereoClassif->pitch_ch1, 3 );
     706      410255 :         Copy( voicing_fx, hStereoClassif->voicing_ch1_fx, 3 );
     707             : 
     708      410255 :         hStereoClassif->xtalk_fv_fx[E_pitch] = Mpy_32_16_1( L_shl( add( pitch[0], add( pitch[1], pitch[2] ) ), 15 ), 10923 );         /*q15*/
     709      410255 :         hStereoClassif->xtalk_fv_fx[E_voicing] = Mpy_32_16_1( L_add( voicing_fx[0], L_add( voicing_fx[1], voicing_fx[2] ) ), 10923 ); /*q15*/
     710      410255 :         move32();
     711      410255 :         move32();
     712             :     }
     713             :     ELSE
     714             :     {
     715      350612 :         hStereoClassif->xtalk_fv_fx[E_d_pitch] = 0;
     716      350612 :         hStereoClassif->xtalk_fv_fx[E_d_voicing] = 0;
     717     1402448 :         FOR( i = 0; i < 3; i++ )
     718             :         {
     719     1051836 :             hStereoClassif->xtalk_fv_fx[E_d_pitch] = L_add( hStereoClassif->xtalk_fv_fx[E_d_pitch], L_shl( abs_s( sub( pitch[i], hStereoClassif->pitch_ch1[i] ) ), Q15 ) );
     720     1051836 :             hStereoClassif->xtalk_fv_fx[E_d_voicing] = L_add( hStereoClassif->xtalk_fv_fx[E_d_voicing], L_abs( L_sub( voicing_fx[i], hStereoClassif->voicing_ch1_fx[i] ) ) );
     721     1051836 :             move32();
     722     1051836 :             move32();
     723             :         }
     724      350612 :         hStereoClassif->xtalk_fv_fx[E_d_pitch] = Mult_32_16( hStereoClassif->xtalk_fv_fx[E_d_pitch], 10923 /*1/3 q15*/ );
     725      350612 :         hStereoClassif->xtalk_fv_fx[E_d_voicing] = Mult_32_16( hStereoClassif->xtalk_fv_fx[E_d_voicing], 10923 /*1/3 q15*/ );
     726      350612 :         move32();
     727      350612 :         move32();
     728      350612 :         move32();
     729      350612 :         move32();
     730             :     }
     731             : 
     732             :     /* making negative exponent zero as we are using this exponent to scale 1 in next block*/
     733      760867 :     IF( hStereoClassif->nchar_ch1_e < 0 )
     734             :     {
     735           0 :         hStereoClassif->nchar_ch1_fx = L_shl( hStereoClassif->nchar_ch1_fx, hStereoClassif->nchar_ch1_e );
     736           0 :         hStereoClassif->nchar_ch1_e = 0;
     737             :     }
     738      760867 :     IF( hStereoClassif->nchar_ch2_e < 0 )
     739             :     {
     740           0 :         hStereoClassif->nchar_ch2_fx = L_shl( hStereoClassif->nchar_ch2_fx, hStereoClassif->nchar_ch2_e );
     741           0 :         hStereoClassif->nchar_ch2_e = 0;
     742             :     }
     743      760867 :     move32();
     744      760867 :     move16();
     745      760867 :     IF( idchan == 0 )
     746             :     {
     747      410255 :         hStereoClassif->cor_map_sum_ch1_fx = cor_map_sum_fx;
     748      410255 :         hStereoClassif->cor_map_sum_ch1_e = cor_map_sum_e;
     749      410255 :         hStereoClassif->non_sta_ch1_fx = non_staX_fx;
     750      410255 :         hStereoClassif->non_sta_ch1_e = non_staX_e;
     751      410255 :         hStereoClassif->sp_div_ch1_fx = sp_div_fx;
     752      410255 :         hStereoClassif->sp_div_ch1_e = sp_div_e;
     753      410255 :         hStereoClassif->xtalk_fv_fx[E_cor_map_sum] = L_shr( cor_map_sum_fx, sub( 16, cor_map_sum_e ) );                                                                                                                              /*q15*/
     754      410255 :         hStereoClassif->xtalk_fv_fx[E_nchar] = L_shr( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch1_e ) ) ), add( hStereoClassif->nchar_ch1_e, 1 ) ) /*q25*/, 10 ); /*q15*/
     755      410255 :         hStereoClassif->xtalk_fv_fx[E_non_sta] = L_shr( non_staX_fx, sub( 16, non_staX_e ) );                                                                                                                                        /*q15*/
     756      410255 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_deposit_h( sp_div_fx ), sp_div_e, ONE_IN_Q31, 0, &exp );
     757      410255 :         hStereoClassif->xtalk_fv_fx[E_sp_div] = L_shr( BASOP_Util_Loge( L_tmp, exp ), 10 ); /*q15*/
     758      410255 :         move32();
     759      410255 :         move32();
     760      410255 :         move32();
     761      410255 :         move32();
     762      410255 :         move32();
     763      410255 :         move32();
     764      410255 :         move16();
     765      410255 :         move16();
     766      410255 :         move16();
     767      410255 :         move16();
     768             :     }
     769             :     ELSE
     770             :     {
     771      350612 :         hStereoClassif->xtalk_fv_fx[E_d_cor_map_sum] = L_abs( L_sub( L_shr( hStereoClassif->cor_map_sum_ch1_fx, sub( 16, hStereoClassif->cor_map_sum_ch1_e ) ) /*q15*/, L_shr( cor_map_sum_fx, sub( 16, cor_map_sum_e ) ) /*q15*/ ) );                                                                                                                                                                                    /*q15*/
     772      350612 :         hStereoClassif->xtalk_fv_fx[E_d_nchar] = L_abs( L_shr( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch1_e ) ) ), add( hStereoClassif->nchar_ch1_e, 1 ) ), BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch2_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch2_e ) ) ), add( hStereoClassif->nchar_ch2_e, 1 ) ) ) /*q25*/, 10 ) ); /*q15*/
     773      350612 :         hStereoClassif->xtalk_fv_fx[E_d_non_sta] = L_abs( L_sub( L_shr( hStereoClassif->non_sta_ch1_fx, sub( 16, hStereoClassif->non_sta_ch1_e ) ) /*q15*/, L_shr( non_staX_fx, sub( 16, non_staX_e ) ) /*q15*/ ) );                                                                                                                                                                                                      /*q15*/
     774      350612 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_deposit_h( sp_div_fx ), sp_div_e, ONE_IN_Q31, 0, &exp );
     775      350612 :         hStereoClassif->xtalk_fv_fx[E_d_sp_div] = L_shr( BASOP_Util_Loge( L_tmp, exp ), 10 ); /*q15*/
     776      350612 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_deposit_h( hStereoClassif->sp_div_ch1_fx ), hStereoClassif->sp_div_ch1_e, ONE_IN_Q31, 0, &exp );
     777      350612 :         hStereoClassif->xtalk_fv_fx[E_d_sp_div] = L_abs( L_sub( L_shr( BASOP_Util_Loge( L_tmp, exp ), 10 ), hStereoClassif->xtalk_fv_fx[E_d_sp_div] ) ); /*q15*/
     778             :         // hStereoClassif->xtalk_fv_fx[E_d_sp_div] = L_abs( L_shr( L_sub( BASOP_Util_Loge( L_deposit_h( add( shr( hStereoClassif->sp_div_ch1_fx, 1 ), shl( 1, sub( 15 - 1, hStereoClassif->sp_div_ch1_e ) ) ) ), add( hStereoClassif->sp_div_ch1_e, 1 ) ), BASOP_Util_Loge( L_deposit_h( add( shr( sp_div_fx, 1 ), shl( 1, sub( 15 - 1, sp_div_e ) ) ) ), add( sp_div_e, 1 ) ) ) /*q25*/, 10 ) );                                                                    /*q15*/
     779      350612 :         move32();
     780      350612 :         move32();
     781      350612 :         move32();
     782      350612 :         move32();
     783      350612 :         move32();
     784             :     }
     785             : 
     786             :     /* making negative exponent zero as we are using this exponent to scale 1 in next block*/
     787      760867 :     IF( hStereoClassif->dE1_ch1_e < 0 )
     788             :     {
     789           0 :         hStereoClassif->dE1_ch1_fx = L_shl( hStereoClassif->dE1_ch1_fx, hStereoClassif->dE1_ch1_e );
     790           0 :         hStereoClassif->dE1_ch1_e = 0;
     791             :     }
     792      760867 :     IF( hStereoClassif->dE1_ch2_e < 0 )
     793             :     {
     794           0 :         hStereoClassif->dE1_ch2_fx = L_shl( hStereoClassif->dE1_ch2_fx, hStereoClassif->dE1_ch2_e );
     795           0 :         hStereoClassif->dE1_ch2_e = 0;
     796             :     }
     797      760867 :     move32();
     798      760867 :     move16();
     799             : 
     800      760867 :     IF( idchan == 0 )
     801             :     {
     802      410255 :         hStereoClassif->xtalk_fv_fx[E_dE1] = L_shr( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->dE1_ch1_e ) ) ), hStereoClassif->dE1_ch1_e + 1 ) /*q25*/, 10 ); /*q15*/
     803             :     }
     804             :     ELSE
     805             :     {
     806      350612 :         hStereoClassif->xtalk_fv_fx[E_d_dE1] = L_shr( L_abs( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch1_fx, 1 ) /*right shifting to avoid overflow*/, L_shl( 1, sub( 30, hStereoClassif->dE1_ch1_e ) ) ), add( hStereoClassif->dE1_ch1_e, 1 ) ) /*q25*/, BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch2_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->dE1_ch2_e ) ) ), add( hStereoClassif->dE1_ch2_e, 1 ) ) /*q25*/ ) ), 10 ); /*right shifting the ouput of log by 10 to bring value to q15*/
     807             :     }
     808      760867 :     move32();
     809             : 
     810      760867 :     IF( idchan == 0 )
     811             :     {
     812      410255 :         IF( GT_16( clas, VOICED_CLAS ) )
     813             :         {
     814       21700 :             hStereoClassif->clas_ch1 = VOICED_CLAS; /*q0*/
     815             :         }
     816      388555 :         ELSE IF( LT_16( clas, VOICED_CLAS ) )
     817             :         {
     818      241640 :             hStereoClassif->clas_ch1 = UNVOICED_CLAS;
     819             :         }
     820             :         ELSE
     821             :         {
     822      146915 :             hStereoClassif->clas_ch1 = clas;
     823             :         }
     824      410255 :         move16();
     825             : 
     826      410255 :         hStereoClassif->xtalk_fv_fx[E_clas] = L_shl( hStereoClassif->clas_ch1, 15 ); /*q15*/
     827             :     }
     828             :     ELSE
     829             :     {
     830      350612 :         IF( GT_16( clas, VOICED_CLAS ) )
     831             :         {
     832       14815 :             clas_ch2 = VOICED_CLAS;
     833             :         }
     834      335797 :         ELSE IF( LT_16( clas, VOICED_CLAS ) )
     835             :         {
     836      236556 :             clas_ch2 = UNVOICED_CLAS;
     837             :         }
     838             :         ELSE
     839             :         {
     840       99241 :             clas_ch2 = clas;
     841             :         }
     842      350612 :         move16();
     843             : 
     844      350612 :         hStereoClassif->xtalk_fv_fx[E_d_clas] = L_shl( L_abs( sub( hStereoClassif->clas_ch1 /*q0*/, clas_ch2 /*q0*/ ) ), 15 ); /*q15*/
     845             :     }
     846      760867 :     move32();
     847             : 
     848      760867 :     IF( idchan == 0 )
     849             :     {
     850      410255 :         hStereoClassif->xtalk_fv_fx[E_ps_diff] = L_shr( hStereoClassif->ps_diff_ch1_fx, sub( 16, hStereoClassif->ps_diff_ch1_e ) ); /*scaling to q15*/
     851      410255 :         hStereoClassif->xtalk_fv_fx[E_ps_sta] = L_shr( hStereoClassif->ps_sta_ch1_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) );    /*q15*/
     852             :     }
     853             :     ELSE
     854             :     {
     855      350612 :         hStereoClassif->xtalk_fv_fx[E_d_ps_diff] = L_abs( L_sub( L_shr( hStereoClassif->ps_diff_ch1_fx, sub( 16, hStereoClassif->ps_diff_ch1_e ) ) /*q15*/, L_shr( hStereoClassif->ps_diff_ch2_fx, sub( 16, hStereoClassif->ps_diff_ch2_e ) ) /*q15*/ ) ); /*q15*/
     856      350612 :         hStereoClassif->xtalk_fv_fx[E_d_ps_sta] = L_abs( L_sub( L_shr( hStereoClassif->ps_sta_ch1_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ) /*q15*/, L_shr( hStereoClassif->ps_sta_ch2_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ) /*q15*/ ) );      /*q15*/
     857             :     }
     858      760867 :     move32();
     859      760867 :     move32();
     860      760867 :     hStereoClassif->Etot_dn_e = hStereoClassif->Etot_up_e = hStereoClassif->e_Etot_buf_fx; /*updating the exponents*/
     861      760867 :     move16();
     862      760867 :     move16();
     863      760867 :     return;
     864             : }
     865             : 
     866             : /*-------------------------------------------------------------------*
     867             :  * Function unclr_classifier_td()
     868             :  *
     869             :  * Classify current TD frame as uncorrelated L/R (1) or normal (0)
     870             :  *-------------------------------------------------------------------*/
     871        3827 : void unclr_classifier_td_fx(
     872             :     CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure       */
     873             : )
     874             : {
     875             :     Word16 i, ind, exp;
     876             :     Word32 relE_ST, score, fvn;
     877             :     Word16 edge, edge_0_1, score_exp;
     878        3827 :     STEREO_CLASSIF_HANDLE hStereoClassif = hCPE->hStereoClassif;
     879             : 
     880             :     /* calcualte raw score based on LR */
     881        3827 :     exp = 0;
     882        3827 :     move16();
     883        3827 :     score = UNCLR_INTERCEPT_TD_Q28;
     884        3827 :     move32();
     885        3827 :     score_exp = 3;
     886        3827 :     move16();
     887       42097 :     FOR( i = 0; i < SIZE_UNCLR_ISEL_TD; i++ )
     888             :     {
     889       38270 :         ind = unclr_isel_td[i];
     890       38270 :         move16();
     891             : 
     892             :         /* mean & std removal */
     893       38270 :         fvn = BASOP_Util_Divide3232_Scale_newton( L_sub( hStereoClassif->unclr_fv_fx[ind], unclr_mean_td[i] ), unclr_scale_td[i], &exp );
     894       38270 :         fvn = Mpy_32_32( fvn, unclr_coef_td[i] ); // Q = 31-exp+15-31 = 15-exp
     895       38270 :         exp = add( exp, 16 );                     // exp = 31-(15-exp) = 16+exp
     896             : 
     897             :         /* LR */
     898       38270 :         score = BASOP_Util_Add_Mant32Exp( score, score_exp, fvn, exp, &score_exp );
     899             :     }
     900             : 
     901        3827 :     score = L_shl_sat( score, sub( score_exp, 3 ) ); // Q28
     902             : 
     903             : 
     904             :     /* normalize score to -1:+1 */
     905        3827 :     IF( GT_32( score, UNCLR_SCORE_THR_Q28 ) )
     906             :     {
     907         379 :         score = UNCLR_SCORE_THR_Q28;
     908         379 :         move32();
     909             :     }
     910        3448 :     ELSE IF( LT_32( score, -UNCLR_SCORE_THR_Q28 ) )
     911             :     {
     912         645 :         score = -UNCLR_SCORE_THR_Q28;
     913         645 :         move32();
     914             :     }
     915             :     /*score /= 2 * UNCLR_SCORE_THR; = score = score / 8
     916             :           score Q will be 31 to account the above operation*/
     917             : 
     918             :     /* weight raw score with relative energy */
     919        3827 :     score = Mpy_32_32( score, hStereoClassif->relE_0_1_fx ); // Q31
     920             : 
     921             :     /* rising edge detection on relE */
     922        3827 :     Word32 L_tmp = 0, tmp32;
     923        3827 :     move32();
     924        3827 :     Word16 L_tmp_e = 0, flag = 0;
     925        3827 :     move16();
     926        3827 :     move16();
     927        3827 :     tmp32 = hStereoClassif->relE_buf_fx[0];
     928       42097 :     FOR( i = 0; i < UNCLR_L_RELE; i++ )
     929             :     {
     930       38270 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, hStereoClassif->relE_buf_fx[i], 0, &L_tmp_e );
     931       38270 :         IF( NE_32( tmp32, hStereoClassif->relE_buf_fx[i] ) )
     932             :         {
     933       31050 :             flag = 1;
     934       31050 :             move16();
     935             :         }
     936             :     }
     937        3827 :     IF( EQ_16( flag, 1 ) )
     938             :     {
     939        3660 :         relE_ST = L_shl( Mpy_32_32( L_tmp, ONE_BY_UNCLR_L_RELE_Q31 ), L_tmp_e ); // Q31
     940             :     }
     941             :     ELSE
     942             :     {
     943         167 :         relE_ST = hStereoClassif->relE_buf_fx[0];
     944         167 :         move16();
     945             :     }
     946             : 
     947        3827 :     IF( hStereoClassif->relE_0_1_fx > relE_ST )
     948             :     {
     949        1759 :         rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_UP_Q31 );
     950             :     }
     951             :     ELSE
     952             :     {
     953        2068 :         rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_DOWN_Q31 );
     954             :     }
     955             : 
     956        3827 :     edge = extract_h( L_sub( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER - 1] ) ); // Q15
     957        3827 :     edge_0_1 = lin_interp_ivas_fx( edge, 0, 31129 /*0.95 in Q15*/, MAX_16, 29491 /*0.9 in Q15f*/, 1 );                  // Q15
     958             : 
     959             :     /* LT average */
     960        3827 :     hStereoClassif->unclr_wscore_fx = Madd_32_16( Mpy_32_16_1( hStereoClassif->unclr_wscore_fx, edge_0_1 ), score, sub( MAX_16, edge_0_1 ) ); // Q31
     961        3827 :     move32();
     962             : 
     963             :     /* binary decision w. hysteresis (switch the decision only when coder_type is GC, UC or IC) */
     964        3827 :     test();
     965        3827 :     test();
     966        3827 :     test();
     967        3827 :     test();
     968        3827 :     test();
     969        3827 :     if ( ( ( hStereoClassif->unclr_decision == 0 && GT_32( hStereoClassif->unclr_wscore_fx, 214748365 /*0.1f in Q31*/ ) ) || ( EQ_16( hStereoClassif->unclr_decision, 1 ) && LT_32( hStereoClassif->unclr_wscore_fx, -150323855 /*-0.07f in Q31*/ ) ) ) && ( hStereoClassif->unclr_sw_enable_cnt[0] > 0 || hStereoClassif->unclr_sw_enable_cnt[1] > 0 ) )
     970             :     {
     971             :         /* let's switch the binary decision */
     972           0 :         hStereoClassif->unclr_decision = !hStereoClassif->unclr_decision;
     973           0 :         move16();
     974             :     }
     975             : 
     976             : #ifdef DEBUG_FORCE_DIR
     977             :     if ( hCPE->hCoreCoder[0]->force_dir[0] != '\0' )
     978             :     {
     979             :         dbgread( &hStereoClassif->unclr_decision, sizeof( int16_t ), 1, fname( hCPE->hCoreCoder[0]->force_dir, "force_unclr_decision.enf", -1, -1, -1 ) );
     980             :     }
     981             :     else
     982             :     {
     983             :         dbgwrite( &hStereoClassif->unclr_decision, sizeof( int16_t ), 1, 1, "res/force_unclr_decision.enf" );
     984             :     }
     985             : #endif
     986             : 
     987        3827 :     return;
     988             : }
     989             : 
     990             : /*-------------------------------------------------------------------*
     991             :  * Function unclr_classifier_dft()
     992             :  *
     993             :  * Classifies current DFT frame as uncorrelated L/R (1) or normal stereo (0)
     994             :  *-------------------------------------------------------------------*/
     995       59643 : void unclr_classifier_dft_fx(
     996             :     CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure       */
     997             : )
     998             : {
     999             :     Word16 i, ind;
    1000             :     Word16 edge, edge_0_1;
    1001             :     Word32 relE_ST;
    1002             :     Word32 score, fvn[SSC_MAX_NFEA];
    1003             :     Word16 score_e, fvn_e[SSC_MAX_NFEA];
    1004             : 
    1005       59643 :     STEREO_CLASSIF_HANDLE hStereoClassif = hCPE->hStereoClassif;
    1006             : 
    1007             :     /* calculate raw score based on LR */
    1008       59643 :     score = UNCLR_INTERCEPT_DFT_Q30;
    1009       59643 :     move32();
    1010       59643 :     score_e = 1;
    1011       59643 :     move16();
    1012      536787 :     FOR( i = 0; i < SIZE_UNCLR_ISEL_DFT; i++ )
    1013             :     {
    1014      477144 :         ind = unclr_isel_dft[i];
    1015      477144 :         move16();
    1016             : 
    1017             :         /* mean & std removal */
    1018             :         // fvn[i] = (hStereoClassif->unclr_fv[ind] - unclr_mean_dft[i]) / unclr_scale_dft[i];
    1019      477144 :         fvn[i] = BASOP_Util_Divide3232_Scale_newton( L_sub( hStereoClassif->unclr_fv_fx[ind], unclr_mean_dft_Q15[i] ), unclr_scale_dft_Q15[i], &fvn_e[i] );
    1020      477144 :         move32();
    1021             : 
    1022             :         /* LR */
    1023             :         // score += fvn[i] * unclr_coef_dft[i];
    1024      477144 :         score = BASOP_Util_Add_Mant32Exp( score, score_e, Mpy_32_32( fvn[i], unclr_coef_dft_Q28[i] ), add( fvn_e[i], 3 ), &score_e );
    1025             :     }
    1026             : 
    1027             : 
    1028             :     /* normalize score to -1:+1 */
    1029       59643 :     IF( BASOP_Util_Add_Mant32Exp( score, score_e, -UNCLR_SCORE_THR_Q28, 3, &i ) > 0 )
    1030             :     {
    1031         872 :         score = UNCLR_SCORE_THR_Q28;
    1032         872 :         move32();
    1033         872 :         score_e = 3;
    1034         872 :         move16();
    1035             :     }
    1036       58771 :     ELSE IF( BASOP_Util_Add_Mant32Exp( score, score_e, UNCLR_SCORE_THR_Q28, 3, &i ) < 0 )
    1037             :     {
    1038       35994 :         score = -UNCLR_SCORE_THR_Q28;
    1039       35994 :         move32();
    1040       35994 :         score_e = 3;
    1041       35994 :         move16();
    1042             :     }
    1043             : 
    1044       59643 :     score = L_shr_r_sat( score, sub( 3, score_e ) ); // Q31
    1045             : 
    1046             :     /* weight raw score with relative energy */
    1047             :     // score *= hStereoClassif->relE_0_1;
    1048       59643 :     score = Mpy_32_32( score, hStereoClassif->relE_0_1_fx ); // Q31
    1049             : 
    1050       59643 :     if ( !hStereoClassif->vad_flag_glob )
    1051             :     {
    1052       21034 :         score = 0;
    1053       21034 :         move32();
    1054             :     }
    1055             : 
    1056             :     /* rising edge detector on relE */
    1057             :     // relE_ST = mean(hStereoClassif->relE_buf, UNCLR_L_RELE);
    1058       59643 :     Word32 L_tmp = 0, tmp32;
    1059       59643 :     move32();
    1060       59643 :     Word16 L_tmp_e = 0, flag = 0;
    1061       59643 :     move16();
    1062       59643 :     move16();
    1063       59643 :     tmp32 = hStereoClassif->relE_buf_fx[0];
    1064       59643 :     move32();
    1065      656073 :     FOR( i = 0; i < UNCLR_L_RELE; i++ )
    1066             :     {
    1067      596430 :         L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, L_tmp_e, hStereoClassif->relE_buf_fx[i], 0, &L_tmp_e );
    1068      596430 :         IF( NE_32( tmp32, hStereoClassif->relE_buf_fx[i] ) )
    1069             :         {
    1070      410239 :             flag = 1;
    1071      410239 :             move16();
    1072             :         }
    1073             :     }
    1074       59643 :     IF( EQ_16( flag, 1 ) )
    1075             :     {
    1076       52151 :         relE_ST = L_shl( Mpy_32_32( L_tmp, ONE_BY_UNCLR_L_RELE_Q31 ), L_tmp_e ); // Q31
    1077             :     }
    1078             :     ELSE
    1079             :     {
    1080        7492 :         relE_ST = hStereoClassif->relE_buf_fx[0];
    1081        7492 :         move16();
    1082             :     }
    1083             : 
    1084       59643 :     IF( GT_32( hStereoClassif->relE_0_1_fx, relE_ST ) )
    1085             :     {
    1086             :         // rc_filter(hStereoClassif->relE_0_1, hStereoClassif->unclr_relE_0_1_LT, UNCLR_RC_ORDER, RC_FACT_UP);
    1087       27288 :         rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_UP_Q31 );
    1088             :     }
    1089             :     ELSE
    1090             :     {
    1091             :         // rc_filter(hStereoClassif->relE_0_1, hStereoClassif->unclr_relE_0_1_LT, UNCLR_RC_ORDER, RC_FACT_DOWN);
    1092       32355 :         rc_filter_fx( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx, UNCLR_RC_ORDER, RC_FACT_DOWN_Q31 );
    1093             :     }
    1094             : 
    1095             :     // edge = hStereoClassif->relE_0_1 - hStereoClassif->unclr_relE_0_1_LT[UNCLR_RC_ORDER - 1];
    1096       59643 :     edge = extract_h( L_sub( hStereoClassif->relE_0_1_fx, hStereoClassif->unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER - 1] ) ); // Q15
    1097             :     // edge_0_1 = lin_interp(edge, 0.0f, 0.95f, 1.0f, 0.9f, 1);
    1098       59643 :     edge_0_1 = lin_interp_ivas_fx( edge, 0, 31129 /*0.95f*/, MAX_16, 29491 /*0.9f*/, 1 );
    1099             : 
    1100             :     /* LT average */
    1101             :     // hStereoClassif->unclr_wscore = edge_0_1 * hStereoClassif->unclr_wscore + (1 - edge_0_1) * score;
    1102       59643 :     hStereoClassif->unclr_wscore_fx = L_add( Mpy_32_16_1( hStereoClassif->unclr_wscore_fx, edge_0_1 ), Mpy_32_16_1( score, sub( MAX_16, edge_0_1 ) ) ); // Q31
    1103       59643 :     move32();
    1104             : 
    1105             :     /* binary decision w. hysteresis (switch the decision only when coder_type is GC, UC or IC) */
    1106             :     // if (((hStereoClassif->unclr_decision == 0 && hStereoClassif->unclr_wscore > 0.1f) || (hStereoClassif->unclr_decision == 1 && hStereoClassif->unclr_wscore < -0.07f)) && (hStereoClassif->unclr_sw_enable_cnt[0] > 0))
    1107       59643 :     test();
    1108       59643 :     test();
    1109       59643 :     test();
    1110       59643 :     test();
    1111       59643 :     if ( ( ( hStereoClassif->unclr_decision == 0 && GT_32( hStereoClassif->unclr_wscore_fx, 214748365 /*0.1f*/ ) ) || ( EQ_16( hStereoClassif->unclr_decision, 1 ) && LT_32( hStereoClassif->unclr_wscore_fx, -150323855 /*-0.07f*/ ) ) ) && ( hStereoClassif->unclr_sw_enable_cnt[0] > 0 ) )
    1112             :     {
    1113             :         /* let's switch the binary decision */
    1114         522 :         hStereoClassif->unclr_decision = !hStereoClassif->unclr_decision;
    1115         522 :         move16();
    1116             :     }
    1117             : 
    1118             : #ifdef DEBUG_FORCE_DIR
    1119             :     if ( hCPE->hCoreCoder[0]->force_dir[0] != '\0' )
    1120             :     {
    1121             :         dbgread( &hStereoClassif->unclr_decision, sizeof( int16_t ), 1, fname( hCPE->hCoreCoder[0]->force_dir, "force_unclr_decision.enf", -1, -1, -1 ) );
    1122             :     }
    1123             :     else
    1124             :     {
    1125             :         dbgwrite( &hStereoClassif->unclr_decision, sizeof( int16_t ), 1, 1, "res/force_unclr_decision.enf" );
    1126             :     }
    1127             : #endif
    1128             : 
    1129       59643 :     return;
    1130             : }
    1131             : 
    1132             : /*-------------------------------------------------------------------*
    1133             :  * Function xtalk_classifier_td()
    1134             :  *
    1135             :  * Classify current TD frame as cross-talk frame (1) or normal stereo frame (0)
    1136             :  *-------------------------------------------------------------------*/
    1137        3827 : void xtalk_classifier_td_fx(
    1138             :     CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure       */
    1139             : )
    1140             : {
    1141             :     Word16 i, ind, edge_type, exp, score_exp;
    1142             :     Word32 score, fvn, scr_min, scr_max;
    1143             :     Word16 edge, edge_0_1, wedge, wrelE;
    1144             : 
    1145        3827 :     STEREO_CLASSIF_HANDLE hStereoClassif = hCPE->hStereoClassif;
    1146             : 
    1147             :     /* calcualte raw score based on LR */
    1148        3827 :     exp = 0;
    1149        3827 :     move16();
    1150        3827 :     score = XTALK_INTERCEPT_TD_Q28;
    1151        3827 :     move32();
    1152        3827 :     score_exp = 3;
    1153        3827 :     move16();
    1154       68886 :     FOR( i = 0; i < SIZE_XTALK_ISEL_TD; i++ )
    1155             :     {
    1156       65059 :         ind = xtalk_isel_td[i];
    1157       65059 :         move16();
    1158             : 
    1159             :         /* mean & std removal */
    1160       65059 :         fvn = BASOP_Util_Divide3232_Scale_newton( L_sub( hStereoClassif->xtalk_fv_fx[ind], xtalk_mean_td[i] ), xtalk_scale_td[i], &exp );
    1161       65059 :         fvn = Mpy_32_32( fvn, xtalk_coef_td[i] ); // Q = 31-exp+15-31 = 15-exp
    1162       65059 :         exp = add( exp, 16 );                     // exp = 31-(15-exp) = 16+exp
    1163             : 
    1164             :         /* LR */
    1165       65059 :         score = BASOP_Util_Add_Mant32Exp( score, score_exp, fvn, exp, &score_exp );
    1166             :     }
    1167             : 
    1168        3827 :     score = L_shl_sat( score, sub( score_exp, 3 ) ); // Q28
    1169             : 
    1170             :     /* normalize raw score to -1:+1 */
    1171        3827 :     IF( GT_32( score, XTALK_SCORE_THR_TD_UP_Q28 ) )
    1172             :     {
    1173        1131 :         score = MAX_32; // Q31
    1174        1131 :         move32();
    1175             :     }
    1176        2696 :     ELSE IF( LT_32( score, -XTALK_SCORE_THR_TD_DN_Q28 ) )
    1177             :     {
    1178         110 :         score = MIN_32; // Q31
    1179         110 :         move32();
    1180             :     }
    1181        2586 :     ELSE IF( score > 0 )
    1182             :     {
    1183        1775 :         score = Mpy_32_32( score, ONE_BY_XTALK_SCORE_THR_TD_UP_Q31 ); // Q = 31-score_exp
    1184        1775 :         score = L_shl( score, 3 );                                    // Q31
    1185             :     }
    1186             :     ELSE
    1187             :     {
    1188         811 :         score = Mpy_32_32( score, ONE_BY_XTALK_SCORE_THR_TD_DN_Q31 ); // Q = 31-score_exp
    1189         811 :         score = L_shl( score, 3 );                                    // Q31
    1190             :     }
    1191             : 
    1192        3827 :     IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) )
    1193             :     {
    1194             :         /* overwrite score if we have just switched from DFT stereo */
    1195          54 :         score = hStereoClassif->xtalk_score_fx; // Q31
    1196          54 :         move32();
    1197             :     }
    1198             :     ELSE
    1199             :     {
    1200        3773 :         hStereoClassif->xtalk_score_fx = score; // Q31
    1201        3773 :         move32();
    1202             :     }
    1203             : 
    1204        3827 :     if ( !hStereoClassif->vad_flag_glob )
    1205             :     {
    1206             :         /* reset score to 0 in inactive segments */
    1207         173 :         score = 0;
    1208         173 :         move32();
    1209             :     }
    1210             : 
    1211             : 
    1212             :     /* weight raw score with relative energy */
    1213        3827 :     wrelE = lin_interp_ivas_fx( extract_h( hStereoClassif->relE_0_1_fx ), 16384 /*0.5f Q15*/, 31129 /*0.95f Q15*/, 29491 /*0.9f Q15*/, 0, 1 );
    1214        3827 :     hStereoClassif->xtalk_score_wrelE_fx = Madd_32_16( Mpy_32_16_1( hStereoClassif->xtalk_score_wrelE_fx, wrelE ), score, sub( MAX_16, wrelE ) ); // Q31
    1215        3827 :     move32();
    1216        3827 :     score = hStereoClassif->xtalk_score_wrelE_fx; // Q31
    1217        3827 :     move32();
    1218             : 
    1219             :     /* rising edge detector on raw score -> yields 1 if strong rising edge is detected in the raw score buffer */
    1220        3827 :     Copy32( &hStereoClassif->xtalk_score_buf_fx[0], &hStereoClassif->xtalk_score_buf_fx[1], XTALK_SCORE_BUF_LEN - 1 );
    1221        3827 :     hStereoClassif->xtalk_score_buf_fx[0] = score; // Q31
    1222        3827 :     move32();
    1223             : 
    1224        3827 :     minimum_l( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, &scr_min );
    1225        3827 :     maximum_l( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, &scr_max );
    1226             : 
    1227        3827 :     test();
    1228        3827 :     test();
    1229        3827 :     IF( ( scr_min < 0 && GT_32( scr_max, 429496730 /*0.2f in Q31*/ ) ) || GT_32( L_sub_sat( scr_max, scr_min ), 1073741824 /*0.5f Q31*/ ) )
    1230             :     {
    1231             :         /* test rising edge (use 0 as edge_type because of newer->older buffer samples ordering) */
    1232         894 :         edge_type = 0;
    1233         894 :         move16();
    1234         894 :         edge_detect_fx( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, -53687091 /*-0.2f Q28*/, ONE_IN_Q28, &edge, &edge_type );
    1235             : 
    1236         894 :         test();
    1237         894 :         IF( edge_type == 0 && LT_16( edge, 9830 /*0.3f Q15*/ ) )
    1238             :         {
    1239             :             /* normalize edge to 0-1 interval */
    1240         570 :             edge_0_1 = lin_interp_ivas_fx( sub( MAX_16, edge ), MAX_16, MAX_16, 19661 /*0.6f Q15*/, 0, 1 );
    1241             :         }
    1242             :         ELSE
    1243             :         {
    1244         324 :             edge_0_1 = 0;
    1245         324 :             move16();
    1246             :         }
    1247             :     }
    1248             :     ELSE
    1249             :     {
    1250        2933 :         edge_0_1 = 0;
    1251        2933 :         move16();
    1252             :     }
    1253             : 
    1254             :     /* weight raw score based on rising edge detector */
    1255        3827 :     wedge = lin_interp_ivas_fx( edge_0_1, 0, 29491 /*0.9f Q15*/, MAX_16, 16384 /*0.5f Q15 */, 1 );
    1256             : 
    1257        3827 :     hStereoClassif->xtalk_wscore_fx = Madd_32_16( Mpy_32_16_1( hStereoClassif->xtalk_wscore_fx, wedge ), score, sub( MAX_16, wedge ) ); // Q31
    1258        3827 :     move32();
    1259             : 
    1260        3827 :     if ( !hStereoClassif->vad_flag_glob )
    1261             :     {
    1262         173 :         hStereoClassif->xtalk_wscore_fx = 0;
    1263         173 :         move16();
    1264             :     }
    1265             : 
    1266             :     /* binary decision w. hysteresis (switch the decision only when coder_type is GC, UC or IC) */
    1267        3827 :     test();
    1268        3827 :     test();
    1269        3827 :     test();
    1270        3827 :     test();
    1271        3827 :     if ( ( hStereoClassif->unclr_decision == 0 && hStereoClassif->xtalk_decision == 0 && GT_32( hStereoClassif->xtalk_wscore_fx, 64424509 /*0.03f Q31*/ ) ) /*|| (hStereoClassif->xtalk_decision == 1 && hStereoClassif->xtalk_wscore < 0.00f)*/ && ( hStereoClassif->unclr_sw_enable_cnt[0] > 0 || hStereoClassif->unclr_sw_enable_cnt[1] > 0 ) )
    1272             :     {
    1273             :         /* let's switch the binary decision */
    1274           8 :         hStereoClassif->xtalk_decision = !hStereoClassif->xtalk_decision;
    1275           8 :         move16();
    1276             :     }
    1277             : 
    1278             : #ifdef DEBUG_FORCE_DIR
    1279             :     if ( hCPE->hCoreCoder[0]->force_dir[0] != '\0' )
    1280             :     {
    1281             :         dbgread( &hStereoClassif->xtalk_decision, sizeof( int16_t ), 1, fname( hCPE->hCoreCoder[0]->force_dir, "force_xtalk_decision.enf", -1, -1, -1 ) );
    1282             :     }
    1283             :     else
    1284             :     {
    1285             :         dbgwrite( &hStereoClassif->xtalk_decision, sizeof( int16_t ), 1, 1, "res/force_xtalk_decision.enf" );
    1286             :     }
    1287             : #endif
    1288             : 
    1289        3827 :     return;
    1290             : }
    1291             : 
    1292             : /*-------------------------------------------------------------------*
    1293             :  * Function xtalk_classifier_dft()
    1294             :  *
    1295             :  * Classify current DFT frame as cross-talk frame (1) or normal stereo frame (0)
    1296             :  *-------------------------------------------------------------------*/
    1297             : 
    1298       74333 : void xtalk_classifier_dft_fx(
    1299             :     CPE_ENC_HANDLE hCPE,    /* i/o: CPE encoder structure                   */
    1300             :     const Word16 itd,       /* i  : ITD from DFT stereo - used as a feature */
    1301             :     const Word32 gcc_phat[] /* i  : GPHAT cross-channel correlation function Q31*/
    1302             : )
    1303             : {
    1304             :     Word16 i, ind, itd2, thr;
    1305             :     Word32 score, m1, m2;
    1306             :     STEREO_CLASSIF_HANDLE hStereoClassif;
    1307             :     ITD_DATA_HANDLE hItd;
    1308             :     Word32 fvn[SSC_MAX_NFEA] /*Q28*/, edge;
    1309             :     Word16 edge_e;
    1310             :     Word16 edge_0_1, wedge;
    1311             :     Word32 ratio_m1_m2, m2_m2, d_itd2, itd1_flip;
    1312             :     Word32 scr_min, scr_max;
    1313             :     Word64 W_tmp;
    1314             : 
    1315       74333 :     hStereoClassif = hCPE->hStereoClassif;
    1316       74333 :     IF( hCPE->hStereoDft != NULL )
    1317             :     {
    1318       59643 :         hItd = hCPE->hStereoDft->hItd;
    1319             :     }
    1320             :     ELSE
    1321             :     {
    1322       14690 :         hItd = hCPE->hStereoMdct->hItd;
    1323             :     }
    1324             : 
    1325       74333 :     m1 = 0;
    1326       74333 :     move32();
    1327       74333 :     m2 = 0;
    1328       74333 :     move32();
    1329             : 
    1330       74333 :     itd2 = 0;
    1331       74333 :     move16();
    1332             :     // thr = ( hCPE->element_brate >= IVAS_32k ? 2 : 1 ) * CLASSIFIER_ITD_THRES;
    1333       74333 :     IF( GE_32( hCPE->element_brate, IVAS_32k ) )
    1334             :     {
    1335       35913 :         thr = 2 * CLASSIFIER_ITD_THRES;
    1336       35913 :         move16();
    1337             :     }
    1338             :     ELSE
    1339             :     {
    1340       38420 :         thr = CLASSIFIER_ITD_THRES;
    1341       38420 :         move16();
    1342             :     }
    1343       74333 :     IF( GT_16( itd, thr ) )
    1344             :     {
    1345       16002 :         m1 = L_abs( gcc_phat[itd + XTALK_PHAT_LEN] );
    1346       16002 :         m2 = L_abs( gcc_phat[0] );
    1347       16002 :         itd2 = -XTALK_PHAT_LEN;
    1348       16002 :         move16();
    1349     3018840 :         FOR( i = 1; i < ( XTALK_PHAT_LEN - thr ); i++ )
    1350             :         {
    1351     3002838 :             IF( GT_32( L_abs( gcc_phat[i] ), m2 ) )
    1352             :             {
    1353      130652 :                 itd2 = add( -XTALK_PHAT_LEN, i );
    1354      130652 :                 m2 = L_abs( gcc_phat[i] );
    1355             :             }
    1356             :         }
    1357             :     }
    1358       58331 :     ELSE IF( LT_16( itd, negate( thr ) ) )
    1359             :     {
    1360       11032 :         m1 = L_abs( gcc_phat[itd + XTALK_PHAT_LEN] );
    1361       11032 :         m2 = L_abs( gcc_phat[XTALK_PHAT_LEN + thr + 1] );
    1362       11032 :         itd2 = add( thr, 1 );
    1363     2074008 :         FOR( i = ( XTALK_PHAT_LEN + 2 + thr ); i < 2 * XTALK_PHAT_LEN + 1; i++ )
    1364             :         {
    1365     2062976 :             IF( GT_32( L_abs( gcc_phat[i] ), m2 ) )
    1366             :             {
    1367       56322 :                 itd2 = add( -XTALK_PHAT_LEN, i );
    1368       56322 :                 m2 = L_abs( gcc_phat[i] );
    1369             :             }
    1370             :         }
    1371             :     }
    1372             : 
    1373             :     // ratio_m1_m2 = fabsf( m1 * m2 ) / fabsf( m1 + m2 + 1.0f );
    1374             :     Word16 exp;
    1375       74333 :     ratio_m1_m2 = BASOP_Util_Divide3232_Scale_newton( L_abs( Mpy_32_32( m1, m2 ) ), L_abs( L_add( L_add( L_shr( m1, 2 ), L_shr( m2, 2 ) ), ONE_IN_Q29 ) ), &exp );
    1376       74333 :     exp = sub( exp, 2 );
    1377             :     // m2_m2 = hItd->prev_m2 * m2;
    1378       74333 :     m2_m2 = Mpy_32_32( hItd->prev_m2_fx, m2 );
    1379             :     // d_itd2 = (float) abs( itd2 - hItd->prev_itd2 );
    1380       74333 :     d_itd2 = abs_s( sub( itd2, hItd->prev_itd2 ) ); // Q0
    1381             :     // itd1_flip = (float) ( max( itd, hItd->prev_itd1 ) * ( -min( itd, hItd->prev_itd1 ) ) );
    1382       74333 :     itd1_flip = L_mult0( s_max( itd, hItd->prev_itd1 ), negate( s_min( itd, hItd->prev_itd1 ) ) ); // Q0
    1383             : 
    1384             : 
    1385       74333 :     hStereoClassif->xtalk_fv_fx[E_gphat_d_itd2] = L_shl( d_itd2, 15 ); // Q15
    1386       74333 :     move32();
    1387       74333 :     hStereoClassif->xtalk_fv_fx[E_gphat_itd1_flip] = L_shl( itd1_flip, 15 ); // Q15
    1388       74333 :     move32();
    1389       74333 :     hStereoClassif->xtalk_fv_fx[E_gphat_ratio_m1_m2] = L_shr_r( Mpy_32_32( ratio_m1_m2, hStereoClassif->prev_ratio_m1_m2_fx ), sub( Q16, exp ) ); // Q15
    1390       74333 :     move32();
    1391       74333 :     hStereoClassif->xtalk_fv_fx[E_gphat_m2_m2] = L_shr_r( m2_m2, Q16 ); // Q15
    1392       74333 :     move32();
    1393             : 
    1394       74333 :     hStereoClassif->prev_ratio_m1_m2_fx = L_shl( ratio_m1_m2, exp );
    1395       74333 :     move32();
    1396             : 
    1397       74333 :     set32_fx( fvn, -ONE_IN_Q29, SSC_MAX_NFEA );
    1398             : 
    1399             :     /* calcualte raw score based on LR */
    1400       74333 :     W_tmp = XTALK_INTERCEPT_DFT_Q27;
    1401       74333 :     move64();
    1402      891996 :     FOR( i = 0; i < SIZE_XTALK_ISEL_DFT; i++ )
    1403             :     {
    1404      817663 :         ind = xtalk_isel_dft[i];
    1405      817663 :         move16();
    1406             : 
    1407             :         /* mean & std removal */
    1408             :         // fvn[i] = ( hStereoClassif->xtalk_fv[ind] - xtalk_mean_dft[i] ) / xtalk_scale_dft[i];
    1409      817663 :         fvn[i] = BASOP_Util_Divide3232_Scale_newton( L_sub( hStereoClassif->xtalk_fv_fx[ind], xtalk_mean_dft_q15[i] ), xtalk_scale_dft_q15[i], &exp ); // Q15
    1410      817663 :         move32();
    1411      817663 :         fvn[i] = L_shl_sat( fvn[i], sub( exp, 2 ) ); // Q29
    1412      817663 :         move32();
    1413             : 
    1414             :         /* LR */
    1415             :         // score += fvn[i] * xtalk_coef_dft[i];
    1416      817663 :         W_tmp = W_add( W_tmp, L_shr( Mpy_32_32( fvn[i], xtalk_coef_dft_q30[i] ), 1 ) ); // Q27
    1417             :     }
    1418             : 
    1419             :     /* normalize score to -1:+1 */
    1420       74333 :     IF( GT_64( W_tmp, XTALK_SCORE_THR_DFT_Q27 ) )
    1421             :     {
    1422        2463 :         score = MAX_32; // Q31
    1423        2463 :         move32();
    1424             :     }
    1425       71870 :     ELSE IF( LT_64( W_tmp, -XTALK_SCORE_THR_DFT_Q27 ) )
    1426             :     {
    1427        4536 :         score = MIN_32; // Q31
    1428        4536 :         move32();
    1429             :     }
    1430             :     ELSE
    1431             :     {
    1432             :         // score /= XTALK_SCORE_THR_DFT;
    1433       67334 :         score = L_shl_sat( W_extract_l( W_tmp ), 2 ); // Q27->Q31/XTALK_SCORE_THR_DFT
    1434             :     }
    1435             : 
    1436             :     /* raw score */
    1437       74333 :     hStereoClassif->xtalk_score_fx = score;
    1438       74333 :     move32();
    1439             :     // printf( "%f ", (float) hStereoClassif->xtalk_score_fx / 0x7fffffff );
    1440             : 
    1441       74333 :     if ( !hStereoClassif->vad_flag_glob )
    1442             :     {
    1443       24931 :         score = 0;
    1444       24931 :         move32();
    1445             :     }
    1446             : 
    1447             : 
    1448             :     /* rising edge detector on raw score -> yields 1 if strong rising edge is detected in the given buffer */
    1449       74333 :     Copy32( &hStereoClassif->xtalk_score_buf_fx[0], &hStereoClassif->xtalk_score_buf_fx[1], XTALK_SCORE_BUF_LEN - 1 );
    1450       74333 :     hStereoClassif->xtalk_score_buf_fx[0] = score;
    1451       74333 :     move32();
    1452       74333 :     minimum_l( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, &scr_min );
    1453       74333 :     maximum_l( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, &scr_max );
    1454             : 
    1455       74333 :     test();
    1456       74333 :     IF( LT_32( scr_min, 429496730 /*0.2f*/ ) && scr_max > 0 )
    1457       15815 :     {
    1458       15815 :         edge = redge_detect_fx( hStereoClassif->xtalk_score_buf_fx, XTALK_SCORE_BUF_LEN, -429496730 /*-0.2f*/, MAX_32 /*1.0f*/, &edge_e );
    1459             :         // edge_0_1 = lin_interp( 1 - edge, 1.0f, 1.0f, 0.83f, 0.0f, 1 );
    1460             :         Word16 temp;
    1461       15815 :         Word16 temp_e = BASOP_Util_Add_MantExp( MAX_16, 0, negate( extract_h( edge ) ), edge_e, &temp );
    1462       15815 :         temp = shl( temp, temp_e ); // Q15
    1463       15815 :         edge_0_1 = lin_interp_ivas_fx( temp, MAX_16, MAX_16, 27197, 0, 1 );
    1464             :     }
    1465             :     ELSE
    1466             :     {
    1467       58518 :         edge_0_1 = 0;
    1468       58518 :         move16();
    1469             :     }
    1470             : 
    1471             :     /* weight raw score based on rising edge detector */
    1472             :     // wedge = lin_interp( edge_0_1, 0.0f, 0.95f, 1.0f, 0.3f, 1 );
    1473       74333 :     wedge = lin_interp_ivas_fx( edge_0_1, 0, 31129, MAX_16, 9830, 1 );
    1474             :     // hStereoClassif->xtalk_wscore = wedge * hStereoClassif->xtalk_wscore + ( 1 - wedge ) * score;
    1475       74333 :     hStereoClassif->xtalk_wscore_fx = L_add( Mpy_32_16_1( hStereoClassif->xtalk_wscore_fx, wedge ), Mpy_32_16_1( score, sub( MAX_16, wedge ) ) );
    1476       74333 :     move32();
    1477             : 
    1478       74333 :     test();
    1479       74333 :     test();
    1480       74333 :     test();
    1481       74333 :     test();
    1482       74333 :     test();
    1483       74333 :     test();
    1484       74333 :     test();
    1485       74333 :     test();
    1486       74333 :     test();
    1487       74333 :     test();
    1488       74333 :     test();
    1489       74333 :     test();
    1490       74333 :     test();
    1491       74333 :     test();
    1492       74333 :     test();
    1493       74333 :     test();
    1494       74333 :     test();
    1495       74333 :     test();
    1496       74333 :     test();
    1497       74333 :     test();
    1498       74333 :     IF( ( itd == 0 ) || ( hCPE->hCoreCoder[0]->vad_flag == 0 ) )
    1499             :     {
    1500       39403 :         hStereoClassif->xtalk_decision = 0;
    1501       39403 :         move16();
    1502             :     }
    1503       34930 :     ELSE IF( GE_32( hCPE->element_brate, IVAS_24k4 ) &&
    1504             :              hStereoClassif->xtalk_decision == 0 && ( ( LT_32( Mpy_32_32( m1, 1717986918 /*0.8f*/ ), m2 ) && LT_32( Mpy_32_32( hItd->prev_m1_fx, 1717986918 /*0.8*/ ), hItd->prev_m2_fx ) && LT_16( abs_s( sub( itd2, hItd->prev_itd2 ) ), 4 ) && GT_32( m1, 322122547 /*0.15*/ ) && GT_32( hItd->prev_m1_fx, 322122547 /*0.15*/ ) ) || GT_32( hStereoClassif->xtalk_wscore_fx, 1717986918 /*0.8*/ ) || ( GT_16( itd, thr ) && LT_16( hItd->prev_itd1, negate( thr ) ) && hStereoClassif->silence_flag == 0 ) || ( GT_16( hItd->prev_itd1, thr ) && LT_16( itd, negate( thr ) ) && hStereoClassif->silence_flag == 0 ) ) &&
    1505             :              EQ_16( hCPE->hCoreCoder[0]->vad_flag, 1 ) && hCPE->hCoreCoder[0]->flag_noisy_speech_snr == 0 && GT_16( hCPE->hCoreCoder[0]->hNoiseEst->aEn_inac_cnt, 15 ) )
    1506             :     {
    1507           0 :         hStereoClassif->xtalk_decision = 1;
    1508           0 :         move16();
    1509             :     }
    1510       34930 :     ELSE IF( GE_32( hCPE->element_brate, IVAS_16k4 ) && hStereoClassif->xtalk_decision == 0 && GT_16( abs_s( itd ), STEREO_DFT_ITD_MAX ) && GT_16( sub( hCPE->hCoreCoder[0]->lp_speech_fx, hCPE->hCoreCoder[0]->lp_noise_fx ), 25 << 8 ) )
    1511             :     {
    1512          69 :         hStereoClassif->xtalk_decision = 1;
    1513          69 :         move16();
    1514             :     }
    1515             : 
    1516             :     /* updates */
    1517       74333 :     hItd->prev_m1_fx = m1;
    1518       74333 :     move32();
    1519       74333 :     hItd->prev_m2_fx = m2;
    1520       74333 :     move32();
    1521       74333 :     hItd->prev_itd1 = itd;
    1522       74333 :     move16();
    1523       74333 :     hItd->prev_itd2 = itd2;
    1524       74333 :     move16();
    1525             : 
    1526             : #ifdef DEBUG_FORCE_DIR
    1527             :     if ( hCPE->hCoreCoder[0]->force_dir[0] != '\0' )
    1528             :     {
    1529             :         dbgread( &hStereoClassif->xtalk_decision, sizeof( int16_t ), 1, fname( hCPE->hCoreCoder[0]->force_dir, "force_xtalk_decision.enf", -1, -1, -1 ) );
    1530             :     }
    1531             :     else
    1532             :     {
    1533             :         dbgwrite( &hStereoClassif->xtalk_decision, sizeof( int16_t ), 1, 1, "res/force_xtalk_decision.enf" );
    1534             :     }
    1535             : #endif
    1536             : 
    1537       74333 :     return;
    1538             : }
    1539             : 
    1540             : /*-------------------------------------------------------------------*
    1541             :  * Function rc_filter()
    1542             :  *
    1543             :  *
    1544             :  *-------------------------------------------------------------------*/
    1545       63470 : static void rc_filter_fx(
    1546             :     const Word32 x, // Q31
    1547             :     Word32 *y,      // Q31
    1548             :     const Word16 order,
    1549             :     const Word32 tau ) // Q31
    1550             : {
    1551             :     Word16 i;
    1552             : 
    1553       63470 :     y[0] = L_add( Mpy_32_32( tau, y[0] ), Mpy_32_32( L_sub( MAX_32, tau ), x ) );
    1554       63470 :     move32();
    1555     1269400 :     FOR( i = 1; i < order; i++ )
    1556             :     {
    1557     1205930 :         y[i] = L_add( Mpy_32_32( tau, y[i] ), Mpy_32_32( L_sub( MAX_32, tau ), y[i - 1] ) );
    1558     1205930 :         move32();
    1559             :     }
    1560             : 
    1561       63470 :     return;
    1562             : }
    1563             : 
    1564             : /*-------------------------------------------------------------------*
    1565             :  * Function edge_detect_fx()
    1566             :  *
    1567             :  * Rising/falling edge detection algorithm
    1568             :  * Analyzes the input buffer and outputs strength and type of the detected edge (rising or falling)
    1569             :  * Set edge_type to 0/1/2 when calling this function to specify the edge type you want to detect. The returned value will be modified
    1570             :  * according to the edge type detected (-1 indicates that no edge has been detected)
    1571             :  *-------------------------------------------------------------------*/
    1572         894 : static void edge_detect_fx(
    1573             :     const Word32 *inp,    /* i  : input buffer                       Q31*/
    1574             :     const Word16 len,     /* i  : length of the input buffer         Q0*/
    1575             :     const Word32 inp_min, /* i  : minimum value for edge detection   Q28*/
    1576             :     const Word32 inp_max, /* i  : maximum value for edge detection   Q28*/
    1577             :     Word16 *edge_str,     /* o  : edge strength (from 0 to Inf)      Q15*/
    1578             :     Word16 *edge_type     /* i/o: edge type (to be) detected: 0 = falling, 1 = rising, 2 = both */
    1579             : )
    1580             : {
    1581             :     Word16 i, j, et;
    1582             :     Word32 y, err, edge_slope, edge[EDGE_MAX_LEN];
    1583             :     Word32 edge_min, err0, L_tmp;
    1584             : 
    1585         894 :     et = -1;
    1586         894 :     move16();
    1587         894 :     edge_min = ONE_IN_Q25;
    1588         894 :     move32();
    1589             : 
    1590         894 :     test();
    1591         894 :     IF( *edge_type == 0 || EQ_16( *edge_type, 2 ) )
    1592             :     {
    1593             :         /* falling edge detection */
    1594         894 :         set_zero_fx( edge, EDGE_MAX_LEN );
    1595             : 
    1596             :         /* set error at 0th index */
    1597         894 :         IF( GT_32( L_shr( inp[0], 6 ), inp_max ) )
    1598             :         {
    1599           0 :             err0 = 0;
    1600           0 :             move32();
    1601             :         }
    1602             :         ELSE
    1603             :         {
    1604             :             /* inhibits edge smearing effect */
    1605             :             /* err0 = powf( inp[0] - inp_max, 2 ); */
    1606         894 :             L_tmp = L_sub( L_shr( inp[0], 3 ), inp_max ); // Q28
    1607         894 :             err0 = Mpy_32_32( L_tmp, L_tmp );             // Q25
    1608             :         }
    1609             : 
    1610             :         /* test edges on intervals from 2 to len */
    1611        4470 :         FOR( i = 1; i < len; i++ )
    1612             :         {
    1613        3576 :             IF( EQ_16( i, 1 ) )
    1614             :             {
    1615         894 :                 edge_slope = L_sub( inp_max, inp_min ); // Q28
    1616             :             }
    1617             :             ELSE
    1618             :             {
    1619        2682 :                 edge_slope = Mpy_32_16_1( L_sub( inp_max, inp_min ), divide1616( 1, i ) ); // Q28
    1620             :             }
    1621        3576 :             edge[i] = err0; // Q25
    1622        3576 :             move32();
    1623       12516 :             FOR( j = 1; j <= i; j++ )
    1624             :             {
    1625        8940 :                 y = L_sub( inp_max, imult3216( edge_slope, j ) );                         // Q28
    1626        8940 :                 err = L_sub( y, check_bounds_l( L_shr( inp[j], 3 ), inp_min, inp_max ) ); // Q28
    1627        8940 :                 edge[i] = Madd_32_32( edge[i], err, err );                                // Q25
    1628        8940 :                 move32();
    1629             :             }
    1630             : 
    1631        3576 :             edge[i] = Mpy_32_16_1( edge[i], divide1616( 1, add( i, 1 ) ) ); // Q25
    1632        3576 :             move32();
    1633             : 
    1634        3576 :             IF( LT_32( edge[i], edge_min ) )
    1635             :             {
    1636        2590 :                 edge_min = edge[i]; // Q25
    1637        2590 :                 move32();
    1638        2590 :                 et = 0;
    1639        2590 :                 move16();
    1640             :             }
    1641             :         }
    1642             :     }
    1643             : 
    1644         894 :     test();
    1645         894 :     IF( EQ_16( *edge_type, 1 ) || EQ_16( *edge_type, 2 ) )
    1646             :     {
    1647             :         /* rising edge detection */
    1648           0 :         set_zero_fx( edge, EDGE_MAX_LEN );
    1649             : 
    1650             :         /* set error at 0th index */
    1651           0 :         IF( LT_32( L_shr( inp[0], 3 ), inp_min ) )
    1652             :         {
    1653           0 :             err0 = 0;
    1654           0 :             move32();
    1655             :         }
    1656             :         ELSE
    1657             :         {
    1658             :             /* inhibits edge smearing effect */
    1659             :             /*err0 = powf( inp[0] - inp_min, 2 );*/
    1660           0 :             L_tmp = L_sub( L_shr( inp[0], 3 ), inp_min ); // Q28
    1661           0 :             err0 = Mpy_32_32( L_tmp, L_tmp );             // Q25
    1662             :         }
    1663             : 
    1664             :         /* test edges on intervals from 2 to len */
    1665           0 :         FOR( i = 1; i <= len; i++ )
    1666             :         {
    1667           0 :             IF( EQ_16( i, 1 ) )
    1668             :             {
    1669           0 :                 edge_slope = L_sub( inp_max, inp_min ); // Q28
    1670             :             }
    1671             :             ELSE
    1672             :             {
    1673           0 :                 edge_slope = Mpy_32_16_1( L_sub( inp_max, inp_min ), divide1616( 1, i ) ); // Q28
    1674             :             }
    1675             : 
    1676           0 :             edge[i] = err0; // Q25
    1677           0 :             move32();
    1678             : 
    1679           0 :             FOR( j = 1; j < i; j++ )
    1680             :             {
    1681           0 :                 y = L_add( inp_min, imult3216( edge_slope, j ) );                         // Q28
    1682           0 :                 err = L_sub( y, check_bounds_l( L_shr( inp[j], 1 ), inp_min, inp_max ) ); // Q28
    1683           0 :                 edge[i] = Madd_32_32( edge[i], err, err );                                // Q25
    1684           0 :                 move32();
    1685             :             }
    1686             : 
    1687           0 :             edge[i] = Mpy_32_16_1( edge[i], divide1616( 1, add( i, 1 ) ) ); // Q25
    1688           0 :             move32();
    1689             : 
    1690           0 :             IF( LT_32( edge[i], edge_min ) )
    1691             :             {
    1692           0 :                 edge_min = edge[i]; // Q25
    1693           0 :                 move32();
    1694           0 :                 et = 1;
    1695           0 :                 move16();
    1696             :             }
    1697             :         }
    1698             :     }
    1699             : 
    1700         894 :     *edge_str = extract_h( L_shl_sat( edge_min, 16 - 10 ) ); // Q15
    1701         894 :     move16();
    1702         894 :     *edge_type = et; // Q0
    1703         894 :     move16();
    1704             : 
    1705         894 :     return;
    1706             : }
    1707             : 
    1708             : /*-------------------------------------------------------------------*
    1709             :  * Function redge_detect()
    1710             :  *
    1711             :  * Rising edge detection algorithm
    1712             :  * Analyzes the input buffer and outputs value close to 1 when it detects strong rising edge
    1713             :  *-------------------------------------------------------------------*/
    1714             : 
    1715             : /*! r: rising edge strength normalized to 0-1 */
    1716       15815 : static Word32 redge_detect_fx(
    1717             :     const Word32 *inp,    /* i  : input buffer (ordered from newest to oldest values) Q31*/
    1718             :     const Word16 len,     /* i  : length of the input buffer                         */
    1719             :     const Word32 inp_min, /* i  : minimum value for edge detection                  Q31 */
    1720             :     const Word32 inp_max, /* i  : maximum value for edge detection                  Q31 */
    1721             :     Word16 *edge_min_e )
    1722             : {
    1723             :     Word16 i, j;
    1724             :     Word32 y, err, edge_slope, edge[REDGE_MAX_LEN];
    1725             :     Word16 y_e, edge_slope_e, edge_e[REDGE_MAX_LEN];
    1726             :     Word32 edge_min, err0;
    1727             :     Word16 err0_e;
    1728             :     Word16 L_temp_e;
    1729             :     Word32 L_temp;
    1730             : 
    1731       15815 :     set32_fx( edge, 0, REDGE_MAX_LEN );
    1732       15815 :     set16_fx( edge_e, 0, REDGE_MAX_LEN );
    1733       15815 :     edge_min = 10000000 /*1e7f*/; // Q0
    1734       15815 :     move32();
    1735       15815 :     *edge_min_e = 31;
    1736       15815 :     move16();
    1737             : 
    1738             :     /* test rising edges on intervals from 2 to len */
    1739       15815 :     IF( GT_32( inp[0], inp_max ) )
    1740             :     {
    1741           0 :         err0 = 0;
    1742           0 :         move32();
    1743           0 :         err0_e = 0;
    1744           0 :         move16();
    1745             :     }
    1746             :     ELSE
    1747             :     {
    1748             :         // err0 = powf( inp[0] - inp_max, 2 );
    1749             :         // Word32 temp = L_sub( inp[0], inp_max );
    1750       15815 :         err0 = BASOP_Util_Add_Mant32Exp( inp[0], 0, L_negate( inp_max ), 0, &err0_e );
    1751       15815 :         err0 = Mpy_32_32( err0, err0 );
    1752       15815 :         err0_e = shl( err0_e, 1 );
    1753             :     }
    1754       79075 :     FOR( i = 1; i < len; i++ )
    1755             :     {
    1756             :         // edge_slope = ( inp_max - inp_min ) / i;
    1757       63260 :         L_temp = BASOP_Util_Add_Mant32Exp( inp_max, 0, L_negate( inp_min ), 0, &L_temp_e );
    1758       63260 :         edge_slope = BASOP_Util_Divide3232_Scale_newton( L_temp, i, &edge_slope_e );
    1759       63260 :         edge_slope_e = add( edge_slope_e, sub( L_temp_e, 31 ) );
    1760       63260 :         edge[i] = err0;
    1761       63260 :         move32();
    1762       63260 :         edge_e[i] = err0_e;
    1763       63260 :         move16();
    1764      158150 :         FOR( j = 1; j < i; j++ )
    1765             :         {
    1766             :             // y = inp_max - edge_slope * j;
    1767       94890 :             y = BASOP_Util_Add_Mant32Exp( inp_max, 0, L_negate( Mpy_32_32( edge_slope, L_shl( j, 28 ) ) ), add( edge_slope_e, 3 ), &y_e );
    1768       94890 :             y = L_shl( y, y_e );
    1769       94890 :             IF( EQ_32( inp[j], inp[j - 1] ) && EQ_32( inp[j], inp_max ) )
    1770             :             {
    1771             :                 /* we are saturated at inp_max */
    1772         775 :                 err = 0;
    1773         775 :                 move32();
    1774             :             }
    1775       94115 :             ELSE IF( LT_32( inp[j], inp_min ) )
    1776             :             {
    1777             :                 /* we are below inp_min */
    1778        6885 :                 err = L_sub( y, inp_min );
    1779             :             }
    1780             :             ELSE
    1781             :             {
    1782       87230 :                 err = L_sub( y, inp[j] );
    1783             :             }
    1784       94890 :             err = Mpy_32_32( err, err );
    1785             :             // edge[i] = L_add( edge[i], err );
    1786       94890 :             edge[i] = BASOP_Util_Add_Mant32Exp( edge[i], edge_e[i], err, 0, &edge_e[i] );
    1787       94890 :             move32();
    1788             :         }
    1789             : 
    1790             :         // edge[i] /= i + 1;
    1791       63260 :         edge[i] = BASOP_Util_Divide3232_Scale_newton( edge[i], add( i, 1 ), &L_temp_e );
    1792       63260 :         move32();
    1793       63260 :         edge_e[i] = add( L_temp_e, sub( edge_e[i], 31 ) );
    1794       63260 :         move16();
    1795             : 
    1796             :         // if ( edge[i] < edge_min )
    1797       63260 :         IF( BASOP_Util_Cmp_Mant32Exp( edge[i], edge_e[i], edge_min, *edge_min_e ) < 0 )
    1798             :         {
    1799       56744 :             edge_min = edge[i];
    1800       56744 :             move32();
    1801       56744 :             *edge_min_e = edge_e[i];
    1802       56744 :             move16();
    1803             :         }
    1804             :     }
    1805             : 
    1806       15815 :     return edge_min; // Q31
    1807             : }

Generated by: LCOV version 1.14