LCOV - code coverage report
Current view: top level - lib_rend - ivas_dirac_dec_binaural_functions_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main -- dec/rend @ 633e3f2e309758d10805ef21e0436356fe719b7a Lines: 2614 3010 86.8 %
Date: 2025-08-23 01:22:27 Functions: 26 26 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 "options.h"
      35             : #include <assert.h>
      36             : #include <math.h>
      37             : #include "prot_fx.h"
      38             : #include "ivas_prot_rend_fx.h"
      39             : #include "ivas_cnst.h"
      40             : #include "ivas_rom_binauralRenderer.h"
      41             : #include "ivas_rom_binaural_crend_head.h"
      42             : #include "ivas_rom_rend.h"
      43             : #include "ivas_rom_com.h"
      44             : #include "ivas_prot_fx.h"
      45             : 
      46             : #include "wmc_auto.h"
      47             : 
      48             : Word16 slot_fx[4] = { 32767, 16384, 10922, 8192 };
      49             : 
      50             : /*-------------------------------------------------------------------------
      51             :  * Local constants
      52             :  *------------------------------------------------------------------------*/
      53             : 
      54             : #define CLDFB_HALF_BIN_FREQUENCY_OFFSET         0.5f
      55             : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN        ( 2.0f )
      56             : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f )
      57             : #define SBA_CARDI_TARGET_ENERGY_GAIN            0.5f
      58             : 
      59             : #define STEREO_PREPROCESS_IIR_FACTOR     ( 0.9f )
      60             : #define STEREO_PREPROCESS_IIR_FACTOR_Q15 ( 29491 )
      61             : /* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */
      62             : #define ADAPT_HTPROTO_IIR_FAC 0.81450625f
      63             : 
      64             : #define ADAPT_HTPROTO_ILD_LIM_DB0  1.0f
      65             : #define ADAPT_HTPROTO_ILD_LIM_DB1  4.0f
      66             : #define ADAPT_HTPROTO_ROT_LIM_0    0.4f
      67             : #define ADAPT_HTPROTO_ROT_LIM_0_FX 429496736  // Q30
      68             : #define TWO_POINT_FIVE_IN_Q13      20480      // Q13
      69             : #define ADAPT_HTPROTO_IIR_FAC_FX   26689      // Q15
      70             : #define LOG_10_BASE_2_Q29          1783446528 // Q29
      71             : #define TAN_30_FX                  17157      // Q15
      72             : #define INV_TAN30_FX               28377      // Q14
      73             : #define EPSILON_MANT               1180591621 /* 1e-12 = 0.5497558*(2^-39) in Q70 */
      74             : #define EPSILON_EXP                ( -39 )
      75             : #define ONE_DIV_EPSILON_MANT       1953125000 /* 1e+12 = 0.9094947*(2^40) */
      76             : #define ONE_DIV_EPSILON_EXP        ( 40 )
      77             : #define ADAPT_HTPROTO_ROT_LIM_1    0.8f
      78             : 
      79             : #define MAX_GAIN_CACHE_SIZE ( ( MASA_MAXIMUM_DIRECTIONS * 3 ) + MAX_NUM_OBJECTS ) /* == different calls to get gains */
      80             : 
      81             : typedef struct hrtfGainCache
      82             : {
      83             :     Word16 azi;
      84             :     Word16 ele;
      85             : 
      86             :     Word32 shVec_fx[HRTF_SH_CHANNELS];
      87             : 
      88             : } PARAMBIN_HRTF_GAIN_CACHE;
      89             : 
      90             : typedef struct parambin_rend_config_data
      91             : {
      92             :     Word16 separateCenterChannelRendering;
      93             :     IVAS_FORMAT ivas_format;
      94             :     MC_MODE mc_mode;
      95             :     Word32 ivas_total_brate;
      96             :     Word16 nchan_transport;
      97             :     Word32 qualityBasedSmFactor_fx; /* Q31 */
      98             :     Word16 processReverb;
      99             :     ISM_MODE ism_mode;
     100             : } PARAMBIN_REND_CONFIG, *PARAMBIN_REND_CONFIG_HANDLE;
     101             : 
     102             : 
     103             : /*-------------------------------------------------------------------------
     104             :  * Local function prototypes
     105             :  *------------------------------------------------------------------------*/
     106             : 
     107             : static void ivas_dirac_dec_binaural_internal_fx( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_f[] /*Q11*/, const Word16 nchan_transport, const Word16 subframe );
     108             : 
     109             : static void ivas_dirac_dec_decorrelate_slot_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const Word16 num_freq_bands, const Word16 slot, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME] /*q_inp*/[CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, Word32 decRe[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 decIm[] /*q_inp*/[CLDFB_NO_CHANNELS_MAX] );
     110             : 
     111             : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 subframe, Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, Word32 *IIReneLimiter, Word16 q );
     112             : 
     113             : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, Word32 Rmat[3][3], const Word16 subframe, const Word16 isHeadtracked, const Word32 *subFrameTotalEne, Word16 *subFrameTotalEne_e, const Word32 *IIReneLimiter, const MASA_ISM_DATA_HANDLE hMasaIsmData );
     114             : 
     115             : static void ivas_dirac_dec_binaural_determine_processing_matrices_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const Word16 max_band_decorr, Word32 Rmat[3][3] /*Q30*/, const Word16 subframe, const Word16 isHeadtracked, const Word16 nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData );
     116             : 
     117             : static void ivas_dirac_dec_binaural_process_output_fx( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], Word32 *output_fx[] /*q_out*/, Word16 *q_out, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, const Word16 q_inp, const Word16 max_band_decorr, const Word16 numInChannels, const Word16 processReverb, const Word16 subframe, const Word16 q_mat, Word32 outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word16 *Q_inp_mix, const Word8 recompute );
     118             : 
     119             : static void adaptTransportSignalsHeadtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX] /*q_inp*/, Word16 q_inp, const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ );
     120             : 
     121             : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( COMBINED_ORIENTATION_HANDLE hHeadTrackData, Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const Word16 nBins, const Word16 nSlots, Word32 Rmat[3][3] /*Q30*/ );
     122             : 
     123             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     124             : static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 useCachedValue, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
     125             : #else
     126             : static void hrtfShGetHrtf_fx( const Word16 bin, const Word16 aziDeg, const Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 useCachedValue );
     127             : #endif
     128             : 
     129             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     130             : static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3] /*Q30*/, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
     131             : #else
     132             : static void getDirectPartGains_fx( const Word16 bin, Word16 aziDeg, Word16 eleDeg, Word32 *lRealp, Word32 *lImagp, Word32 *rRealp, Word32 *rImagp, const UWord8 renderStereoOutputInsteadOfBinaural, Word32 Rmat[3][3] /*Q30*/, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const Word16 isHeadtracked );
     133             : #endif
     134             : 
     135             : static void ivas_masa_ext_rend_parambin_internal_fx( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, Word32 *output_fx[] /*Q11*/, const Word16 subframe, const SPLIT_REND_WRAPPER *hSplitRendWrapper, Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] );
     136             : 
     137             : static void formulate2x2MixingMatrix_fx( Word32 Ein1_fx /*q_Ein*/, Word32 Ein2_fx /*q_Ein*/, Word16 q_Ein, Word32 CinRe_fx /*q_Cin*/, Word32 CinIm_fx /*q_Cin*/, Word16 q_Cin, Word32 Eout1_fx /*q_Eout*/, Word32 Eout2_fx /*q_Eout*/, Word16 q_Eout, Word32 CoutRe_fx /*q_Cout*/, Word32 CoutIm_fx /*q_Cout*/, Word16 q_Cout, Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*Q31*/, Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_M*/, Word16 *q_M, const Word16 regularizationFactor_fx /*Q14*/ );
     138             : 
     139             : static void matrixMul_fx( Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/, Word16 *q_A, Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/, Word16 *q_B, Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/, Word16 *q_out );
     140             : 
     141             : static void matrixTransp2Mul_fx(
     142             :     Word32 Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/,
     143             :     Word32 Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_A*/,
     144             :     Word16 *q_A,
     145             :     Word32 Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/,
     146             :     Word32 Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_B*/,
     147             :     Word16 *q_B,
     148             :     Word32 Ascale,
     149             :     Word32 Bscale,
     150             :     Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/,
     151             :     Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] /*q_out*/,
     152             :     Word16 *q_out );
     153             : 
     154             : 
     155             : /*-------------------------------------------------------------------------
     156             :  * ivas_dirac_dec_init_binaural_data()
     157             :  *
     158             :  * Initialize parametric binaural renderer
     159             :  *------------------------------------------------------------------------*/
     160             : 
     161         462 : ivas_error ivas_dirac_dec_init_binaural_data_fx(
     162             :     Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure                  */
     163             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     164             :     HRTFS_PARAMBIN_HANDLE *phHrtfParambin /* i  : HRTF structure for rendering            */
     165             : #else
     166             :     HRTFS_PARAMBIN_HANDLE hHrtfParambin /* i  : HRTF structure for rendering            */
     167             : #endif
     168             : )
     169             : {
     170             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
     171             :     Word16 nBins;
     172             :     Word32 output_Fs;
     173             :     RENDERER_TYPE renderer_type;
     174             :     Word16 j, k, bin;
     175             :     Word32 binCenterFreq_fx;
     176             :     Word16 tmpFloat_fx;
     177             :     Word16 tmp;
     178             :     Word16 tmp_e;
     179             :     Word16 tmp2;
     180             :     ivas_error error;
     181             : 
     182             :     Word16 num_poses, pos_idx;
     183             : #ifdef FIX_587_DEFAULT_REVERB
     184             :     const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics;
     185             : #endif
     186             : 
     187         462 :     num_poses = 1;
     188         462 :     IF( st_ivas->hSplitBinRend != NULL )
     189             :     {
     190           0 :         num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses;
     191           0 :         move16();
     192             :     }
     193             : 
     194         924 :     FOR( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
     195             :     {
     196         462 :         hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
     197         462 :         move32();
     198             : 
     199         462 :         IF( hDiracDecBin == NULL )
     200             :         {
     201         462 :             IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL )
     202             :             {
     203           0 :                 return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " );
     204             :             }
     205             : 
     206         462 :             hDiracDecBin->hTdDecorr = NULL;
     207         462 :             hDiracDecBin->hReverb = NULL;
     208         462 :             hDiracDecBin->h_freq_domain_decorr_ap_params = NULL;
     209         462 :             hDiracDecBin->h_freq_domain_decorr_ap_state = NULL;
     210             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     211         462 :             hDiracDecBin->phHrtfParambin = NULL;
     212             : #endif
     213             :         }
     214             : 
     215         462 :         output_Fs = st_ivas->hDecoderConfig->output_Fs;
     216         462 :         move32();
     217         462 :         nBins = st_ivas->hSpatParamRendCom->num_freq_bands;
     218         462 :         move16();
     219         462 :         renderer_type = st_ivas->renderer_type;
     220         462 :         move32();
     221             : 
     222        1386 :         FOR( j = 0; j < BINAURAL_CHANNELS; j++ )
     223             :         {
     224        6468 :             FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ )
     225             :             {
     226        5544 :                 set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins );
     227        5544 :                 set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins );
     228        5544 :                 set16_fx( hDiracDecBin->processMtxRePrev_fx[j][k], 0, nBins );
     229        5544 :                 set16_fx( hDiracDecBin->processMtxImPrev_fx[j][k], 0, nBins );
     230             :             }
     231             : 
     232        2772 :             FOR( k = 0; k < BINAURAL_CHANNELS; k++ )
     233             :             {
     234        1848 :                 set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins );
     235        1848 :                 set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins );
     236             :             }
     237         924 :             set32_fx( hDiracDecBin->ChEnePrev_fx[j], 0, nBins );
     238         924 :             set32_fx( hDiracDecBin->ChEneOutPrev_fx[j], 0, nBins );
     239         924 :             set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins );
     240         924 :             set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins );
     241             :         }
     242         462 :         set32_fx( hDiracDecBin->ChCrossRePrev_fx, 0, nBins );
     243         462 :         set32_fx( hDiracDecBin->ChCrossImPrev_fx, 0, nBins );
     244         462 :         set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins );
     245         462 :         set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins );
     246         462 :         set32_fx( hDiracDecBin->ChCrossReOutPrev_fx, 0, nBins );
     247         462 :         set32_fx( hDiracDecBin->ChCrossImOutPrev_fx, 0, nBins );
     248         462 :         set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins );
     249         462 :         set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins );
     250         462 :         hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0;
     251         462 :         move16();
     252             : 
     253         462 :         hDiracDecBin->q_processMtx = Q15;
     254         462 :         hDiracDecBin->q_processMtxSCCR = Q15;
     255         462 :         hDiracDecBin->q_processMtxPrev = Q15;
     256         462 :         hDiracDecBin->q_processMtxPrevSCCR = Q15;
     257         462 :         hDiracDecBin->q_processMtxDec = Q15;
     258         462 :         hDiracDecBin->q_processMtxDecPrev = Q15;
     259         462 :         move16();
     260         462 :         move16();
     261         462 :         move16();
     262         462 :         move16();
     263         462 :         move16();
     264         462 :         move16();
     265             : 
     266       22222 :         FOR( bin = 0; bin < nBins; bin++ )
     267             :         {
     268       21760 :             binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/
     269             :             /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */
     270       21760 :             tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, 2700 << Q15, &tmp_e );
     271       21760 :             IF( tmp_e < 0 )
     272             :             {
     273        1386 :                 tmp = shl( tmp, tmp_e ); /*q15*/
     274        1386 :                 tmp_e = 0;
     275        1386 :                 move16();
     276             :             }
     277       21760 :             tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/;                                                                                                                                                           /*Q15-tmp_e*/
     278       21760 :             tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 ); /* Q15 */                                                                                                                                                                          //*binCenterFreq_fx * EVS_PI / 550.0f*/
     279       21760 :             hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/ /* Q30 */
     280       21760 :             hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 );                                                                                                                                                                          /* Q31 */
     281       21760 :             move32();
     282       21760 :             move32();
     283             :         }
     284             : 
     285        4620 :         FOR( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ )
     286             :         {
     287        4158 :             hDiracDecBin->diffuseFieldCoherenceX_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceX_fx[bin] );
     288        4158 :             hDiracDecBin->diffuseFieldCoherenceY_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceY_fx[bin] );
     289        4158 :             hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] = L_add( hDiracDecBin->diffuseFieldCoherence_fx[bin], diffuseFieldCoherenceDifferenceZ_fx[bin] );
     290        4158 :             move32();
     291        4158 :             move32();
     292        4158 :             move32();
     293             :         }
     294             : 
     295         462 :         IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */
     296             :         {
     297         173 :             set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
     298         173 :             hDiracDecBin->q_earlyPartEneCorrection = Q28;
     299         173 :             move16();
     300         173 :             hDiracDecBin->hReverb = NULL;
     301             :         }
     302         289 :         ELSE IF( EQ_32( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */
     303             :         {
     304             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     305             : #ifdef NONBE_FIX_981_PARAMBIN_DEFAULT_EARLY_PART
     306         278 :             IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) )
     307             :             {
     308         163 :                 Copy32( ( *phHrtfParambin )->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
     309             : #ifdef FIX_587_DEFAULT_REVERB
     310         163 :                 pRoomAcoustics = NULL;
     311             : #endif
     312             :             }
     313             :             ELSE
     314             :             {
     315         115 :                 set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
     316             : #ifdef FIX_587_DEFAULT_REVERB
     317         115 :                 pRoomAcoustics = &( st_ivas->hRenderConfig->roomAcoustics );
     318             : #endif
     319             :             }
     320             : #else
     321             :             Copy32( ( *phHrtfParambin )->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
     322             : #endif
     323             : #else
     324             :             Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
     325             : #endif
     326         278 :             hDiracDecBin->q_earlyPartEneCorrection = Q28;
     327         278 :             move16();
     328             :             /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */
     329         278 :             test();
     330         278 :             test();
     331         278 :             IF( hDiracDecBin->hReverb != NULL && ( ( NE_16( hDiracDecBin->hReverb->numBins, nBins ) ) ||
     332             :                                                    ( NE_16( hDiracDecBin->hReverb->blockSize, CLDFB_SLOTS_PER_SUBFRAME ) ) ) )
     333             :             {
     334           0 :                 ivas_binaural_reverb_close_fx( &( hDiracDecBin->hReverb ) );
     335             :             }
     336             : 
     337         278 :             IF( hDiracDecBin->hReverb == NULL && EQ_16( pos_idx, 0 ) ) /* open reverb only for the main direction */
     338             :             {
     339             : 
     340             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     341             : #ifdef FIX_587_DEFAULT_REVERB
     342             : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
     343         278 :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx, hDiracDecBin->earlyPartEneCorrection_fx ) ), IVAS_ERR_OK ) )
     344             : #else
     345             :                 if ( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
     346             : #endif
     347             : #else
     348             :                 if ( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( st_ivas->hRenderConfig->roomAcoustics ), output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
     349             : #endif
     350             : #else
     351             :                 if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, st_ivas->hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( st_ivas->hRenderConfig->roomAcoustics ), output_Fs, st_ivas->hHrtfParambin->parametricReverberationTimes_fx, st_ivas->hHrtfParambin->parametricReverberationEneCorrections_fx ) ) != IVAS_ERR_OK )
     352             : #endif
     353             :                 {
     354           0 :                     return error;
     355             :                 }
     356             :             }
     357             :         }
     358          11 :         ELSE IF( EQ_32( renderer_type, RENDERER_STEREO_PARAMETRIC ) )
     359             :         {
     360          11 :             set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
     361          11 :             hDiracDecBin->q_earlyPartEneCorrection = Q28;
     362          11 :             hDiracDecBin->hReverb = NULL;
     363          11 :             hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1;
     364          11 :             move16();
     365          11 :             move16();
     366             :         }
     367             :         ELSE /* Not valid renderer type for this renderer */
     368             :         {
     369           0 :             assert( false );
     370             :         }
     371             : 
     372         462 :         hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */
     373             : 
     374         462 :         if ( hDiracDecBin->hTdDecorr == NULL )
     375             :         {
     376         462 :             hDiracDecBin->useTdDecorr = 0;
     377         462 :             move16();
     378             :         }
     379             : 
     380         462 :         IF( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL )
     381             :         {
     382           0 :             ivas_dirac_dec_decorr_close_fx( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state );
     383             :         }
     384             : 
     385         462 :         if ( pos_idx == 0 ) /* open decorrelator only for the main direction */
     386             :         {
     387         462 :             IF( NE_32( ( error = ivas_td_decorr_reconfig_dec( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->hDecoderConfig->output_Fs, &( hDiracDecBin->hTdDecorr ), &( hDiracDecBin->useTdDecorr ) ) ), IVAS_ERR_OK ) )
     388             :             {
     389           0 :                 return error;
     390             :             }
     391             : 
     392         462 :             test();
     393         462 :             test();
     394         462 :             IF( !hDiracDecBin->useTdDecorr && !( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) )
     395             :             {
     396             :                 Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX];
     397         111 :                 ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins );
     398             : 
     399         111 :                 IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ),
     400             :                                                                     &( hDiracDecBin->h_freq_domain_decorr_ap_state ),
     401             :                                                                     nBins,
     402             :                                                                     BINAURAL_CHANNELS,
     403             :                                                                     BINAURAL_CHANNELS,
     404             :                                                                     DIRAC_SYNTHESIS_PSD_LS,
     405             :                                                                     frequency_axis_fx,
     406             :                                                                     BINAURAL_CHANNELS,
     407             :                                                                     output_Fs ) ),
     408             :                            IVAS_ERR_OK ) )
     409             :                 {
     410           0 :                     return error;
     411             :                 }
     412             :             }
     413             :         }
     414             :         else
     415             :         {
     416           0 :             hDiracDecBin->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; /* copy the flag, but the implementation re-uses the decorrelated signal */
     417             :         }
     418             : 
     419         462 :         hDiracDecBin->reqularizationFactor_fx = configure_reqularization_factor_fx( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate ); /* Q14 */
     420         462 :         move16();
     421             : 
     422             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
     423         462 :         hDiracDecBin->phHrtfParambin = phHrtfParambin;
     424             : #endif
     425             : 
     426         462 :         st_ivas->hDiracDecBin[pos_idx] = hDiracDecBin;
     427             :     }
     428             : 
     429             :     /* allocate transport channels */
     430         462 :     IF( st_ivas->hTcBuffer == NULL )
     431             :     {
     432             :         Word16 nchan_to_allocate;
     433             :         Word16 n_samples_granularity;
     434             : 
     435          65 :         nchan_to_allocate = 2 * BINAURAL_CHANNELS;
     436          65 :         move16();
     437          65 :         if ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     438             :         {
     439             : #ifdef FIX_1222_OMASA_DEC_CHANNEL_BUFFERS
     440          15 :             nchan_to_allocate = add( BINAURAL_CHANNELS, st_ivas->nchan_ism );
     441             : #else
     442             :             nchan_to_allocate = 2 * BINAURAL_CHANNELS + 2;
     443             :             move16();
     444             : #endif
     445             :         }
     446             : 
     447          65 :         n_samples_granularity = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
     448          65 :         test();
     449          65 :         test();
     450          65 :         IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) )
     451             :         {
     452           1 :             n_samples_granularity = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); /* Use the same granularity as tdrend */
     453             :         }
     454             : 
     455          65 :         IF( NE_32( ( error = ivas_jbm_dec_tc_buffer_open_fx( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels_fx( st_ivas ), nchan_to_allocate, nchan_to_allocate, n_samples_granularity ) ), IVAS_ERR_OK ) )
     456             :         {
     457           0 :             return error;
     458             :         }
     459             :     }
     460         462 :     return IVAS_ERR_OK;
     461             : }
     462             : 
     463             : /*-------------------------------------------------------------------------
     464             :  * ivas_dirac_dec_close_binaural_data()
     465             :  *
     466             :  * Close parametric binaural renderer
     467             :  *------------------------------------------------------------------------*/
     468        3167 : void ivas_dirac_dec_close_binaural_data(
     469             :     DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle  */
     470             : )
     471             : {
     472             :     int16_t pos_idx;
     473        3167 :     test();
     474        3167 :     IF( hBinaural == NULL || *hBinaural == NULL )
     475             :     {
     476        2693 :         return;
     477             :     }
     478             : 
     479        4266 :     FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
     480             :     {
     481        3792 :         IF( hBinaural[pos_idx] != NULL )
     482             :         {
     483         474 :             IF( hBinaural[pos_idx]->hReverb != NULL )
     484             :             {
     485         278 :                 ivas_binaural_reverb_close_fx( &( hBinaural[pos_idx]->hReverb ) );
     486             :             }
     487             : 
     488         474 :             ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) );
     489             : 
     490         474 :             if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL )
     491             :             {
     492         128 :                 ivas_dirac_dec_decorr_close_fx( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) );
     493             :             }
     494             : 
     495         474 :             free( hBinaural[pos_idx] );
     496         474 :             hBinaural[pos_idx] = NULL;
     497             :         }
     498             :     }
     499             : 
     500         474 :     return;
     501             : }
     502             : /*-------------------------------------------------------------------------
     503             :  * ivas_dirac_dec_binaural_copy_hrtfs()
     504             :  *
     505             :  * Temporary function for copying HRTF data from rom tables if no binary
     506             :  * file was given.
     507             :  *------------------------------------------------------------------------*/
     508        1628 : ivas_error ivas_dirac_dec_binaural_copy_hrtfs_fx(
     509             :     HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */
     510             : )
     511             : {
     512             :     Word16 i, j;
     513        1628 :     test();
     514        1628 :     IF( hHrtfParambin != NULL && *hHrtfParambin != NULL )
     515             :     {
     516             :         /* Tables already loaded from file */
     517        1521 :         return IVAS_ERR_OK;
     518             :     }
     519             :     ELSE
     520             :     {
     521             :         /* Initialise tables from ROM */
     522             :         HRTFS_PARAMBIN *hrtfParambin;
     523         107 :         IF( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL )
     524             :         {
     525           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" );
     526             :         }
     527         321 :         FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
     528             :         {
     529        3638 :             FOR( j = 0; j < HRTF_SH_CHANNELS; j++ )
     530             :             {
     531        3424 :                 Copy( hrtfShCoeffsRe_fx[i][j], hrtfParambin->hrtfShCoeffsRe_fx[i][j], HRTF_NUM_BINS ); /*Q14*/
     532        3424 :                 Copy( hrtfShCoeffsIm_fx[i][j], hrtfParambin->hrtfShCoeffsIm_fx[i][j], HRTF_NUM_BINS ); /*Q14*/
     533             :             }
     534             :         }
     535         107 :         Copy32( parametricReverberationTimes_fx, hrtfParambin->parametricReverberationTimes_fx, CLDFB_NO_CHANNELS_MAX );                   /*Q26*/
     536         107 :         Copy32( parametricReverberationEneCorrections_fx, hrtfParambin->parametricReverberationEneCorrections_fx, CLDFB_NO_CHANNELS_MAX ); /*Q31*/
     537         107 :         Copy32( parametricEarlyPartEneCorrection_fx, hrtfParambin->parametricEarlyPartEneCorrection_fx, CLDFB_NO_CHANNELS_MAX );           /*Q28*/
     538         107 :         *hHrtfParambin = hrtfParambin;
     539             :     }
     540             : 
     541         107 :     return IVAS_ERR_OK;
     542             : }
     543             : 
     544             : 
     545             : /*-------------------------------------------------------------------------
     546             :  * void ivas_dirac_dec_binaural_render_fx()
     547             :  *
     548             :  *
     549             :  *------------------------------------------------------------------------*/
     550       72073 : void ivas_dirac_dec_binaural_render_fx(
     551             :     Decoder_Struct *st_ivas,      /* i/o: IVAS decoder handle                      */
     552             :     const UWord16 nSamplesAsked,  /* i  : number of CLDFB slots requested          */
     553             :     UWord16 *nSamplesRendered,    /* o  : number of CLDFB slots rendered           */
     554             :     UWord16 *nSamplesAvailable,   /* o  : number of CLDFB slots still to render    */
     555             :     const Word16 nchan_transport, /* i  : number of transport channels             */
     556             :     Word32 *output_f[]            /* o  : rendered time signal, Q11                */
     557             : )
     558             : {
     559             :     Word16 slots_to_render, first_sf, last_sf, subframe_idx;
     560             :     UWord16 slot_size, ch;
     561             :     UWord16 nchan_out;
     562             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
     563             :     Word32 *output_fx_local[MAX_OUTPUT_CHANNELS];
     564             :     Word32 output_fx_local_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k];
     565             :     Word16 output_length;
     566             : 
     567       72073 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
     568       72073 :     nchan_out = BINAURAL_CHANNELS;
     569       72073 :     move16();
     570      216219 :     FOR( ch = 0; ch < nchan_out; ch++ )
     571             :     {
     572      144146 :         output_fx_local[ch] = output_fx_local_buff[ch];
     573             :     }
     574       72073 :     slot_size = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
     575             : 
     576             :     /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
     577       72073 :     slots_to_render = s_min( sub( hSpatParamRendCom->num_slots, hSpatParamRendCom->slots_rendered ), idiv1616( (Word16) nSamplesAsked, (Word16) slot_size ) );
     578       72073 :     *nSamplesRendered = imult1616( slots_to_render, slot_size );
     579       72073 :     move16();
     580       72073 :     first_sf = hSpatParamRendCom->subframes_rendered;
     581       72073 :     last_sf = first_sf;
     582       72073 :     move16();
     583       72073 :     move16();
     584             : 
     585      347398 :     WHILE( slots_to_render > 0 )
     586             :     {
     587      275325 :         slots_to_render = sub( slots_to_render, hSpatParamRendCom->subframe_nbslots[last_sf] );
     588      275325 :         last_sf = add( last_sf, 1 );
     589             :     }
     590             : 
     591       72073 :     output_length = 0;
     592       72073 :     move16();
     593      347398 :     FOR( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     594             :     {
     595      275325 :         Word16 n_samples_sf = imult1616( slot_size, hSpatParamRendCom->subframe_nbslots[subframe_idx] );
     596      275325 :         ivas_dirac_dec_binaural_internal_fx( st_ivas, st_ivas->hCombinedOrientationData, output_fx_local, nchan_transport, subframe_idx );
     597             : 
     598      825975 :         FOR( ch = 0; ch < nchan_out; ch++ )
     599             :         {
     600      550650 :             output_fx_local[ch] += n_samples_sf;
     601             :         }
     602             : 
     603      275325 :         output_length = add( output_length, n_samples_sf );
     604             : 
     605             :         /* update combined orientation access index */
     606      275325 :         ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_sf );
     607             :     }
     608             : 
     609      216219 :     FOR( ch = 0; ch < nchan_out; ch++ )
     610             :     {
     611      144146 :         Copy32( output_fx_local_buff[ch], output_f[ch], output_length );
     612             :     }
     613             : 
     614       72073 :     IF( EQ_16( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->num_slots ) )
     615             :     {
     616       68602 :         hSpatParamRendCom->dirac_read_idx = add( hSpatParamRendCom->dirac_read_idx, DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length;
     617       68602 :         move16();
     618             :     }
     619             : 
     620       72073 :     *nSamplesAvailable = imult1616( sub( hSpatParamRendCom->num_slots, hSpatParamRendCom->slots_rendered ), slot_size );
     621       72073 :     move16();
     622             : 
     623       72073 :     return;
     624             : }
     625             : 
     626             : /*-------------------------------------------------------------------------
     627             :  * ivas_dirac_dec_binaural_sba_gain()
     628             :  *
     629             :  * loudness correction for parametric binaural renderer
     630             :  *------------------------------------------------------------------------*/
     631       45535 : void ivas_dirac_dec_binaural_sba_gain_fx(
     632             :     Word32 *output[],            /* i/o: synthesized core-coder transport channels/DirAC output, inp Qx, out Qx-1    */
     633             :     const Word16 nchan_remapped, /* i  : num channels after remapping of TCs                                         */
     634             :     const Word16 output_frame    /* i  : output frame length                                                         */
     635             : )
     636             : {
     637             :     Word16 n;
     638             :     Word16 gain; /*Q-14*/
     639             : 
     640       45535 :     IF( EQ_16( nchan_remapped, 1 ) )
     641             :     {
     642       16159 :         gain = 23681; /*Q14*/
     643       16159 :         move16();
     644             :     }
     645             :     ELSE
     646             :     {
     647       29376 :         gain = 22376; /*Q14*/
     648       29376 :         move16();
     649             :     }
     650             : 
     651      120446 :     FOR( n = 0; n < nchan_remapped; n++ )
     652             :     {
     653       74911 :         v_multc_fixed_16( output[n], gain, output[n], output_frame ); /* Qx to Qx-1*/
     654             :     }
     655             : 
     656       45535 :     return;
     657             : }
     658             : 
     659             : 
     660             : /*-------------------------------------------------------------------------
     661             :  * Local functions
     662             :  *------------------------------------------------------------------------*/
     663      275325 : static void ivas_dirac_dec_binaural_internal_fx(
     664             :     Decoder_Struct *st_ivas,
     665             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
     666             :     Word32 *output_fx[], /*Q11*/
     667             :     const Word16 nchan_transport,
     668             :     const Word16 subframe )
     669             : {
     670      275325 :     Word16 q_input = 11;
     671      275325 :     move16();
     672      275325 :     IF( st_ivas->hSCE[0] )
     673             :     {
     674      161083 :         Word16 shift = getScaleFactor32( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel, FFTCLDFBLEN );
     675      161083 :         IF( LT_16( sub( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp, shift ), 4 ) )
     676             :         {
     677       11702 :             shift = sub( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp, 4 );
     678             :         }
     679      161083 :         scale_sig32( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevel, FFTCLDFBLEN, shift );
     680      161083 :         st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp = sub( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->cngNoiseLevelExp, shift );
     681      161083 :         move16();
     682             :     }
     683             :     Word16 q_cldfb[6][CLDFB_SLOTS_PER_SUBFRAME];
     684     1927275 :     FOR( Word16 ind = 0; ind < 6; ind++ )
     685             :     {
     686     8259750 :         FOR( Word16 ind2 = 0; ind2 < 4; ind2++ )
     687             :         {
     688     6607800 :             q_cldfb[ind][ind2] = q_input;
     689     6607800 :             move16();
     690             :         }
     691             :     }
     692      275325 :     Word16 q_cldfb_temp = sub( q_input, 1 );
     693             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
     694             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
     695             :     PARAMBIN_REND_CONFIG config_data;
     696             :     Word16 slot, ch, numInChannels;
     697             :     Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     698             :     Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     699             :     Word16 nchanSeparateChannels;
     700             :     Word32 Rmat_fx[3][3];
     701             :     Word16 max_band_decorr;
     702             :     DIFFUSE_DISTRIBUTION_DATA diffuseDistData;
     703             :     Word16 nBins, offsetSamples;
     704             :     Word16 i, j;
     705             :     Word16 q_mat, q_out;
     706             :     Word16 pos_idx;
     707             :     MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
     708             :     Word32 tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     709             :     Word32 tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     710             :     /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */
     711             :     Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     712             :     Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     713             :     Word32 decorrRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     714             :     Word32 decorrIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     715             :     Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX];
     716             :     Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX];
     717             :     Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX];
     718             :     Word16 Q_inp_mix;
     719             : 
     720      275325 :     hDiracDecBin = st_ivas->hDiracDecBin[0];
     721      275325 :     assert( hDiracDecBin );
     722      275325 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
     723      275325 :     nBins = hSpatParamRendCom->num_freq_bands;
     724      275325 :     move16();
     725      275325 :     offsetSamples = imult1616( hSpatParamRendCom->slots_rendered, nBins );
     726             :     Word32 tmp_arr[CLDFB_NO_CHANNELS_MAX];
     727             :     /* Setup internal config */
     728      275325 :     config_data.separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled;
     729      275325 :     move16();
     730      275325 :     config_data.ivas_format = st_ivas->ivas_format;
     731      275325 :     move32();
     732      275325 :     config_data.mc_mode = st_ivas->mc_mode;
     733      275325 :     move32();
     734      275325 :     config_data.ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
     735      275325 :     move32();
     736      275325 :     config_data.nchan_transport = st_ivas->nchan_transport;
     737      275325 :     move16();
     738      275325 :     IF( st_ivas->hMasa != NULL )
     739             :     {
     740       92664 :         config_data.qualityBasedSmFactor_fx = L_deposit_h( st_ivas->hMasa->data.dir_decode_quality_fx ); // Q31
     741             :     }
     742             :     ELSE
     743             :     {
     744      182661 :         config_data.qualityBasedSmFactor_fx = ONE_IN_Q31;
     745             :     }
     746      275325 :     move32();
     747      275325 :     IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
     748             :     {
     749      118411 :         config_data.processReverb = 1;
     750             :     }
     751             :     ELSE
     752             :     {
     753      156914 :         config_data.processReverb = 0;
     754             :     }
     755      275325 :     move16();
     756      275325 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) )
     757             :     {
     758       10085 :         config_data.ism_mode = st_ivas->ism_mode;
     759             :     }
     760             :     ELSE
     761             :     {
     762      265240 :         config_data.ism_mode = ISM_MODE_NONE;
     763             :     }
     764      275325 :     move32();
     765             : 
     766             :     /* The input channel number at this processing function (not nchan_transport) */
     767      275325 :     numInChannels = BINAURAL_CHANNELS;
     768      275325 :     move16();
     769      275325 :     test();
     770      275325 :     test();
     771      275325 :     test();
     772      275325 :     test();
     773      275325 :     test();
     774      275325 :     test();
     775      275325 :     IF( config_data.separateCenterChannelRendering || ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) )
     776             :     {
     777        6795 :         numInChannels = add( numInChannels, 1 );
     778             :     }
     779      268530 :     ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) )
     780             :     {
     781        2958 :         numInChannels = add( numInChannels, st_ivas->nchan_ism );
     782             :     }
     783             : 
     784      275325 :     Rmat_fx[0][0] = ONE_IN_Q30;
     785      275325 :     Rmat_fx[0][1] = 0;
     786      275325 :     Rmat_fx[0][2] = 0;
     787      275325 :     move32();
     788      275325 :     move32();
     789      275325 :     move32();
     790             : 
     791      275325 :     Rmat_fx[1][0] = 0;
     792      275325 :     Rmat_fx[1][1] = ONE_IN_Q30;
     793      275325 :     Rmat_fx[1][2] = 0;
     794      275325 :     move32();
     795      275325 :     move32();
     796      275325 :     move32();
     797             : 
     798      275325 :     Rmat_fx[2][0] = 0;
     799      275325 :     Rmat_fx[2][1] = 0;
     800      275325 :     Rmat_fx[2][2] = ONE_IN_Q30;
     801      275325 :     move32();
     802      275325 :     move32();
     803      275325 :     move32();
     804      275325 :     Word16 ch_len = s_max( 4, numInChannels );
     805     1927275 :     FOR( i = 0; i < 6; i++ )
     806             :     {
     807     8259750 :         FOR( j = 0; j < 4; j++ )
     808             :         {
     809     6607800 :             set32_fx( Cldfb_RealBuffer_in_fx[i][j], 0, 60 );
     810     6607800 :             set32_fx( Cldfb_ImagBuffer_in_fx[i][j], 0, 60 );
     811             :         }
     812             :     }
     813             :     /* CLDFB Analysis of input */
     814     1373046 :     FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
     815             :     {
     816     3350189 :         FOR( ch = 0; ch < numInChannels; ch++ )
     817             :         {
     818     2252468 :             test();
     819     2252468 :             IF( ch == 0 || EQ_16( nchan_transport, 2 ) )
     820             :             {
     821     1757947 :                 q_cldfb[ch][slot] = q_cldfb_temp;
     822     1757947 :                 move16();
     823     1757947 :                 Copy_Scale_sig32( &( st_ivas->hTcBuffer->tc_fx[ch][nBins * slot + offsetSamples] ), tmp_arr, nBins, -1 );
     824     1757947 :                 scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( q_cldfb_temp, st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
     825     1757947 :                 cldfbAnalysis_ts_fx_fixed_q(
     826             :                     tmp_arr,
     827     1757947 :                     Cldfb_RealBuffer_in_fx[ch][slot],
     828     1757947 :                     Cldfb_ImagBuffer_in_fx[ch][slot],
     829     1757947 :                     nBins, st_ivas->cldfbAnaDec[ch], &q_cldfb[ch][slot] );
     830     1757947 :                 scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( q_input, st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
     831     1757947 :                 st_ivas->cldfbAnaDec[ch]->Q_cldfb_state = q_input;
     832     1757947 :                 scale_sig32( Cldfb_RealBuffer_in_fx[ch][slot], nBins, 1 ); // Q6
     833     1757947 :                 scale_sig32( Cldfb_ImagBuffer_in_fx[ch][slot], nBins, 1 ); // Q6
     834     1757947 :                 q_cldfb[ch][slot] = add( q_cldfb[ch][slot], 1 );
     835     1757947 :                 move16();
     836             :             }
     837      494521 :             ELSE IF( EQ_16( config_data.nchan_transport, 2 ) ) /* Stereo signal transmitted as mono with DFT stereo */
     838             :             {
     839             :                 /* At mono input duplicate the channel to dual-mono  */
     840       19396 :                 Copy32( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins );
     841       19396 :                 Copy32( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins );
     842       19396 :                 q_cldfb[1][slot] = q_cldfb[0][slot];
     843       19396 :                 move16();
     844             :             }
     845             :             ELSE /* when nchan_transport == 1 and ch == 1 */
     846             :             {
     847             :                 /* CNA and HB FD-CNG*/
     848      475125 :                 test();
     849      475125 :                 IF( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag )
     850      266722 :                 {
     851             :                     Word16 numCoreBands, b;
     852             : 
     853      266722 :                     numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands;
     854      266722 :                     move16();
     855             : 
     856      800166 :                     generate_masking_noise_dirac_ivas_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
     857             :                                                           st_ivas->cldfbAnaDec[1],
     858      266722 :                                                           &st_ivas->hTcBuffer->tc_fx[nchan_transport][hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->slots_rendered],
     859      266722 :                                                           Cldfb_RealBuffer_in_fx[2][slot], Cldfb_ImagBuffer_in_fx[2][slot],
     860             :                                                           slot,
     861      266722 :                                                           st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
     862      266722 :                                                           ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag,
     863      266722 :                                                           11, &q_cldfb[2][slot] );
     864             : 
     865      800166 :                     generate_masking_noise_dirac_ivas_fx( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
     866             :                                                           st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/
     867             :                                                           NULL,
     868      266722 :                                                           Cldfb_RealBuffer_in_fx[1][slot], Cldfb_ImagBuffer_in_fx[1][slot],
     869             :                                                           slot,
     870      266722 :                                                           st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
     871      266722 :                                                           ( st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == FRAME_NO_DATA || st_ivas->hSCE[0]->hCoreCoder[0]->core_brate == SID_2k40 ) && ( st_ivas->hSCE[0]->hCoreCoder[0]->cng_type == FD_CNG ) && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag,
     872      266722 :                                                           0, &q_cldfb[1][slot] );
     873             : 
     874      266722 :                     scale_sig32( Cldfb_RealBuffer_in_fx[1][slot], CLDFB_NO_CHANNELS_MAX, negate( add( sub( q_cldfb[1][slot], q_input ), 5 ) ) );
     875      266722 :                     scale_sig32( Cldfb_ImagBuffer_in_fx[1][slot], CLDFB_NO_CHANNELS_MAX, negate( add( sub( q_cldfb[1][slot], q_input ), 5 ) ) );
     876             : 
     877             :                     /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/
     878     5468106 :                     FOR( b = 0; b < numCoreBands; b++ )
     879             :                     {
     880     5201384 :                         Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add( L_shr( Cldfb_RealBuffer_in_fx[0][slot][b], add( sub( q_cldfb[0][slot], q_input ), 5 ) ), L_shr( Cldfb_RealBuffer_in_fx[2][slot][b], add( sub( q_cldfb[2][slot], q_input ), 5 ) ) ), 23170 /* INV_SQRT2 in Q15*/ );
     881     5201384 :                         Cldfb_RealBuffer_in_fx[1][slot][b] = Cldfb_RealBuffer_in_fx[0][slot][b];
     882     5201384 :                         move32();
     883     5201384 :                         move32();
     884     5201384 :                         Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( L_add( L_shr( Cldfb_ImagBuffer_in_fx[0][slot][b], add( sub( q_cldfb[0][slot], q_input ), 5 ) ), L_shr( Cldfb_ImagBuffer_in_fx[2][slot][b], add( sub( q_cldfb[2][slot], q_input ), 5 ) ) ), 23170 );
     885     5201384 :                         Cldfb_ImagBuffer_in_fx[1][slot][b] = Cldfb_ImagBuffer_in_fx[0][slot][b];
     886     5201384 :                         move32();
     887     5201384 :                         move32();
     888             :                     }
     889      266722 :                     q_cldfb[1][slot] = sub( q_input, 5 );
     890      266722 :                     q_cldfb[0][slot] = sub( q_input, 5 );
     891      266722 :                     move16();
     892      266722 :                     move16();
     893             :                     /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/
     894    10070258 :                     FOR( ; b < nBins; b++ )
     895             :                     {
     896     9803536 :                         Cldfb_RealBuffer_in_fx[0][slot][b] = Mpy_32_16_1( Cldfb_RealBuffer_in_fx[0][slot][b], 23170 );
     897     9803536 :                         Cldfb_RealBuffer_in_fx[1][slot][b] = L_add( L_add( Cldfb_RealBuffer_in_fx[0][slot][b], L_shr( Cldfb_RealBuffer_in_fx[1][slot][b], 1 ) ), Cldfb_RealBuffer_in_fx[0][slot][b] );
     898     9803536 :                         Cldfb_RealBuffer_in_fx[0][slot][b] = L_add( Cldfb_RealBuffer_in_fx[0][slot][b], L_shr( Cldfb_RealBuffer_in_fx[2][slot][b], 1 ) );
     899             : 
     900     9803536 :                         Cldfb_ImagBuffer_in_fx[0][slot][b] = Mpy_32_16_1( Cldfb_ImagBuffer_in_fx[0][slot][b], 23170 );
     901     9803536 :                         Cldfb_ImagBuffer_in_fx[1][slot][b] = L_add( Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr( Cldfb_ImagBuffer_in_fx[1][slot][b], 1 ) );
     902     9803536 :                         Cldfb_ImagBuffer_in_fx[0][slot][b] = L_add( Cldfb_ImagBuffer_in_fx[0][slot][b], L_shr( Cldfb_ImagBuffer_in_fx[2][slot][b], 1 ) );
     903     9803536 :                         move32();
     904     9803536 :                         move32();
     905     9803536 :                         move32();
     906     9803536 :                         move32();
     907     9803536 :                         move32();
     908     9803536 :                         move32();
     909             :                     }
     910             :                 }
     911             :                 ELSE
     912             :                 {
     913             :                     /* At mono input duplicate the channel to dual-mono, and apply gain
     914             :                     correction to ensure same overall level as in stereo mode  */
     915      208403 :                     v_multc_fixed_16( Cldfb_RealBuffer_in_fx[0][slot], 23170, Cldfb_RealBuffer_in_fx[0][slot], nBins );
     916      208403 :                     v_multc_fixed_16( Cldfb_ImagBuffer_in_fx[0][slot], 23170, Cldfb_ImagBuffer_in_fx[0][slot], nBins );
     917             : 
     918      208403 :                     Copy32( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins );
     919      208403 :                     Copy32( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins );
     920      208403 :                     q_cldfb[1][slot] = q_cldfb[0][slot];
     921      208403 :                     move16();
     922             :                 }
     923             :             }
     924             :         }
     925             : 
     926     1097721 :         IF( hDiracDecBin->useTdDecorr )
     927             :         {
     928     1304919 :             FOR( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ )
     929             :             {
     930      869946 :                 q_cldfb[ch][slot] = sub( q_input, 1 );
     931      869946 :                 move16();
     932             : 
     933      869946 :                 Copy_Scale_sig32( &( st_ivas->hTcBuffer->tc_fx[ch][nBins * slot + offsetSamples] ), tmp_arr, 60, -1 );
     934      869946 :                 scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( sub( q_input, 1 ), st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
     935      869946 :                 st_ivas->cldfbAnaDec[ch]->Q_cldfb_state = sub( q_input, 1 );
     936      869946 :                 move16();
     937             : 
     938      869946 :                 cldfbAnalysis_ts_fx_fixed_q(
     939             :                     tmp_arr,
     940      869946 :                     Cldfb_RealBuffer_in_fx[ch][slot],
     941      869946 :                     Cldfb_ImagBuffer_in_fx[ch][slot],
     942      869946 :                     nBins, st_ivas->cldfbAnaDec[ch], &q_cldfb[ch][slot] );
     943             : 
     944      869946 :                 scale_sig32( st_ivas->cldfbAnaDec[ch]->cldfb_state_fx, sub( st_ivas->cldfbAnaDec[ch]->p_filter_length, st_ivas->cldfbAnaDec[ch]->no_channels ), sub( q_input, st_ivas->cldfbAnaDec[ch]->Q_cldfb_state ) );
     945      869946 :                 st_ivas->cldfbAnaDec[ch]->Q_cldfb_state = q_input;
     946      869946 :                 move16();
     947             : 
     948      869946 :                 test();
     949      869946 :                 test();
     950      869946 :                 IF( EQ_16( config_data.nchan_transport, 1 ) &&
     951             :                     ( EQ_32( config_data.ivas_format, SBA_FORMAT ) || EQ_32( config_data.ivas_format, SBA_ISM_FORMAT ) ) )
     952             :                 {
     953      517124 :                     v_multc_fixed_16( Cldfb_RealBuffer_in_fx[ch][slot], 23170, Cldfb_RealBuffer_in_fx[ch][slot], nBins );
     954      517124 :                     v_multc_fixed_16( Cldfb_ImagBuffer_in_fx[ch][slot], 23170, Cldfb_ImagBuffer_in_fx[ch][slot], nBins );
     955             :                 }
     956             :             }
     957             :         }
     958             :     }
     959             : 
     960      275325 :     test();
     961      275325 :     IF( EQ_32( config_data.ivas_format, SBA_FORMAT ) || EQ_32( config_data.ivas_format, SBA_ISM_FORMAT ) )
     962             :     {
     963      150768 :         hDiracDecBin->hDiffuseDist = &diffuseDistData;
     964      150768 :         ivas_spar_param_to_masa_param_mapping_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe );
     965             : 
     966      150768 :         Scale_sig( st_ivas->hSpar->hFbMixer->cldfb_cross_fade_fx, CLDFB_NO_COL_MAX, Q15 - st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q );
     967      150768 :         st_ivas->hSpar->hFbMixer->cldfb_cross_fade_q = Q15;
     968      150768 :         move16();
     969      150768 :         ivas_sba_prototype_renderer_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_cldfb, subframe );
     970             :     }
     971             : 
     972      275325 :     Word16 q_inp = Q6;
     973      275325 :     move16();
     974     1378793 :     FOR( Word16 cha = 0; cha < ch_len; cha++ )
     975             :     {
     976     5517340 :         FOR( slot = 0; slot < 4; slot++ )
     977             :         {
     978     4413872 :             Word16 q_diff = sub( q_inp, q_cldfb[cha][slot] );
     979     4413872 :             IF( q_diff != 0 )
     980             :             {
     981     3363986 :                 Scale_sig32( Cldfb_RealBuffer_in_fx[cha][slot], 60, q_diff ); // Q6
     982     3363986 :                 Scale_sig32( Cldfb_ImagBuffer_in_fx[cha][slot], 60, q_diff ); // Q6
     983     3363986 :                 q_cldfb[cha][slot] = 6;
     984             :             }
     985     4413872 :             move16();
     986             :         }
     987             :     }
     988             : 
     989      275325 :     test();
     990      275325 :     test();
     991      275325 :     test();
     992      275325 :     IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_16( nchan_transport, 2 ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) )
     993             :     {
     994             :         /* Un-tested function. No test-case is hitting.*/
     995        2418 :         ivas_omasa_preProcessStereoTransportsForMovedObjects_fx( st_ivas, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, &q_inp, nBins, subframe );
     996             :     }
     997             : 
     998      275325 :     IF( hCombinedOrientationData )
     999             :     {
    1000      405888 :         FOR( i = 0; i < 3; i++ )
    1001             :         {
    1002     1217664 :             FOR( j = 0; j < 3; j++ )
    1003             :             {
    1004      913248 :                 Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30//
    1005      913248 :                 move32();
    1006             :             }
    1007             :         }
    1008             : 
    1009      101472 :         IF( EQ_16( nchan_transport, 2 ) )
    1010             :         {
    1011             :             /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
    1012       70800 :             adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
    1013       70800 :             ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
    1014             :         }
    1015             :     }
    1016             : 
    1017      275325 :     test();
    1018             : 
    1019      275325 :     IF( EQ_32( config_data.ivas_format, ISM_FORMAT ) )
    1020             :     {
    1021       31893 :         max_band_decorr = 0;
    1022       31893 :         move16();
    1023             :     }
    1024      243432 :     ELSE IF( hDiracDecBin->useTdDecorr )
    1025             :     {
    1026      109053 :         max_band_decorr = CLDFB_NO_CHANNELS_MAX;
    1027      109053 :         move16();
    1028             :     }
    1029             :     ELSE
    1030             :     {
    1031      134379 :         max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
    1032      134379 :         move16();
    1033             :     }
    1034             : 
    1035      275325 :     ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe,
    1036             :                                                                     subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp );
    1037             : 
    1038      275325 :     ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe,
    1039      275325 :                                                                      hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData );
    1040             : 
    1041      275325 :     nchanSeparateChannels = 0;
    1042      275325 :     move16();
    1043      275325 :     test();
    1044      275325 :     test();
    1045      275325 :     test();
    1046      275325 :     test();
    1047      275325 :     test();
    1048      275325 :     test();
    1049      275325 :     IF( config_data.separateCenterChannelRendering || ( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) )
    1050             :     {
    1051        6795 :         nchanSeparateChannels = 1;
    1052        6795 :         move16();
    1053             :     }
    1054      268530 :     ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && ( EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) )
    1055             :     {
    1056        2958 :         nchanSeparateChannels = (UWord8) st_ivas->nchan_ism;
    1057        2958 :         move16();
    1058             :     }
    1059             : 
    1060      275325 :     ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_fx, subframe, hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData );
    1061             : 
    1062      275325 :     q_inp = Q6;
    1063      275325 :     move16();
    1064      825975 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1065             :     {
    1066      550650 :         st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11;
    1067      550650 :         move16();
    1068             :     }
    1069             : 
    1070      275325 :     q_mat = hDiracDecBin->q_processMtx;
    1071      275325 :     move16();
    1072      275325 :     q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
    1073      275325 :     q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
    1074      275325 :     q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
    1075             : 
    1076      825975 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1077             :     {
    1078     1651950 :         FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
    1079             :         {
    1080     1101300 :             Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );               // scaling to q_mat
    1081     1101300 :             Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );               // scaling to q_mat
    1082     1101300 :             Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) );       // scaling to q_mat
    1083     1101300 :             Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) );       // scaling to q_mat
    1084     1101300 :             Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    1085     1101300 :             Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    1086     1101300 :             Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    1087     1101300 :             Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    1088             :         }
    1089      579708 :         FOR( slot = 0; slot < nchanSeparateChannels; slot++ )
    1090             :         {
    1091       29058 :             Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    1092       29058 :             Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    1093       29058 :             Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    1094       29058 :             Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    1095             :         }
    1096             :     }
    1097      275325 :     hDiracDecBin->q_processMtx = q_mat;
    1098      275325 :     move16();
    1099      275325 :     hDiracDecBin->q_processMtxPrev = q_mat;
    1100      275325 :     move16();
    1101      275325 :     hDiracDecBin->q_processMtxDec = q_mat;
    1102      275325 :     move16();
    1103      275325 :     hDiracDecBin->q_processMtxDecPrev = q_mat;
    1104      275325 :     move16();
    1105             : 
    1106      275325 :     pMultiBinPoseData = NULL;
    1107      275325 :     IF( st_ivas->hSplitBinRend != NULL )
    1108             :     {
    1109           0 :         pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
    1110           0 :         move32();
    1111             :     }
    1112             : 
    1113      275325 :     IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    1114             :     {
    1115           0 :         ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat,
    1116             :                                                    tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
    1117             : 
    1118           0 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1119             :         {
    1120           0 :             FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
    1121             :             {
    1122           0 :                 Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
    1123           0 :                 Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
    1124             :             }
    1125             :         }
    1126             :     }
    1127             :     ELSE
    1128             :     {
    1129      275325 :         ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL,
    1130             :                                                    reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
    1131             :     }
    1132      275325 :     hDiracDecBin->hDiffuseDist = NULL;
    1133             : 
    1134             : 
    1135      275325 :     if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
    1136             :     {
    1137             :         /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
    1138             :         IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
    1139             :         Word32 Rmat_local[3][3];
    1140             : 
    1141           0 :         if ( hCombinedOrientationData )
    1142             :         {
    1143           0 :             Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
    1144           0 :             Copy_Quat_fx( Quaternions_ref, &Quaternions_abs );
    1145           0 :             modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, Q22 );
    1146           0 :             Quaternions_rot.w_fx = L_negate( 12582912 );                                                                 /* signal to use Euler */
    1147           0 :             Quat2EulerDegree_fx( Quaternions_abs, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/
    1148           0 :             Quaternions_abs.w_fx = L_negate( 12582912 );                                                                 /* signal to use Euler */
    1149             : 
    1150           0 :             FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
    1151             :             {
    1152           0 :                 Quaternions_rot.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
    1153           0 :                 Quaternions_rot.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
    1154           0 :                 Quaternions_rot.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
    1155           0 :                 move32();
    1156           0 :                 move32();
    1157           0 :                 move32();
    1158           0 :                 Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot );
    1159           0 :                 modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact );
    1160           0 :                 QuatToRotMat_fx( Quaternions_rot, Rmat_local );
    1161           0 :                 modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( Quaternions_ref->q_fact, 1 ), 32 ), Q30 );
    1162             : 
    1163           0 :                 hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
    1164           0 :                 assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
    1165           0 :                 if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
    1166             :                 {
    1167           0 :                     hDiracDecBin->hDiffuseDist = &diffuseDistData;
    1168             :                 }
    1169             : 
    1170             :                 /* re-use input covariance for the side renderings */
    1171           0 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1172             :                 {
    1173           0 :                     Copy32( st_ivas->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands );
    1174           0 :                     Copy( st_ivas->hDiracDecBin[0]->ChEne_e[ch], hDiracDecBin->ChEne_e[ch], hSpatParamRendCom->num_freq_bands );
    1175             :                 }
    1176           0 :                 Copy32( st_ivas->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands );
    1177           0 :                 Copy32( st_ivas->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands );
    1178           0 :                 Copy( st_ivas->hDiracDecBin[0]->ChCrossRe_e, hDiracDecBin->ChCrossRe_e, hSpatParamRendCom->num_freq_bands );
    1179           0 :                 Copy( st_ivas->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands );
    1180             : 
    1181           0 :                 ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
    1182           0 :                                                                                  hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    1183             :                                                                                  subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, st_ivas->hMasaIsmData );
    1184             : 
    1185           0 :                 ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
    1186           0 :                                                                           hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    1187             :                                                                           nchanSeparateChannels, st_ivas->hMasaIsmData );
    1188             : 
    1189             : 
    1190           0 :                 q_mat = hDiracDecBin->q_processMtx;
    1191           0 :                 move16();
    1192           0 :                 q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
    1193           0 :                 q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
    1194           0 :                 q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
    1195             : 
    1196           0 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1197             :                 {
    1198           0 :                     FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
    1199             :                     {
    1200           0 :                         Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );               // scaling to q_mat
    1201           0 :                         Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );               // scaling to q_mat
    1202           0 :                         Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) );       // scaling to q_mat
    1203           0 :                         Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) );       // scaling to q_mat
    1204           0 :                         Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    1205           0 :                         Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    1206           0 :                         Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    1207           0 :                         Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    1208             :                     }
    1209           0 :                     FOR( slot = 0; slot < nchanSeparateChannels; slot++ )
    1210             :                     {
    1211           0 :                         Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    1212           0 :                         Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    1213           0 :                         Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    1214           0 :                         Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot + BINAURAL_CHANNELS], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    1215             :                     }
    1216             :                 }
    1217           0 :                 hDiracDecBin->q_processMtx = q_mat;
    1218           0 :                 move16();
    1219           0 :                 hDiracDecBin->q_processMtxPrev = q_mat;
    1220           0 :                 move16();
    1221           0 :                 hDiracDecBin->q_processMtxDec = q_mat;
    1222           0 :                 move16();
    1223           0 :                 hDiracDecBin->q_processMtxDecPrev = q_mat;
    1224           0 :                 move16();
    1225             : 
    1226             :                 /* re-use reverb and decorr from main direction for the sides */
    1227           0 :                 ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat,
    1228             :                                                            tmp_Cldfb_out_re, tmp_Cldfb_out_im, reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 0 );
    1229             : 
    1230             :                 /* copy from temporary buffer to the main split rendering buffer */
    1231           0 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1232             :                 {
    1233           0 :                     FOR( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
    1234             :                     {
    1235           0 :                         Copy32( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
    1236           0 :                         Copy32( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural_fx[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
    1237             :                     }
    1238             :                 }
    1239             : 
    1240           0 :                 hDiracDecBin->hDiffuseDist = NULL;
    1241             :             }
    1242             :         }
    1243             :     }
    1244             : 
    1245             :     /* update this counter only after the last rendering of split directions */
    1246             : 
    1247      275325 :     hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] );
    1248      275325 :     hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 );
    1249             : 
    1250      275325 :     move16();
    1251      275325 :     move16();
    1252      825975 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1253             :     {
    1254      550650 :         scale_sig32( output_fx[ch], imult1616( nBins, hSpatParamRendCom->subframe_nbslots[subframe] ), sub( 11, q_out ) ); // Scaling to Q11
    1255      550650 :         scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, sub( Q11, st_ivas->cldfbSynDec[ch]->Q_cldfb_state ) );
    1256      550650 :         st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11;
    1257      550650 :         move16();
    1258             :     }
    1259             : 
    1260      275325 :     return;
    1261             : }
    1262             : 
    1263             : 
    1264      564275 : static void ivas_dirac_dec_decorrelate_slot_fx(
    1265             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    1266             :     const Word16 num_freq_bands,
    1267             :     const Word16 slot,
    1268             :     Word32 inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
    1269             :     Word32 inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
    1270             :     Word16 q_inp,
    1271             :     Word32 decRe[][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
    1272             :     Word32 decIm[][CLDFB_NO_CHANNELS_MAX] /*q_inp*/ )
    1273             : {
    1274             :     Word16 offset, ch, bin;
    1275             :     Word32 onset_filter_fx[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX];                     /* 2 ch, 60 bins */
    1276             :     Word32 decorrelatedFrameInterleaved_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
    1277             :     Word32 protoFrame_fx[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX];                   /* 2 ch, real + imag, 60 bins */
    1278             :     Word16 q_decorrelatedFrameInterleaved, q_protoFrame;
    1279      564275 :     const Word16 protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 };
    1280      564275 :     move16();
    1281      564275 :     q_protoFrame = q_inp;
    1282      564275 :     move16();
    1283             :     /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */
    1284     1692825 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1285             :     {
    1286     1128550 :         offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch );
    1287    54483230 :         FOR( bin = 0; bin < num_freq_bands; bin++ )
    1288             :         {
    1289    53354680 :             protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )] = inRe[ch][slot][bin];           // q_protoFrame
    1290    53354680 :             protoFrame_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )] = inIm[ch][slot][bin]; // q_protoFrame
    1291    53354680 :             move32();
    1292    53354680 :             move32();
    1293             :         }
    1294             :     }
    1295             : 
    1296             :     /* Decorrelate proto signal to decorrelatedFrameInterleaved */
    1297      564275 :     ivas_dirac_dec_decorr_process_fx( num_freq_bands,
    1298             :                                       BINAURAL_CHANNELS,
    1299             :                                       BINAURAL_CHANNELS,
    1300             :                                       DIRAC_SYNTHESIS_PSD_LS,
    1301             :                                       BINAURAL_CHANNELS,
    1302             :                                       protoFrame_fx,
    1303             :                                       q_protoFrame,
    1304             :                                       BINAURAL_CHANNELS,
    1305             :                                       protoIndexDir,
    1306             :                                       decorrelatedFrameInterleaved_fx,
    1307             :                                       &q_decorrelatedFrameInterleaved,
    1308             :                                       onset_filter_fx,
    1309             :                                       hDiracDecBin->h_freq_domain_decorr_ap_params,
    1310             :                                       hDiracDecBin->h_freq_domain_decorr_ap_state );
    1311             : 
    1312             :     /* De-interleave decorrelated signals*/
    1313     1692825 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1314             :     {
    1315     1128550 :         offset = imult1616( imult1616( num_freq_bands, BINAURAL_CHANNELS ), ch );
    1316    54483230 :         FOR( bin = 0; bin < num_freq_bands; bin++ )
    1317             :         {
    1318    53354680 :             decRe[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), offset )];           // q_inp
    1319    53354680 :             decIm[ch][bin] = decorrelatedFrameInterleaved_fx[add( imult1616( bin, BINAURAL_CHANNELS ), add( offset, 1 ) )]; // q_inp
    1320    53354680 :             move32();
    1321    53354680 :             move32();
    1322             :         }
    1323             :     }
    1324             :     // q_decorrelatedFrameInterleaved will be same as q_inp/q_protoFrame //
    1325      564275 :     return;
    1326             : }
    1327             : 
    1328             : 
    1329      282525 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx(
    1330             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    1331             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    1332             :     PARAMBIN_REND_CONFIG_HANDLE hConfig,
    1333             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/
    1334             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q*/
    1335             :     const Word16 subframe,
    1336             :     Word32 *subFrameTotalEne_fx,
    1337             :     Word16 *subFrameTotalEne_e,
    1338             :     Word32 *IIReneLimiter_fx,
    1339             :     Word16 q )
    1340             : {
    1341             :     Word16 ch, slot, bin;
    1342             :     Word16 nBins;
    1343             :     Word32 IIReneLimiterFactor_fx; // Q26
    1344             :     Word32 qualityBasedSmFactor_fx;
    1345             :     Word32 lowBitRateEQ_fx[CLDFB_NO_CHANNELS_MAX];
    1346             :     UWord8 applyLowBitRateEQ;
    1347             :     IVAS_FORMAT ivas_format;
    1348             :     Word32 ivas_total_brate;
    1349             :     Word16 nchan_transport;
    1350             :     Word16 exp, exp1;
    1351             :     Word64 temp64;
    1352             :     Word32 temp;
    1353             : 
    1354      282525 :     ivas_format = hConfig->ivas_format;
    1355      282525 :     move32();
    1356      282525 :     ivas_total_brate = hConfig->ivas_total_brate;
    1357      282525 :     move32();
    1358      282525 :     nchan_transport = hConfig->nchan_transport;
    1359      282525 :     move16();
    1360      282525 :     qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/
    1361      282525 :     move32();
    1362      282525 :     qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/
    1363             : 
    1364      282525 :     nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
    1365      282525 :     move16();
    1366             : 
    1367             : 
    1368      282525 :     set32_fx( hDiracDecBin->ChCrossRe_fx, 0, nBins );
    1369      282525 :     set32_fx( hDiracDecBin->ChCrossIm_fx, 0, nBins );
    1370             : 
    1371             : 
    1372      282525 :     set16_fx( hDiracDecBin->ChCrossRe_e, 0, nBins );
    1373      282525 :     set16_fx( hDiracDecBin->ChCrossIm_e, 0, nBins );
    1374             : 
    1375      847575 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1376             :     {
    1377      565050 :         set32_fx( hDiracDecBin->ChEne_fx[ch], 0, nBins );
    1378             : 
    1379      565050 :         set16_fx( hDiracDecBin->ChEne_e[ch], 0, nBins );
    1380             :     }
    1381             : 
    1382      282525 :     set16_fx( subFrameTotalEne_e, 0, CLDFB_NO_CHANNELS_MAX );
    1383             : 
    1384             :     /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */
    1385      282525 :     applyLowBitRateEQ = 0;
    1386      282525 :     move16();
    1387      282525 :     test();
    1388      282525 :     test();
    1389      282525 :     IF( ( EQ_32( ivas_format, MASA_FORMAT ) || EQ_32( ivas_format, MC_FORMAT ) ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
    1390             :     {
    1391       10979 :         applyLowBitRateEQ = 1;
    1392       10979 :         move16();
    1393       10979 :         IF( EQ_32( ivas_total_brate, IVAS_16k4 ) )
    1394             :         {
    1395       78084 :             FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
    1396             :             {
    1397       73746 :                 lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = L_add( L_shr( lowBitRateBinauralEQ_fx[bin], 1 ), ONE_IN_Q30 ); // Q31
    1398       73746 :                 move32();
    1399             :             }
    1400             :         }
    1401             :         ELSE
    1402             :         {
    1403      119538 :             FOR( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
    1404             :             {
    1405      112897 :                 lowBitRateEQ_fx[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ_fx[bin]; // Q31
    1406      112897 :                 move32();
    1407             :             }
    1408             :         }
    1409             :     }
    1410             : 
    1411             :     /* Formulate input and target covariance matrices for this subframe */
    1412      282525 :     set32_fx( subFrameTotalEne_fx, 0, CLDFB_NO_CHANNELS_MAX );
    1413             : 
    1414      282525 :     exp = sub( 63, shl( q, 1 ) ); // exp for the energy (inRe_fx * inRe_fx + inIm_fx * inIm_fx) computed below
    1415             : 
    1416             :     /* Calculate input covariance matrix */
    1417     1409046 :     FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    1418             :     {
    1419    56624661 :         FOR( bin = 0; bin < nBins; bin++ )
    1420             :         {
    1421   166494420 :             FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1422             :             {
    1423             :                 Word32 instEne_fx;
    1424   110996280 :                 temp64 = W_mult0_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] );                  // 2q
    1425   110996280 :                 temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // 2q
    1426   110996280 :                 exp1 = W_norm( temp64 );
    1427   110996280 :                 instEne_fx = W_extract_h( W_shl( temp64, exp1 ) ); // 2q - 32 + exp1
    1428             :                 /* exp of instEne_fx = 31 - (2q -32 + exp1) = 63 - 2q - exp1 = exp - exp1*/
    1429             : 
    1430   110996280 :                 hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], instEne_fx, sub( exp, exp1 ), &hDiracDecBin->ChEne_e[ch][bin] );
    1431   110996280 :                 subFrameTotalEne_fx[bin] = BASOP_Util_Add_Mant32Exp( subFrameTotalEne_fx[bin], subFrameTotalEne_e[bin], instEne_fx, sub( exp, exp1 ), &subFrameTotalEne_e[bin] );
    1432   110996280 :                 move32();
    1433   110996280 :                 move32();
    1434             :             }
    1435    55498140 :             temp64 = W_mult0_32_32( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] );                  // 2q
    1436    55498140 :             temp64 = W_add( temp64, W_mult0_32_32( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ); // 2q
    1437    55498140 :             exp1 = W_norm( temp64 );
    1438    55498140 :             temp = W_extract_h( W_shl( temp64, exp1 ) ); // // 2q - 32 + exp1
    1439    55498140 :             hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], temp, sub( exp, exp1 ), &hDiracDecBin->ChCrossRe_e[bin] );
    1440    55498140 :             move32();
    1441             : 
    1442    55498140 :             temp64 = W_mult0_32_32( inRe_fx[0][slot][bin], inIm_fx[1][slot][bin] );                  // 2q
    1443    55498140 :             temp64 = W_sub( temp64, W_mult0_32_32( inIm_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ); // 2q
    1444    55498140 :             exp1 = W_norm( temp64 );
    1445    55498140 :             temp = W_extract_h( W_shl( temp64, exp1 ) ); // // 2q - 32 + exp1
    1446    55498140 :             hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], temp, sub( exp, exp1 ), &hDiracDecBin->ChCrossIm_e[bin] );
    1447    55498140 :             move32();
    1448             :         }
    1449             :     }
    1450             : 
    1451             :     /* Apply EQ at low bit rates */
    1452      282525 :     IF( applyLowBitRateEQ != 0 )
    1453             :     {
    1454       10979 :         Word16 lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1;
    1455             : 
    1456      186643 :         FOR( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ )
    1457             :         {
    1458      175664 :             subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[bin] ); // exp = subFrameTotalEne_e[bin]
    1459      175664 :             move32();
    1460             :         }
    1461      275279 :         FOR( ; bin < nBins; bin++ )
    1462             :         {
    1463      264300 :             subFrameTotalEne_fx[bin] = Mpy_32_32( subFrameTotalEne_fx[bin], lowBitRateEQ_fx[lastEqBin] ); // exp = subFrameTotalEne_e[bin]
    1464      264300 :             move32();
    1465             :         }
    1466             :     }
    1467             : 
    1468      282525 :     test();
    1469      282525 :     test();
    1470      282525 :     IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, SBA_ISM_FORMAT ) ) && EQ_16( nchan_transport, 2 ) )
    1471             :     {
    1472             :         Word32 tempRe, tempIm;
    1473             :         Word32 subFrameSumEne_fx[CLDFB_NO_CHANNELS_MAX];
    1474             :         Word16 subFrameSumEne_e[CLDFB_NO_CHANNELS_MAX];
    1475             : 
    1476       85934 :         set32_fx( subFrameSumEne_fx, 0, CLDFB_NO_CHANNELS_MAX );
    1477       85934 :         set16_fx( subFrameSumEne_e, 0, CLDFB_NO_CHANNELS_MAX );
    1478      428675 :         FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    1479             :         {
    1480    15063361 :             FOR( bin = 0; bin < nBins; bin++ )
    1481             :             {
    1482    14720620 :                 tempRe = L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] );                     // q
    1483    14720620 :                 tempIm = L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] );                     // q
    1484    14720620 :                 temp64 = W_add( W_mult0_32_32( tempRe, tempRe ), W_mult0_32_32( tempIm, tempIm ) ); // 2q
    1485    14720620 :                 exp1 = W_norm( temp64 );
    1486    14720620 :                 temp64 = W_shl( temp64, exp1 ); // 2q + exp1
    1487    14720620 :                 subFrameSumEne_fx[bin] = BASOP_Util_Add_Mant32Exp( subFrameSumEne_fx[bin], subFrameSumEne_e[bin], W_extract_h( temp64 ), sub( exp /* 63 - 2q */, exp1 ) /*31 - (2q + exp1 - 32)*/, &subFrameSumEne_e[bin] );
    1488    14720620 :                 move32();
    1489             :             }
    1490             :         }
    1491     3781014 :         FOR( bin = 0; bin < nBins; bin++ )
    1492             :         {
    1493     3695080 :             subFrameTotalEne_e[bin] = sub( subFrameTotalEne_e[bin], 1 );
    1494     3695080 :             move16();
    1495     3695080 :             temp = L_shl_sat( subFrameTotalEne_fx[bin], sub( subFrameTotalEne_e[bin], subFrameSumEne_e[bin] ) ); // subFrameSumEne_e[bin]
    1496     3695080 :             IF( GT_32( subFrameSumEne_fx[bin], temp ) )
    1497             :             {
    1498     3580523 :                 subFrameTotalEne_fx[bin] = subFrameSumEne_fx[bin];
    1499     3580523 :                 move32();
    1500     3580523 :                 subFrameTotalEne_e[bin] = subFrameSumEne_e[bin];
    1501     3580523 :                 move16();
    1502             :             }
    1503             :         }
    1504             :     }
    1505             : 
    1506             : 
    1507      282525 :     test();
    1508             :     /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */
    1509      282525 :     IF( EQ_32( ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
    1510             :     {
    1511        9559 :         IIReneLimiterFactor_fx = L_add( L_shl( 16, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26
    1512             :     }
    1513             :     ELSE
    1514             :     {
    1515      272966 :         IIReneLimiterFactor_fx = L_add( L_shl( 8, Q26 ), L_sub( L_shl( 1, Q26 ), L_shr( qualityBasedSmFactor_fx, 5 ) ) ); // Q26
    1516             :     }
    1517             : 
    1518    14200945 :     FOR( bin = 0; bin < nBins; bin++ )
    1519             :     {
    1520             : 
    1521             :         /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that
    1522             :          * the energy history (IIR) must not be more than double of the current frame energy. This provides more
    1523             :          * robust performance at energy offsets when compared to typical IIR averaging. */
    1524             :         Word16 num_e, den_e;
    1525             :         Word32 num, den;
    1526    13918420 :         num = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_fx[1][bin], hDiracDecBin->ChEne_e[1][bin], &num_e );
    1527    13918420 :         num = Mpy_32_32( num, IIReneLimiterFactor_fx ); /*Q = (31 - num_e + 26 - 31) = (26 - num_e)*/
    1528    13918420 :         den_e = 0;
    1529    13918420 :         move16();
    1530    13918420 :         den = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEnePrev_fx[0][bin], hDiracDecBin->ChEnePrev_e[0][bin], hDiracDecBin->ChEnePrev_fx[1][bin], hDiracDecBin->ChEnePrev_e[1][bin], &den_e );
    1531    13918420 :         den = L_max( 1, den );
    1532    13918420 :         IIReneLimiter_fx[bin] = BASOP_Util_Divide3232_Scale_cadence( num, den, &exp );
    1533    13918420 :         exp = add( sub( num_e, den_e ), add( 5, exp ) );
    1534    13918420 :         IF( L_shr_sat( IIReneLimiter_fx[bin], sub( 31, exp ) ) > 0 )
    1535             :         {
    1536     8607236 :             IIReneLimiter_fx[bin] = ONE_IN_Q31; /*Q31*/
    1537     8607236 :             move32();
    1538             :         }
    1539             :         ELSE
    1540             :         {
    1541     5311184 :             IIReneLimiter_fx[bin] = L_shl( IIReneLimiter_fx[bin], exp ); /*Q31*/
    1542             :         }
    1543             : 
    1544    13918420 :         hDiracDecBin->ChCrossRe_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossRe_fx[bin], qualityBasedSmFactor_fx );
    1545    13918420 :         hDiracDecBin->ChCrossIm_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossIm_fx[bin], qualityBasedSmFactor_fx );
    1546             : 
    1547    13918420 :         move32();
    1548    13918420 :         move32();
    1549    13918420 :         move32();
    1550    13918420 :         move32();
    1551             : 
    1552    41755260 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1553             :         {
    1554    27836840 :             hDiracDecBin->ChEne_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEne_fx[ch][bin], qualityBasedSmFactor_fx );
    1555    27836840 :             move32();
    1556             :         }
    1557             : 
    1558    13918420 :         hDiracDecBin->ChCrossRe_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossRe_e[bin], Mpy_32_32( hDiracDecBin->ChCrossRePrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossRePrev_e[bin], &hDiracDecBin->ChCrossRe_e[bin] );
    1559    13918420 :         hDiracDecBin->ChCrossIm_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossIm_fx[bin], hDiracDecBin->ChCrossIm_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossImPrev_e[bin], &hDiracDecBin->ChCrossIm_e[bin] );
    1560    13918420 :         move32();
    1561    13918420 :         move32();
    1562             : 
    1563    41755260 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1564             :         {
    1565    27836840 :             hDiracDecBin->ChEne_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEne_fx[ch][bin], hDiracDecBin->ChEne_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEnePrev_fx[ch][bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChEnePrev_e[ch][bin], &hDiracDecBin->ChEne_e[ch][bin] );
    1566    27836840 :             move32();
    1567             :         }
    1568             : 
    1569             :         /* Store energy values and coefficients for next round */
    1570    13918420 :         hDiracDecBin->ChCrossRePrev_fx[bin] = hDiracDecBin->ChCrossRe_fx[bin];
    1571    13918420 :         move32();
    1572    13918420 :         hDiracDecBin->ChCrossImPrev_fx[bin] = hDiracDecBin->ChCrossIm_fx[bin];
    1573    13918420 :         move32();
    1574    13918420 :         hDiracDecBin->ChCrossRePrev_e[bin] = hDiracDecBin->ChCrossRe_e[bin];
    1575    13918420 :         move16();
    1576    13918420 :         hDiracDecBin->ChCrossImPrev_e[bin] = hDiracDecBin->ChCrossIm_e[bin];
    1577    13918420 :         move16();
    1578             : 
    1579    41755260 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1580             :         {
    1581    27836840 :             hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin];
    1582    27836840 :             move32();
    1583    27836840 :             hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin];
    1584    27836840 :             move16();
    1585             :         }
    1586             :     }
    1587             : 
    1588      282525 :     return;
    1589             : }
    1590             : 
    1591             : 
    1592      282525 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx(
    1593             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    1594             :     const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    1595             :     const PARAMBIN_REND_CONFIG_HANDLE hConfig,
    1596             :     Word32 Rmat_fx[3][3],
    1597             :     const Word16 subframe,
    1598             :     const Word16 isHeadtracked,
    1599             :     const Word32 *subFrameTotalEne_fx,
    1600             :     Word16 *subFrameTotalEne_e,
    1601             :     const Word32 *IIReneLimiter_fx,
    1602             :     const MASA_ISM_DATA_HANDLE hMasaIsmData )
    1603             : {
    1604             :     Word16 ch, bin;
    1605             :     Word16 separateCenterChannelRendering;
    1606             :     Word16 nBins, idx, shift;
    1607             :     Word32 frameMeanDiffusenessEneWeight_fx[CLDFB_NO_CHANNELS_MAX];
    1608             :     Word32 qualityBasedSmFactor_fx;
    1609             :     Word16 dirac_read_idx;
    1610             :     PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE];
    1611             :     IVAS_FORMAT ivas_format;
    1612             :     MC_MODE mc_mode;
    1613             :     Word16 gainCacheBaseIndex;
    1614             :     Word16 q_earlyPartEneCorrection;
    1615             :     Word16 exp, exp1;
    1616             :     Word32 temp;
    1617             : 
    1618      282525 :     separateCenterChannelRendering = hConfig->separateCenterChannelRendering;
    1619      282525 :     move16();
    1620      282525 :     ivas_format = hConfig->ivas_format;
    1621      282525 :     move32();
    1622      282525 :     mc_mode = hConfig->mc_mode;
    1623      282525 :     move32();
    1624      282525 :     qualityBasedSmFactor_fx = hConfig->qualityBasedSmFactor_fx; /*Q31*/
    1625      282525 :     move32();
    1626      282525 :     qualityBasedSmFactor_fx = Mpy_32_32( qualityBasedSmFactor_fx, qualityBasedSmFactor_fx ); /*Q31*/
    1627             : 
    1628      282525 :     nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
    1629      282525 :     move16();
    1630             : 
    1631      282525 :     q_earlyPartEneCorrection = s_min( Q31, add( getScaleFactor32( hDiracDecBin->earlyPartEneCorrection_fx, nBins ), hDiracDecBin->q_earlyPartEneCorrection ) );
    1632      282525 :     scale_sig32( hDiracDecBin->earlyPartEneCorrection_fx, nBins, sub( q_earlyPartEneCorrection, hDiracDecBin->q_earlyPartEneCorrection ) );
    1633      282525 :     hDiracDecBin->q_earlyPartEneCorrection = q_earlyPartEneCorrection;
    1634      282525 :     move16();
    1635             : 
    1636      282525 :     set32_fx( hDiracDecBin->ChCrossReOut_fx, 0, nBins );
    1637      282525 :     set32_fx( hDiracDecBin->ChCrossImOut_fx, 0, nBins );
    1638      282525 :     set16_fx( hDiracDecBin->ChCrossReOut_e, 0, nBins );
    1639      282525 :     set16_fx( hDiracDecBin->ChCrossImOut_e, 0, nBins );
    1640             : 
    1641      847575 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1642             :     {
    1643      565050 :         set32_fx( hDiracDecBin->ChEneOut_fx[ch], 0, nBins );
    1644      565050 :         set16_fx( hDiracDecBin->ChEneOut_e[ch], 0, nBins );
    1645             :     }
    1646      282525 :     set32_fx( hDiracDecBin->frameMeanDiffuseness_fx, 0, nBins );
    1647             : 
    1648      282525 :     set32_fx( frameMeanDiffusenessEneWeight_fx, 0, CLDFB_NO_CHANNELS_MAX );
    1649             : 
    1650     3107775 :     FOR( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ )
    1651             :     {
    1652     2825250 :         gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
    1653     2825250 :         move16();
    1654             :     }
    1655             : 
    1656      282525 :     dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
    1657             : 
    1658             :     /* Determine target covariance matrix containing target binaural properties */
    1659    14200945 :     FOR( bin = 0; bin < nBins; bin++ )
    1660             :     {
    1661    13918420 :         Word32 diffuseness_fx = ONE_IN_Q30; /* ratio1 and ratio2 are subtracted from diffuseness further below */
    1662    13918420 :         Word32 diffusenessValForDecorrelationReduction_fx = ONE_IN_Q30;
    1663             :         Word32 diffEneValForDecorrelationReduction_fx;
    1664             :         Word16 q_diffEneValForDecorrelationReduction;
    1665    13918420 :         Word16 surCoh_fx = 0, spreadCoh_fx = 0; /* Default values if spreadSurroundCoherenceApplied == false */
    1666             :         Word32 diffEne_fx, dirEne_fx, meanEnePerCh_fx;
    1667             :         Word16 q_meanEnePerCh;
    1668             :         Word16 q_diffEne, q_dirEne;
    1669             :         Word16 dirIndex;
    1670    13918420 :         move16();
    1671    13918420 :         move16();
    1672    13918420 :         move32();
    1673    13918420 :         move32();
    1674             : 
    1675             :         /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f.
    1676             :          * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the
    1677             :          * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match
    1678             :          * the early spectrum of the BRIR data, using the spectral correction data in
    1679             :          * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */
    1680    13918420 :         meanEnePerCh_fx = Mpy_32_32( hDiracDecBin->earlyPartEneCorrection_fx[bin], subFrameTotalEne_fx[bin] ); // Q( q_meanEnePerCh )
    1681    13918420 :         q_meanEnePerCh = add( sub( q_earlyPartEneCorrection, subFrameTotalEne_e[bin] ), 1 );                   // q_earlyPartEneCorrection + 31 - subFrameTotalEne_e[bin] - 31 + Q1(0.5f)
    1682             :         /* Determine direct part target covariance matrix (for 1 or 2 directions) */
    1683    30802220 :         FOR( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ )
    1684             :         {
    1685             :             Word16 aziDeg, eleDeg;
    1686             :             Word32 lRealp_fx, lImagp_fx, rRealp_fx, rImagp_fx;
    1687             :             Word32 lRealpTmp_fx, lImagpTmp_fx, rRealpTmp_fx, rImagpTmp_fx;
    1688             :             Word32 hrtfEne_fx[BINAURAL_CHANNELS], hrtfCrossRe_fx, hrtfCrossIm_fx, ratio_fx;
    1689    16883800 :             UWord8 isIsmDirection = 0;
    1690    16883800 :             move16();
    1691             : 
    1692    16883800 :             test();
    1693    16883800 :             test();
    1694    16883800 :             IF( dirIndex == 0 ) /* For first of the two simultaneous directions */
    1695             :             {
    1696    13918420 :                 aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin];
    1697    13918420 :                 move16();
    1698    13918420 :                 eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin];
    1699    13918420 :                 move16();
    1700    13918420 :                 ratio_fx = hSpatParamRendCom->energy_ratio1_fx[dirac_read_idx][bin];
    1701    13918420 :                 move32();
    1702    13918420 :                 spreadCoh_fx = hSpatParamRendCom->spreadCoherence_fx[dirac_read_idx][bin];
    1703    13918420 :                 move16();
    1704    13918420 :                 gainCacheBaseIndex = 0;
    1705    13918420 :                 move16();
    1706             :             }
    1707     2965380 :             ELSE IF( NE_32( ivas_format, MASA_ISM_FORMAT ) || ( EQ_32( ivas_format, MASA_ISM_FORMAT ) && LT_16( dirIndex, hSpatParamRendCom->numParametricDirections ) ) ) /* For second of the two simultaneous directions */
    1708             :             {
    1709     2627220 :                 IF( LT_32( ( ratio_fx = hSpatParamRendCom->energy_ratio2_fx[dirac_read_idx][bin] ), 10737418 /* 0.01 in Q30 */ ) )
    1710             :                 {
    1711             :                     /* This touches only MASA path where second direction always has smaller ratio and
    1712             :                      * for non-2dir it is zero. As the whole direction contribution is multiplied with
    1713             :                      * the ratio, a very small ratio does not contribute any energy to output. Thus,
    1714             :                      * it is better to save complexity. */
    1715     1043373 :                     CONTINUE;
    1716             :                 }
    1717     1583847 :                 aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin];
    1718     1583847 :                 move16();
    1719     1583847 :                 eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin];
    1720     1583847 :                 move16();
    1721     1583847 :                 spreadCoh_fx = hSpatParamRendCom->spreadCoherence2_fx[dirac_read_idx][bin];
    1722     1583847 :                 move16();
    1723     1583847 :                 gainCacheBaseIndex = 3;
    1724     1583847 :                 move16();
    1725             :             }
    1726             :             ELSE /* For object directions of MASA_ISM_FORMAT */
    1727             :             {
    1728      338160 :                 isIsmDirection = 1;
    1729      338160 :                 move16();
    1730             :                 UWord16 ismDirIndex;
    1731      338160 :                 ismDirIndex = sub( dirIndex, hSpatParamRendCom->numParametricDirections );
    1732      338160 :                 assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" );
    1733      338160 :                 IF( hMasaIsmData->ism_is_edited[ismDirIndex] )
    1734             :                 {
    1735           0 :                     aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex];
    1736           0 :                     move16();
    1737           0 :                     eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex];
    1738           0 :                     move16();
    1739             :                 }
    1740             :                 ELSE
    1741             :                 {
    1742      338160 :                     aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx];
    1743      338160 :                     move16();
    1744      338160 :                     eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx];
    1745      338160 :                     move16();
    1746             :                 }
    1747      338160 :                 ratio_fx = hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin];
    1748      338160 :                 move32();
    1749      338160 :                 spreadCoh_fx = 0;
    1750      338160 :                 move16();
    1751      338160 :                 gainCacheBaseIndex = add( 6, ismDirIndex );
    1752             :             }
    1753             : 
    1754    15840427 :             diffuseness_fx = L_sub( diffuseness_fx, ratio_fx ); /* diffuseness = 1 - ratio1 - ratio2 */
    1755             : 
    1756    15840427 :             if ( diffuseness_fx < 0 )
    1757             :             {
    1758       13091 :                 diffuseness_fx = 0;
    1759       13091 :                 move32();
    1760             :             }
    1761    15840427 :             IF( isIsmDirection )
    1762             :             {
    1763             :                 /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */
    1764      338160 :                 diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, L_shr( ratio_fx, 1 ) ); /*Q30*/
    1765             :             }
    1766             :             ELSE
    1767             :             {
    1768    15502267 :                 diffusenessValForDecorrelationReduction_fx = L_sub( diffusenessValForDecorrelationReduction_fx, ratio_fx ); /*Q30*/
    1769             :             }
    1770             : 
    1771    15840427 :             IF( separateCenterChannelRendering )
    1772             :             {
    1773             :                 /* In masa + mono rendering mode, the center directions originate from phantom sources, so the
    1774             :                  * spread coherence is increased */
    1775             :                 Word16 azi_scaled, ele_scaled;
    1776             :                 Word32 doaVectorX_fx, num, den;
    1777        6000 :                 Word16 e = 0, spatialAngleDeg_fx, altSpreadCoh_fx;
    1778        6000 :                 move16();
    1779             : 
    1780        6000 :                 azi_scaled = i_mult( aziDeg, 91 );
    1781        6000 :                 ele_scaled = i_mult( eleDeg, 91 );
    1782        6000 :                 doaVectorX_fx = L_mult( getCosWord16R2( azi_scaled ), getCosWord16R2( ele_scaled ) ); /*Q31*/
    1783        6000 :                 num = Sqrt32( L_sub( ONE_IN_Q31, Mpy_32_32( doaVectorX_fx, doaVectorX_fx ) ), &e );
    1784        6000 :                 den = doaVectorX_fx;
    1785        6000 :                 move32();
    1786        6000 :                 spatialAngleDeg_fx = BASOP_util_atan2( num, den, e ); // Q13
    1787        6000 :                 Word16 numr, num_e = 0, denr, den_e;
    1788        6000 :                 move16();
    1789        6000 :                 num_e = sub( norm_s( spatialAngleDeg_fx ), 1 );
    1790        6000 :                 numr = shl( spatialAngleDeg_fx, num_e );
    1791        6000 :                 denr = 17157;
    1792        6000 :                 move16();
    1793        6000 :                 den_e = 4;
    1794        6000 :                 move16();
    1795        6000 :                 altSpreadCoh_fx = sub( 32767, shl_sat( div_s( numr, denr ), sub( den_e, num_e ) ) ); // 4289 = pi/6 in Q13
    1796        6000 :                 spreadCoh_fx = s_max( spreadCoh_fx, altSpreadCoh_fx );
    1797             :             }
    1798             : 
    1799             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    1800    15840427 :             getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1801             : #else
    1802             :             getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex], isHeadtracked );
    1803             : #endif
    1804             : 
    1805    15840427 :             Word16 q_lr = Q28;
    1806    15840427 :             move16();
    1807    15840427 :             if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
    1808             :             {
    1809             :                 /* Synthesizing spread coherence is not needed for stereo loudspeaker output,
    1810             :                  * as directional sound is reproduced with two loudspeakers in any case */
    1811     1255906 :                 spreadCoh_fx = 0;
    1812     1255906 :                 move32();
    1813             :             }
    1814             : 
    1815    15840427 :             IF( spreadCoh_fx > 0 )
    1816             :             {
    1817             :                 Word32 centerMul_fx, sidesMul_fx;
    1818             :                 Word32 hrtfEneCenter_fx, hrtfEneSides_fx, hrtfEneRealized_fx;
    1819             :                 Word16 eneCorrectionFactor_fx, eneCorrectionFactor_e;
    1820             :                 Word16 w1_fx, w2_fx, w3_fx, eq_fx;
    1821             : 
    1822     2138881 :                 hrtfEneCenter_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ),                     // Q25
    1823             :                                           L_add( Mpy_32_32( lImagp_fx, lImagp_fx ),              // Q25
    1824             :                                                  L_add( Mpy_32_32( rRealp_fx, rRealp_fx ),       // Q25
    1825             :                                                         Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q25
    1826             : 
    1827             :                 /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing.
    1828             :                  * The following formulas determine the gains for these sources.
    1829             :                  * spreadCoh = 0: Only panning
    1830             :                  * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi)
    1831             :                  * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */
    1832     2138881 :                 IF( LT_16( spreadCoh_fx, 16384 ) )
    1833             :                 {
    1834             :                     /* 0.0f < spreadCoh < 0.5f */
    1835     1639747 :                     sidesMul_fx = L_mult0( spreadCoh_fx, 9459 ); /* 2*sqrt(1/3) in Q13 = 9459 */         // Q28
    1836     1639747 :                     centerMul_fx = L_add( L_sub( ONE_IN_Q28, L_shl( spreadCoh_fx, 14 ) ), sidesMul_fx ); // Q28
    1837             :                 }
    1838             :                 ELSE
    1839             :                 {
    1840             :                     /* 0.5f <= spreadCoh < 1.0f */
    1841             :                     // centerMul = 2.0f - ( 2.0f * spreadCoh );
    1842      499134 :                     centerMul_fx = L_shl( sub( 32767, spreadCoh_fx ), 14 );                    // Q28
    1843      499134 :                     sidesMul_fx = Isqrt( L_add( L_shr( centerMul_fx, 22 ), L_shl( 2, Q6 ) ) ); // Q28
    1844      499134 :                     centerMul_fx = L_shl( Mpy_32_32( centerMul_fx, sidesMul_fx ), 3 );         // Q28
    1845             :                 }
    1846             : 
    1847             :                 /* Apply the gain for the center source of the three coherent sources */
    1848     2138881 :                 lRealp_fx = Mpy_32_32( lRealp_fx, centerMul_fx ); // Q25
    1849     2138881 :                 lImagp_fx = Mpy_32_32( lImagp_fx, centerMul_fx ); // Q25
    1850     2138881 :                 rRealp_fx = Mpy_32_32( rRealp_fx, centerMul_fx ); // Q25
    1851     2138881 :                 rImagp_fx = Mpy_32_32( rImagp_fx, centerMul_fx ); // Q25
    1852             : 
    1853             :                 /* Apply the gain for the left source of the three coherent sources */
    1854             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    1855     2138881 :                 getDirectPartGains_fx( bin, add( aziDeg, 30 ), eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 1], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1856             : #else
    1857             :                 getDirectPartGains_fx( bin, add( aziDeg, 30 ), eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 1], isHeadtracked );
    1858             : #endif
    1859             : 
    1860     2138881 :                 hrtfEneSides_fx = L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ),                     // Q25
    1861             :                                          L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ),              // Q25
    1862             :                                                 L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ),       // Q25
    1863             :                                                        Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ); // Q25
    1864     2138881 :                 lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) );               // Q25
    1865     2138881 :                 lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) );               // Q25
    1866     2138881 :                 rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) );               // Q25
    1867     2138881 :                 rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) );               // Q25
    1868             : 
    1869             :                 /* Apply the gain for the right source of the three coherent sources.
    1870             :                  * -30 degrees to 330 wrapping due to internal functions. */
    1871             : 
    1872             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    1873     2138881 :                 getDirectPartGains_fx( bin, aziDeg + 330, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 2], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1874             : #else
    1875             :                 getDirectPartGains_fx( bin, aziDeg + 330, eleDeg, &lRealpTmp_fx, &lImagpTmp_fx, &rRealpTmp_fx, &rImagpTmp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat_fx, &gainCache[gainCacheBaseIndex + 2], isHeadtracked );
    1876             : #endif
    1877             : 
    1878     2138881 :                 hrtfEneSides_fx = L_add( hrtfEneSides_fx,
    1879             :                                          L_add( Mpy_32_32( lRealpTmp_fx, lRealpTmp_fx ),                       // Q25
    1880             :                                                 L_add( Mpy_32_32( lImagpTmp_fx, lImagpTmp_fx ),                // Q25
    1881             :                                                        L_add( Mpy_32_32( rRealpTmp_fx, rRealpTmp_fx ),         // Q25
    1882             :                                                               Mpy_32_32( rImagpTmp_fx, rImagpTmp_fx ) ) ) ) ); // Q25
    1883     2138881 :                 lRealp_fx = L_add( lRealp_fx, Mpy_32_32( sidesMul_fx, lRealpTmp_fx ) );                        // Q25
    1884     2138881 :                 lImagp_fx = L_add( lImagp_fx, Mpy_32_32( sidesMul_fx, lImagpTmp_fx ) );                        // Q25
    1885     2138881 :                 rRealp_fx = L_add( rRealp_fx, Mpy_32_32( sidesMul_fx, rRealpTmp_fx ) );                        // Q25
    1886     2138881 :                 rImagp_fx = L_add( rImagp_fx, Mpy_32_32( sidesMul_fx, rImagpTmp_fx ) );                        // Q25
    1887             : 
    1888             :                 /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */
    1889     2138881 :                 hrtfEneRealized_fx = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ),                     // Q19
    1890             :                                             L_add( Mpy_32_32( lImagp_fx, lImagp_fx ),              // Q19
    1891             :                                                    L_add( Mpy_32_32( rRealp_fx, rRealp_fx ),       // Q19
    1892             :                                                           Mpy_32_32( rImagp_fx, rImagp_fx ) ) ) ); // Q19
    1893             : 
    1894     2138881 :                 eneCorrectionFactor_fx = BASOP_Util_Divide3232_Scale( L_add( Mpy_32_32( hrtfEneSides_fx, Mpy_32_32( sidesMul_fx, sidesMul_fx ) ),
    1895             :                                                                              Mpy_32_32( hrtfEneCenter_fx, Mpy_32_32( centerMul_fx, centerMul_fx ) ) ),
    1896             :                                                                       L_max( 1, hrtfEneRealized_fx ), &eneCorrectionFactor_e );
    1897             : 
    1898             :                 /* Weighting factors to determine appropriate target spectrum for spread coherent sound */
    1899     2138881 :                 IF( LT_16( spreadCoh_fx, 16384 ) )
    1900             :                 {
    1901     1639747 :                     w1_fx = sub( 32767, shl( spreadCoh_fx, 1 ) ); /*Q15*/
    1902     1639747 :                     w2_fx = shl( spreadCoh_fx, 1 );               /*Q15*/
    1903     1639747 :                     w3_fx = 0;
    1904     1639747 :                     move16();
    1905             :                 }
    1906             :                 ELSE
    1907             :                 {
    1908      499134 :                     w1_fx = 0;
    1909      499134 :                     move16();
    1910      499134 :                     w2_fx = shl( sub( 32767, spreadCoh_fx ), 1 ); /*Q15*/
    1911      499134 :                     w3_fx = shl( sub( spreadCoh_fx, 16384 ), 1 ); /*Q15*/
    1912             :                 }
    1913             : 
    1914     2138881 :                 test();
    1915     2138881 :                 IF( ( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( mc_mode, MC_MODE_MCMASA ) ) )
    1916             :                 {
    1917      939257 :                     idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
    1918             : 
    1919             :                     /* Apply the target spectrum to the eneCorrectionFactor */
    1920      939257 :                     IF( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */
    1921             :                     {
    1922        3514 :                         eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 8192 ), shr( mult_r( add( w2_fx, w3_fx ), spreadCohEne1_fx[idx] ), 1 ) ) );
    1923        3514 :                         eneCorrectionFactor_e = add( eneCorrectionFactor_e, 2 );
    1924             :                     }
    1925             :                     ELSE
    1926             :                     {
    1927      935743 :                         eneCorrectionFactor_fx = mult_r( eneCorrectionFactor_fx, add( mult_r( w1_fx, 4096 ), add( shr( mult_r( w2_fx, spreadCohEne05_fx[idx] ), 1 ), shr( mult_r( w3_fx, spreadCohEne1_fx[idx] ), 2 ) ) ) );
    1928      935743 :                         eneCorrectionFactor_e = add( eneCorrectionFactor_e, 3 );
    1929             :                     }
    1930             :                 }
    1931             : 
    1932             :                 /* Equalize the spread coherent combined HRTFs */
    1933             :                 Word16 tmp, tmp_e;
    1934     2138881 :                 tmp_e = eneCorrectionFactor_e;
    1935     2138881 :                 move16();
    1936     2138881 :                 tmp = Sqrt16( eneCorrectionFactor_fx, &tmp_e );
    1937     2138881 :                 IF( GE_16( shr( tmp, sub( 15, tmp_e ) ), 4 ) )
    1938             :                 {
    1939           2 :                     eq_fx = 32767; // Q13
    1940           2 :                     move16();
    1941             :                 }
    1942             :                 ELSE
    1943             :                 {
    1944     2138879 :                     eq_fx = shl( tmp, sub( tmp_e, 2 ) ); // Q13
    1945             :                 }
    1946             : 
    1947     2138881 :                 lRealp_fx = Mpy_32_16_1( lRealp_fx, eq_fx ); // Q23
    1948     2138881 :                 lImagp_fx = Mpy_32_16_1( lImagp_fx, eq_fx ); // Q23
    1949     2138881 :                 rRealp_fx = Mpy_32_16_1( rRealp_fx, eq_fx ); // Q23
    1950     2138881 :                 rImagp_fx = Mpy_32_16_1( rImagp_fx, eq_fx ); // Q23
    1951     2138881 :                 q_lr = Q23;
    1952     2138881 :                 move16();
    1953             :             }
    1954             : 
    1955    15840427 :             hrtfEne_fx[0] = L_add( Mpy_32_32( lRealp_fx, lRealp_fx ), Mpy_32_32( lImagp_fx, lImagp_fx ) ); // Q( 2*q_lr - 31 )
    1956    15840427 :             hrtfEne_fx[1] = L_add( Mpy_32_32( rRealp_fx, rRealp_fx ), Mpy_32_32( rImagp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 )
    1957    15840427 :             move32();
    1958    15840427 :             move32();
    1959    15840427 :             hrtfCrossRe_fx = L_add( Mpy_32_32( lRealp_fx, rRealp_fx ), Mpy_32_32( lImagp_fx, rImagp_fx ) );  // Q( 2*q_lr - 31 )
    1960    15840427 :             hrtfCrossIm_fx = L_add( Mpy_32_32( -lImagp_fx, rRealp_fx ), Mpy_32_32( lRealp_fx, rImagp_fx ) ); // Q( 2*q_lr - 31 )
    1961             : 
    1962             :             /* Add direct part (1 or 2) covariance matrix */
    1963    15840427 :             dirEne_fx = Mpy_32_32( ratio_fx, meanEnePerCh_fx ); // Q(q_meanEnePerCh - 1)
    1964    15840427 :             shift = norm_l( dirEne_fx );
    1965    15840427 :             dirEne_fx = L_shl( dirEne_fx, shift );
    1966    15840427 :             q_dirEne = add( sub( q_meanEnePerCh, 1 ), shift );
    1967             : 
    1968    15840427 :             hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[0] ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Dir ene part*/
    1969    15840427 :             hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], Mpy_32_32( dirEne_fx, hrtfEne_fx[1] ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChEneOut_e[1][bin] );
    1970    15840427 :             hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossRe_fx ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChCrossReOut_e[bin] ); /* Dir cross re */
    1971    15840427 :             hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( dirEne_fx, hrtfCrossIm_fx ), sub( 31, sub( add( q_dirEne, shl( q_lr, 1 ) ), 62 ) ), &hDiracDecBin->ChCrossImOut_e[bin] ); /* Dir cross im */
    1972    15840427 :             move32();
    1973    15840427 :             move32();
    1974    15840427 :             move32();
    1975    15840427 :             move32();
    1976             :         }
    1977             : 
    1978             :         /* Add diffuse / ambient part covariance matrix */
    1979    13918420 :         diffuseness_fx = L_max( 0, diffuseness_fx );               // Q30
    1980    13918420 :         diffEne_fx = Mpy_32_32( diffuseness_fx, meanEnePerCh_fx ); // Q(2q - 32)
    1981    13918420 :         shift = norm_l( diffEne_fx );
    1982    13918420 :         diffEne_fx = L_shl( diffEne_fx, shift );
    1983    13918420 :         q_diffEne = add( shift, sub( q_meanEnePerCh, 1 ) );
    1984             : 
    1985    13918420 :         surCoh_fx = hSpatParamRendCom->surroundingCoherence_fx[dirac_read_idx][bin]; // Q15
    1986    13918420 :         move16();
    1987             : 
    1988    13918420 :         diffusenessValForDecorrelationReduction_fx = L_max( 0, diffusenessValForDecorrelationReduction_fx );               // Q30
    1989    13918420 :         diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffusenessValForDecorrelationReduction_fx, meanEnePerCh_fx ); // resulting Q = q_meanEnePerCh - 1
    1990    13918420 :         q_diffEneValForDecorrelationReduction = sub( q_meanEnePerCh, 1 );
    1991             : 
    1992    13918420 :         test();
    1993    13918420 :         IF( ( EQ_32( ivas_format, MC_FORMAT ) && EQ_32( mc_mode, MC_MODE_MCMASA ) ) )
    1994             :         {
    1995     1640240 :             IF( !hDiracDecBin->renderStereoOutputInsteadOfBinaural )
    1996             :             {
    1997             :                 Word32 spectrumModVal;
    1998             : 
    1999     1640240 :                 idx = s_min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
    2000             :                 /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */
    2001     1640240 :                 spectrumModVal = L_add( L_sub( ONE_IN_Q29, L_shl( surCoh_fx, 14 ) ), L_mult( surCoh_fx, surCohEne_fx[idx] ) ); // Q29
    2002     1640240 :                 diffEne_fx = Mpy_32_32( diffEne_fx, spectrumModVal );                                                          // Q-2
    2003     1640240 :                 q_diffEne = sub( q_diffEne, 2 );
    2004             :                 /* Modify also the value for decorrelation reduction */
    2005     1640240 :                 diffEneValForDecorrelationReduction_fx = Mpy_32_32( diffEneValForDecorrelationReduction_fx, spectrumModVal ); // Q-2
    2006     1640240 :                 q_diffEneValForDecorrelationReduction = sub( q_diffEneValForDecorrelationReduction, 2 );
    2007             :             }
    2008             :         }
    2009    13918420 :         hDiracDecBin->ChEneOut_fx[0][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_e[0][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[0][bin] ); /* Diff ene part*/
    2010    13918420 :         hDiracDecBin->ChEneOut_fx[1][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[1][bin], hDiracDecBin->ChEneOut_e[1][bin], diffEne_fx, sub( 31, q_diffEne ), &hDiracDecBin->ChEneOut_e[1][bin] );
    2011             : 
    2012    13918420 :         move32();
    2013    13918420 :         move32();
    2014    13918420 :         IF( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
    2015             :         {
    2016             :             /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */
    2017     1032140 :             hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_16_1( diffEne_fx, surCoh_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] );
    2018     1032140 :             move32();
    2019             :         }
    2020             :         ELSE /* When rendering binaural, ambience has frequency dependent ICC. */
    2021             :         {
    2022    12886280 :             test();
    2023    12886280 :             test();
    2024    12886280 :             IF( ( EQ_32( ivas_format, SBA_FORMAT ) || EQ_32( ivas_format, SBA_ISM_FORMAT ) ) && LT_16( bin, BINAURAL_COHERENCE_DIFFERENCE_BINS ) )
    2025     1356912 :             {
    2026             :                 Word32 diffuseFieldCoherence_fx;
    2027             :                 Word16 tmp_exp;
    2028     1356912 :                 temp = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioX_fx[bin], hDiracDecBin->diffuseFieldCoherenceX_fx[bin] ), 0, Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioY_fx[bin], hDiracDecBin->diffuseFieldCoherenceY_fx[bin] ), 0, &tmp_exp );
    2029     1356912 :                 diffuseFieldCoherence_fx = BASOP_Util_Add_Mant32Exp( temp, tmp_exp, Mpy_32_32( hDiracDecBin->hDiffuseDist->diffuseRatioZ_fx[bin], hDiracDecBin->diffuseFieldCoherenceZ_fx[bin] ), 0, &tmp_exp );
    2030     1356912 :                 temp = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( diffuseFieldCoherence_fx, sub( 32767, surCoh_fx ) ), tmp_exp, L_shl( surCoh_fx, 16 ), 0, &tmp_exp );
    2031     1356912 :                 hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( temp, diffEne_fx ), add( tmp_exp, sub( 31, q_diffEne ) ), &hDiracDecBin->ChCrossReOut_e[bin] );
    2032             :             }
    2033             :             ELSE
    2034             :             {
    2035    11529368 :                 hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( L_add( Mpy_32_16_1( hDiracDecBin->diffuseFieldCoherence_fx[bin], sub( 32767, surCoh_fx ) ), L_shl( surCoh_fx, 16 ) ), diffEne_fx ), sub( 31, q_diffEne ), &hDiracDecBin->ChCrossReOut_e[bin] );
    2036             :             }
    2037    12886280 :             move32();
    2038             :         }
    2039             : 
    2040             :         /* Store parameters for formulating average diffuseness over frame */
    2041    13918420 :         Word32 frameMeanDiffuseness = BASOP_Util_Add_Mant32Exp( hDiracDecBin->frameMeanDiffuseness_fx[bin], 2 /*Q29*/, diffEneValForDecorrelationReduction_fx, sub( 31, q_diffEneValForDecorrelationReduction ), &exp1 ); // exp = exp1
    2042    13918420 :         frameMeanDiffusenessEneWeight_fx[bin] = L_add( frameMeanDiffusenessEneWeight_fx[bin], meanEnePerCh_fx );
    2043    13918420 :         move32();
    2044             : 
    2045             :         /* Formulate average diffuseness over frame */
    2046    13918420 :         frameMeanDiffuseness = BASOP_Util_Divide3232_Scale_cadence( frameMeanDiffuseness, L_max( EPSILLON_FX, frameMeanDiffusenessEneWeight_fx[bin] ), &exp ); // exp = exp + 31 - q_meanEnePerCh - exp1
    2047    13918420 :         exp = sub( exp, sub( sub( 31, q_meanEnePerCh ), exp1 ) );
    2048    13918420 :         hDiracDecBin->frameMeanDiffuseness_fx[bin] = L_shl( frameMeanDiffuseness, sub( exp, 2 ) ); // Q29
    2049    13918420 :         move32();
    2050             :     }
    2051             : 
    2052    14200945 :     FOR( bin = 0; bin < nBins; bin++ )
    2053             :     {
    2054    13918420 :         hDiracDecBin->ChCrossReOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossReOut_fx[bin], qualityBasedSmFactor_fx );
    2055    13918420 :         hDiracDecBin->ChCrossImOut_fx[bin] = Mpy_32_32( hDiracDecBin->ChCrossImOut_fx[bin], qualityBasedSmFactor_fx );
    2056             : 
    2057    41755260 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2058             :         {
    2059    27836840 :             hDiracDecBin->ChEneOut_fx[ch][bin] = Mpy_32_32( hDiracDecBin->ChEneOut_fx[ch][bin], qualityBasedSmFactor_fx );
    2060    27836840 :             move32();
    2061             :         }
    2062    13918420 :         hDiracDecBin->ChCrossReOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossReOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossReOutPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossReOutPrev_e[bin], &hDiracDecBin->ChCrossReOut_e[bin] );
    2063    13918420 :         hDiracDecBin->ChCrossImOut_fx[bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChCrossImOut_fx[bin], hDiracDecBin->ChCrossImOut_e[bin], Mpy_32_32( hDiracDecBin->ChCrossImOutPrev_fx[bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChCrossImOutPrev_e[bin], &hDiracDecBin->ChCrossImOut_e[bin] );
    2064    13918420 :         move32();
    2065    13918420 :         move32();
    2066             : 
    2067    41755260 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2068             :         {
    2069    27836840 :             hDiracDecBin->ChEneOut_fx[ch][bin] = BASOP_Util_Add_Mant32Exp( hDiracDecBin->ChEneOut_fx[ch][bin], hDiracDecBin->ChEneOut_e[ch][bin], Mpy_32_32( hDiracDecBin->ChEneOutPrev_fx[ch][bin], IIReneLimiter_fx[bin] ), hDiracDecBin->ChEneOutPrev_e[ch][bin], &hDiracDecBin->ChEneOut_e[ch][bin] );
    2070    27836840 :             move32();
    2071             :         }
    2072             : 
    2073             : 
    2074    13918420 :         hDiracDecBin->ChCrossReOutPrev_fx[bin] = hDiracDecBin->ChCrossReOut_fx[bin];
    2075    13918420 :         move32();
    2076    13918420 :         hDiracDecBin->ChCrossImOutPrev_fx[bin] = hDiracDecBin->ChCrossImOut_fx[bin];
    2077    13918420 :         move32();
    2078    13918420 :         hDiracDecBin->ChCrossReOutPrev_e[bin] = hDiracDecBin->ChCrossReOut_e[bin];
    2079    13918420 :         move16();
    2080    13918420 :         hDiracDecBin->ChCrossImOutPrev_e[bin] = hDiracDecBin->ChCrossImOut_e[bin];
    2081    13918420 :         move16();
    2082             : 
    2083    41755260 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2084             :         {
    2085    27836840 :             hDiracDecBin->ChEnePrev_fx[ch][bin] = hDiracDecBin->ChEne_fx[ch][bin];
    2086    27836840 :             move32();
    2087    27836840 :             hDiracDecBin->ChEnePrev_e[ch][bin] = hDiracDecBin->ChEne_e[ch][bin];
    2088    27836840 :             move16();
    2089    27836840 :             hDiracDecBin->ChEneOutPrev_fx[ch][bin] = hDiracDecBin->ChEneOut_fx[ch][bin];
    2090    27836840 :             move32();
    2091    27836840 :             hDiracDecBin->ChEneOutPrev_e[ch][bin] = hDiracDecBin->ChEneOut_e[ch][bin];
    2092    27836840 :             move16();
    2093             :         }
    2094             :     }
    2095             : 
    2096      282525 :     return;
    2097             : }
    2098             : 
    2099             : 
    2100      282525 : static void ivas_dirac_dec_binaural_determine_processing_matrices_fx(
    2101             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    2102             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    2103             :     PARAMBIN_REND_CONFIG_HANDLE hConfig,
    2104             :     const Word16 max_band_decorr,
    2105             :     Word32 Rmat[3][3], /*Q30*/
    2106             :     const Word16 subframe,
    2107             :     const Word16 isHeadtracked,
    2108             :     const Word16 nchanSeparateChannels,
    2109             :     const MASA_ISM_DATA_HANDLE hMasaIsmData )
    2110             : {
    2111             :     Word16 chA, chB, bin;
    2112             :     Word16 separateCenterChannelRendering;
    2113             :     Word16 nBins;
    2114             :     Word16 dirac_read_idx;
    2115             :     PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS];
    2116             :     Word16 idx;
    2117             :     ISM_MODE ism_mode;
    2118             :     IVAS_FORMAT ivas_format;
    2119             :     MC_MODE mc_mode;
    2120             :     Word32 ivas_total_brate;
    2121             :     Word16 nchan_transport;
    2122             :     Word16 exp;
    2123             :     Word16 q_processMtx[CLDFB_NO_CHANNELS_MAX], q_processMtxPrev[CLDFB_NO_CHANNELS_MAX];
    2124             :     Word16 q_processMtx_SCCR[CLDFB_NO_CHANNELS_MAX], q_processMtxPrev_SCCR[CLDFB_NO_CHANNELS_MAX];
    2125             :     Word16 q_processMtxDec[CLDFB_NO_CHANNELS_MAX], q_processMtxDecPrev[CLDFB_NO_CHANNELS_MAX];
    2126      282525 :     set16_fx( q_processMtx, hDiracDecBin->q_processMtx, CLDFB_NO_CHANNELS_MAX );
    2127      282525 :     set16_fx( q_processMtxPrev, hDiracDecBin->q_processMtxPrev, CLDFB_NO_CHANNELS_MAX );
    2128      282525 :     set16_fx( q_processMtx_SCCR, hDiracDecBin->q_processMtx, CLDFB_NO_CHANNELS_MAX );
    2129      282525 :     set16_fx( q_processMtxPrev_SCCR, hDiracDecBin->q_processMtxPrev, CLDFB_NO_CHANNELS_MAX );
    2130      282525 :     set16_fx( q_processMtxDec, hDiracDecBin->q_processMtxDec, CLDFB_NO_CHANNELS_MAX );
    2131      282525 :     set16_fx( q_processMtxDecPrev, hDiracDecBin->q_processMtxDecPrev, CLDFB_NO_CHANNELS_MAX );
    2132             : 
    2133      282525 :     ivas_format = hConfig->ivas_format;
    2134      282525 :     move32();
    2135      282525 :     separateCenterChannelRendering = extract_l( GT_16( nchanSeparateChannels, 0 ) );
    2136      282525 :     move16();
    2137      282525 :     mc_mode = hConfig->mc_mode;
    2138      282525 :     move32();
    2139      282525 :     ivas_total_brate = hConfig->ivas_total_brate;
    2140      282525 :     move32();
    2141      282525 :     nchan_transport = hConfig->nchan_transport;
    2142      282525 :     move16();
    2143      282525 :     nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
    2144      282525 :     move16();
    2145             : 
    2146      282525 :     ism_mode = hConfig->ism_mode;
    2147      282525 :     move32();
    2148             : 
    2149      282525 :     dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
    2150      282525 :     move16();
    2151             : 
    2152     1412625 :     FOR( idx = 0; idx < MAX_NUM_OBJECTS; idx++ )
    2153             :     {
    2154     1130100 :         gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
    2155     1130100 :         move16();
    2156             :     }
    2157             : 
    2158    14200945 :     FOR( bin = 0; bin < nBins; bin++ )
    2159             :     {
    2160             :         Word32 tmpMtxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain_fx;
    2161             :         Word32 CxRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */
    2162             :         Word32 realizedOutputEne_fx, targetOutputEne_fx, missingOutputEne_fx;
    2163             :         Word32 CrEneL_fx, CrEneR_fx; /* Cr = residual decorrelated sound covariance matrix */
    2164             :         Word32 CrCrossRe_fx, CrCrossIm_fx;
    2165             :         Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* M = mixing matrix; Mdec = residual decorrelated signal mixing matrix */
    2166    13918420 :         Word32 prototypeMtx_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { ONE_IN_Q31, 107374182 }, { 107374182, ONE_IN_Q31 } };
    2167    13918420 :         move32();
    2168    13918420 :         Word16 q_M, q_Cx, q_tmp, q_res, q_CrEne, q_CrCross, q_Mdec = 0;
    2169    13918420 :         move16();
    2170             :         Word32 tmp1, tmp2, res1, res2;
    2171             :         Word16 q_tmp1, q_tmp2, q_realizedOutputEne, q_targetOutputEne, q_missingOutputEne, q_gain;
    2172             :         Word16 exp1, exp2, q_processMtx_bin, q_processMtxDec_bin;
    2173             : 
    2174    13918420 :         CrEneL_fx = 0;
    2175    13918420 :         move32();
    2176    13918420 :         CrEneR_fx = 0;
    2177    13918420 :         move32();
    2178    13918420 :         q_CrEne = Q31;
    2179    13918420 :         move16();
    2180             : 
    2181    13918420 :         Word16 q_diff = sub( hDiracDecBin->ChEne_e[0][bin], hDiracDecBin->ChEne_e[1][bin] );
    2182             : 
    2183    13918420 :         IF( q_diff > 0 )
    2184             :         {
    2185     1927092 :             hDiracDecBin->ChEne_fx[1][bin] = L_shr( hDiracDecBin->ChEne_fx[1][bin], q_diff );
    2186     1927092 :             hDiracDecBin->q_ChEne = sub( 31, hDiracDecBin->ChEne_e[0][bin] );
    2187     1927092 :             hDiracDecBin->ChEne_e[1][bin] = hDiracDecBin->ChEne_e[0][bin];
    2188             :         }
    2189             :         ELSE
    2190             :         {
    2191    11991328 :             hDiracDecBin->ChEne_fx[0][bin] = L_shl( hDiracDecBin->ChEne_fx[0][bin], q_diff );
    2192    11991328 :             hDiracDecBin->q_ChEne = sub( 31, hDiracDecBin->ChEne_e[1][bin] );
    2193    11991328 :             hDiracDecBin->ChEne_e[0][bin] = hDiracDecBin->ChEne_e[1][bin];
    2194             :         }
    2195    13918420 :         move32();
    2196    13918420 :         move16();
    2197    13918420 :         move16();
    2198             : 
    2199    13918420 :         q_diff = sub( hDiracDecBin->ChEneOut_e[0][bin], hDiracDecBin->ChEneOut_e[1][bin] );
    2200    13918420 :         IF( q_diff > 0 )
    2201             :         {
    2202     3069343 :             hDiracDecBin->ChEneOut_fx[1][bin] = L_shr( hDiracDecBin->ChEneOut_fx[1][bin], q_diff );
    2203     3069343 :             hDiracDecBin->q_ChEneOut = sub( 31, hDiracDecBin->ChEneOut_e[0][bin] );
    2204     3069343 :             hDiracDecBin->ChEneOut_e[1][bin] = hDiracDecBin->ChEneOut_e[0][bin];
    2205             :         }
    2206             :         ELSE
    2207             :         {
    2208    10849077 :             hDiracDecBin->ChEneOut_fx[0][bin] = L_shl( hDiracDecBin->ChEneOut_fx[0][bin], q_diff );
    2209    10849077 :             hDiracDecBin->q_ChEneOut = sub( 31, hDiracDecBin->ChEneOut_e[1][bin] );
    2210    10849077 :             hDiracDecBin->ChEneOut_e[0][bin] = hDiracDecBin->ChEneOut_e[1][bin];
    2211             :         }
    2212    13918420 :         move32();
    2213    13918420 :         move16();
    2214    13918420 :         move16();
    2215             : 
    2216    13918420 :         q_diff = sub( hDiracDecBin->ChCrossRe_e[bin], hDiracDecBin->ChCrossIm_e[bin] );
    2217    13918420 :         IF( q_diff > 0 )
    2218             :         {
    2219    11789098 :             hDiracDecBin->ChCrossIm_fx[bin] = L_shr( hDiracDecBin->ChCrossIm_fx[bin], q_diff );
    2220    11789098 :             hDiracDecBin->q_ChCross = sub( 31, hDiracDecBin->ChCrossRe_e[bin] );
    2221    11789098 :             hDiracDecBin->ChCrossIm_e[bin] = hDiracDecBin->ChCrossRe_e[bin];
    2222             :         }
    2223             :         ELSE
    2224             :         {
    2225     2129322 :             hDiracDecBin->ChCrossRe_fx[bin] = L_shl( hDiracDecBin->ChCrossRe_fx[bin], q_diff );
    2226     2129322 :             hDiracDecBin->q_ChCross = sub( 31, hDiracDecBin->ChCrossIm_e[bin] );
    2227     2129322 :             hDiracDecBin->ChCrossRe_e[bin] = hDiracDecBin->ChCrossIm_e[bin];
    2228             :         }
    2229    13918420 :         move32();
    2230    13918420 :         move16();
    2231    13918420 :         move16();
    2232             : 
    2233    13918420 :         q_diff = sub( hDiracDecBin->ChCrossReOut_e[bin], hDiracDecBin->ChCrossImOut_e[bin] );
    2234    13918420 :         IF( q_diff > 0 )
    2235             :         {
    2236    12489847 :             hDiracDecBin->ChCrossImOut_fx[bin] = L_shr( hDiracDecBin->ChCrossImOut_fx[bin], q_diff );
    2237    12489847 :             hDiracDecBin->q_ChCrossOut = sub( 31, hDiracDecBin->ChCrossReOut_e[bin] );
    2238    12489847 :             hDiracDecBin->ChCrossImOut_e[bin] = hDiracDecBin->ChCrossReOut_e[bin];
    2239             :         }
    2240             :         ELSE
    2241             :         {
    2242     1428573 :             hDiracDecBin->ChCrossReOut_fx[bin] = L_shl( hDiracDecBin->ChCrossReOut_fx[bin], q_diff );
    2243     1428573 :             hDiracDecBin->q_ChCrossOut = sub( 31, hDiracDecBin->ChCrossImOut_e[bin] );
    2244     1428573 :             hDiracDecBin->ChCrossReOut_e[bin] = hDiracDecBin->ChCrossImOut_e[bin];
    2245             :         }
    2246    13918420 :         move32();
    2247    13918420 :         move16();
    2248    13918420 :         move16();
    2249             : 
    2250    13918420 :         formulate2x2MixingMatrix_fx( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_fx[1][bin],
    2251    13918420 :                                      hDiracDecBin->q_ChEne,
    2252             :                                      hDiracDecBin->ChCrossRe_fx[bin], hDiracDecBin->ChCrossIm_fx[bin],
    2253    13918420 :                                      hDiracDecBin->q_ChCross,
    2254             :                                      hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_fx[1][bin],
    2255    13918420 :                                      hDiracDecBin->q_ChEneOut,
    2256             :                                      hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossImOut_fx[bin],
    2257    13918420 :                                      hDiracDecBin->q_ChCrossOut,
    2258    13918420 :                                      prototypeMtx_fx, Mre_fx, Mim_fx, &q_M, hDiracDecBin->reqularizationFactor_fx );
    2259             : 
    2260    13918420 :         IF( LT_16( hDiracDecBin->q_ChEne, hDiracDecBin->q_ChCross ) )
    2261             :         {
    2262     7950629 :             CxRe_fx[0][0] = hDiracDecBin->ChEne_fx[0][bin];
    2263     7950629 :             move32();
    2264     7950629 :             CxRe_fx[1][1] = hDiracDecBin->ChEne_fx[1][bin];
    2265     7950629 :             move32();
    2266     7950629 :             CxRe_fx[1][0] = L_shr( hDiracDecBin->ChCrossRe_fx[bin], sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
    2267     7950629 :             move32();
    2268     7950629 :             CxRe_fx[0][1] = L_shr( hDiracDecBin->ChCrossRe_fx[bin], sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
    2269     7950629 :             move32();
    2270     7950629 :             CxIm_fx[0][0] = 0;
    2271     7950629 :             move32();
    2272     7950629 :             CxIm_fx[1][1] = 0;
    2273     7950629 :             move32();
    2274     7950629 :             CxIm_fx[1][0] = L_shr( hDiracDecBin->ChCrossIm_fx[bin], sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
    2275     7950629 :             move32();
    2276     7950629 :             CxIm_fx[0][1] = L_shr( L_negate( hDiracDecBin->ChCrossIm_fx[bin] ), sub( hDiracDecBin->q_ChCross, hDiracDecBin->q_ChEne ) );
    2277     7950629 :             move32();
    2278     7950629 :             q_Cx = hDiracDecBin->q_ChEne;
    2279     7950629 :             move16();
    2280             :         }
    2281             :         ELSE
    2282             :         {
    2283     5967791 :             CxRe_fx[0][0] = L_shr( hDiracDecBin->ChEne_fx[0][bin], sub( hDiracDecBin->q_ChEne, hDiracDecBin->q_ChCross ) );
    2284     5967791 :             move32();
    2285     5967791 :             CxRe_fx[1][1] = L_shr( hDiracDecBin->ChEne_fx[1][bin], sub( hDiracDecBin->q_ChEne, hDiracDecBin->q_ChCross ) );
    2286     5967791 :             move32();
    2287     5967791 :             CxRe_fx[1][0] = hDiracDecBin->ChCrossRe_fx[bin];
    2288     5967791 :             move32();
    2289     5967791 :             CxRe_fx[0][1] = hDiracDecBin->ChCrossRe_fx[bin];
    2290     5967791 :             move32();
    2291     5967791 :             CxIm_fx[0][0] = 0;
    2292     5967791 :             move32();
    2293     5967791 :             CxIm_fx[1][1] = 0;
    2294     5967791 :             move32();
    2295     5967791 :             CxIm_fx[1][0] = hDiracDecBin->ChCrossIm_fx[bin];
    2296     5967791 :             move32();
    2297     5967791 :             CxIm_fx[0][1] = L_negate( hDiracDecBin->ChCrossIm_fx[bin] );
    2298     5967791 :             move32();
    2299     5967791 :             q_Cx = hDiracDecBin->q_ChCross;
    2300     5967791 :             move16();
    2301             :         }
    2302             : 
    2303             :         /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */
    2304    13918420 :         matrixMul_fx( Mre_fx, Mim_fx, &q_M, CxRe_fx, CxIm_fx, &q_Cx, tmpMtxRe_fx, tmpMtxIm_fx, &q_tmp );
    2305    13918420 :         matrixTransp2Mul_fx(
    2306             :             tmpMtxRe_fx, tmpMtxIm_fx, &q_tmp, Mre_fx, Mim_fx, &q_M,
    2307             :             1 /*int Ascale*/,
    2308             :             0 /*int Bscale*/,
    2309             :             resultMtxRe_fx, resultMtxIm_fx, &q_res );
    2310             : 
    2311             :         /* When below the frequency limit where decorrelation is applied, we inject the decorrelated
    2312             :          * residual (or missing) signal component. The procedure is active when there are not enough independent
    2313             :          * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */
    2314    13918420 :         IF( LT_16( bin, max_band_decorr ) )
    2315             :         {
    2316             :             Word32 decorrelationReductionFactor_fx;
    2317             :             Word16 q_decorrelationReductionFactor;
    2318             : 
    2319             :             /* Subtract the resulting covariance matrix from the target covariance matrix to determine
    2320             :              * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e.,
    2321             :              * a residual covariance matrix. */
    2322     7496145 :             exp = sub( get_min_scalefactor( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_fx[1][bin] ), 3 );
    2323     7496145 :             tmp1 = L_shl( hDiracDecBin->ChEneOut_fx[0][bin], exp );
    2324     7496145 :             tmp2 = L_shl( hDiracDecBin->ChEneOut_fx[1][bin], exp );
    2325     7496145 :             q_tmp1 = add( hDiracDecBin->q_ChEneOut, exp );
    2326             : 
    2327     7496145 :             exp = sub( get_min_scalefactor( resultMtxRe_fx[0][0], resultMtxRe_fx[1][1] ), 3 );
    2328     7496145 :             res1 = L_shl( resultMtxRe_fx[0][0], exp );
    2329     7496145 :             res2 = L_shl( resultMtxRe_fx[1][1], exp );
    2330     7496145 :             q_tmp2 = add( q_res, exp );
    2331             : 
    2332     7496145 :             IF( LT_16( q_tmp1, q_tmp2 ) )
    2333             :             {
    2334     2490006 :                 CrEneL_fx = L_max( 0, L_sub( tmp1, L_shr( res1, sub( q_tmp2, q_tmp1 ) ) ) );
    2335     2490006 :                 CrEneR_fx = L_max( 0, L_sub( tmp2, L_shr( res2, sub( q_tmp2, q_tmp1 ) ) ) );
    2336     2490006 :                 q_CrEne = q_tmp1;
    2337     2490006 :                 move16();
    2338             :             }
    2339             :             ELSE
    2340             :             {
    2341     5006139 :                 CrEneL_fx = L_max( 0, L_sub( L_shr( tmp1, sub( q_tmp1, q_tmp2 ) ), res1 ) );
    2342     5006139 :                 CrEneR_fx = L_max( 0, L_sub( L_shr( tmp2, sub( q_tmp1, q_tmp2 ) ), res2 ) );
    2343     5006139 :                 q_CrEne = q_tmp2;
    2344     5006139 :                 move16();
    2345             :             }
    2346             : 
    2347     7496145 :             exp = sub( get_min_scalefactor( hDiracDecBin->ChCrossReOut_fx[bin], hDiracDecBin->ChCrossImOut_fx[bin] ), 3 );
    2348     7496145 :             tmp1 = L_shl( hDiracDecBin->ChCrossReOut_fx[bin], exp );
    2349     7496145 :             tmp2 = L_shl( hDiracDecBin->ChCrossImOut_fx[bin], exp );
    2350     7496145 :             q_tmp1 = add( hDiracDecBin->q_ChCrossOut, exp );
    2351             : 
    2352     7496145 :             exp = sub( get_min_scalefactor( resultMtxRe_fx[1][0], resultMtxIm_fx[1][0] ), 3 );
    2353     7496145 :             res1 = L_shl( resultMtxRe_fx[1][0], exp );
    2354     7496145 :             res2 = L_shl( resultMtxIm_fx[1][0], exp );
    2355     7496145 :             q_tmp2 = add( q_res, exp );
    2356             : 
    2357     7496145 :             IF( LT_16( q_tmp1, q_tmp2 ) )
    2358             :             {
    2359      218220 :                 CrCrossRe_fx = L_sub( tmp1, L_shr( res1, sub( q_tmp2, q_tmp1 ) ) );
    2360      218220 :                 CrCrossIm_fx = L_sub( tmp2, L_shr( res2, sub( q_tmp2, q_tmp1 ) ) );
    2361      218220 :                 q_CrCross = q_tmp1;
    2362      218220 :                 move16();
    2363             :             }
    2364             :             ELSE
    2365             :             {
    2366     7277925 :                 CrCrossRe_fx = L_sub( L_shr( tmp1, sub( q_tmp1, q_tmp2 ) ), res1 );
    2367     7277925 :                 CrCrossIm_fx = L_sub( L_shr( tmp2, sub( q_tmp1, q_tmp2 ) ), res2 );
    2368     7277925 :                 q_CrCross = q_tmp2;
    2369     7277925 :                 move16();
    2370             :             }
    2371             : 
    2372             :             /* The amount of the decorrelated sound is further controlled based on the spatial metadata,
    2373             :              * by determining an energy-suppressed residual covariance matrix that is a control parameter
    2374             :              * that guides the processing of the decorrelated sound to a residual signal.
    2375             :              * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/
    2376     7496145 :             test();
    2377     7496145 :             IF( EQ_16( ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) )
    2378             :             {
    2379      515460 :                 decorrelationReductionFactor_fx = ONE_IN_Q30;
    2380      515460 :                 move32();
    2381      515460 :                 q_decorrelationReductionFactor = Q30;
    2382      515460 :                 move16();
    2383             :             }
    2384     6980685 :             ELSE IF( L_or( L_and( EQ_16( ivas_format, MC_FORMAT ), EQ_16( mc_mode, MC_MODE_MCMASA ) ), L_and( EQ_16( ivas_format, MASA_FORMAT ), EQ_16( nchan_transport, 1 ) ) ) )
    2385             :             {
    2386     2322965 :                 exp = 31 - 29;
    2387     2322965 :                 move16();
    2388     2322965 :                 decorrelationReductionFactor_fx = Sqrt32( L_max( 0, hDiracDecBin->frameMeanDiffuseness_fx[bin] ), &exp );
    2389     2322965 :                 q_decorrelationReductionFactor = sub( 31, exp );
    2390             :             }
    2391     4657720 :             ELSE IF( L_and( L_or( EQ_16( ivas_format, SBA_FORMAT ), EQ_16( ivas_format, SBA_ISM_FORMAT ) ), EQ_16( nchan_transport, 1 ) ) )
    2392             :             {
    2393     2823640 :                 decorrelationReductionFactor_fx = ONE_IN_Q30;
    2394     2823640 :                 move32();
    2395     2823640 :                 q_decorrelationReductionFactor = Q30;
    2396     2823640 :                 move16();
    2397             :             }
    2398             :             ELSE
    2399             :             {
    2400     1834080 :                 decorrelationReductionFactor_fx = L_max( 0, hDiracDecBin->frameMeanDiffuseness_fx[bin] );
    2401     1834080 :                 q_decorrelationReductionFactor = 29;
    2402     1834080 :                 move16();
    2403             :             }
    2404             : 
    2405     7496145 :             CrEneL_fx = Mpy_32_32( CrEneL_fx, decorrelationReductionFactor_fx );
    2406     7496145 :             CrEneR_fx = Mpy_32_32( CrEneR_fx, decorrelationReductionFactor_fx );
    2407     7496145 :             q_CrEne = sub( add( q_CrEne, q_decorrelationReductionFactor ), 31 );
    2408     7496145 :             CrCrossRe_fx = Mpy_32_32( CrCrossRe_fx, decorrelationReductionFactor_fx );
    2409     7496145 :             CrCrossIm_fx = Mpy_32_32( CrCrossIm_fx, decorrelationReductionFactor_fx );
    2410     7496145 :             q_CrCross = sub( add( q_CrCross, q_decorrelationReductionFactor ), 31 );
    2411             : 
    2412     7496145 :             formulate2x2MixingMatrix_fx( hDiracDecBin->ChEne_fx[0][bin], hDiracDecBin->ChEne_fx[1][bin],
    2413     7496145 :                                          hDiracDecBin->q_ChEne,
    2414             :                                          0, 0, /* Decorrelated signal has ideally no cross-terms */
    2415             :                                          Q31, CrEneL_fx, CrEneR_fx, q_CrEne,
    2416             :                                          CrCrossRe_fx, CrCrossIm_fx, q_CrCross,
    2417             :                                          prototypeMtx_fx, MdecRe_fx, MdecIm_fx, &q_Mdec, 3277 ); // 3277 = 0.2 in Q14
    2418             :         }
    2419             :         ELSE
    2420             :         {
    2421    19266825 :             FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2422             :             {
    2423    12844550 :                 set_zero_fx( MdecRe_fx[chA], BINAURAL_CHANNELS );
    2424    12844550 :                 set_zero_fx( MdecIm_fx[chA], BINAURAL_CHANNELS );
    2425             :             }
    2426     6422275 :             q_Mdec = Q31;
    2427     6422275 :             move16();
    2428             :         }
    2429             : 
    2430             :         /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */
    2431    13918420 :         tmp1 = L_add( CrEneL_fx, CrEneR_fx );
    2432    13918420 :         exp = sub( get_min_scalefactor( resultMtxRe_fx[0][0], resultMtxRe_fx[1][1] ), 2 );
    2433    13918420 :         tmp2 = L_add( L_shl( resultMtxRe_fx[0][0], exp ), L_shl( resultMtxRe_fx[1][1], exp ) );
    2434    13918420 :         q_tmp2 = add( q_res, exp );
    2435             : 
    2436             :         /*Limiting value to Q63*/
    2437    13918420 :         IF( GT_16( q_tmp2, 63 ) )
    2438             :         {
    2439       43697 :             tmp2 = L_shl( tmp2, sub( 63, q_tmp2 ) );
    2440       43697 :             q_tmp2 = 63;
    2441       43697 :             move16();
    2442       43697 :             IF( EQ_32( tmp2, -1 ) )
    2443             :             {
    2444           0 :                 tmp2 = 0;
    2445           0 :                 move32();
    2446           0 :                 q_tmp2 = 31;
    2447           0 :                 move16();
    2448             :             }
    2449             :         }
    2450    13918420 :         IF( LT_16( q_CrEne, q_tmp2 ) )
    2451             :         {
    2452     7547430 :             realizedOutputEne_fx = L_add( tmp1, L_shr( tmp2, sub( q_tmp2, q_CrEne ) ) );
    2453     7547430 :             q_realizedOutputEne = q_CrEne;
    2454     7547430 :             move16();
    2455             :         }
    2456             :         ELSE
    2457             :         {
    2458     6370990 :             realizedOutputEne_fx = L_add( L_shr( tmp1, sub( q_CrEne, q_tmp2 ) ), tmp2 );
    2459     6370990 :             q_realizedOutputEne = q_tmp2;
    2460     6370990 :             move16();
    2461             :         }
    2462             : 
    2463    13918420 :         exp = sub( get_min_scalefactor( hDiracDecBin->ChEneOut_fx[0][bin], hDiracDecBin->ChEneOut_fx[1][bin] ), 1 );
    2464    13918420 :         targetOutputEne_fx = L_add( L_shl( hDiracDecBin->ChEneOut_fx[0][bin], exp ), L_shl( hDiracDecBin->ChEneOut_fx[1][bin], exp ) );
    2465    13918420 :         q_targetOutputEne = add( hDiracDecBin->q_ChEneOut, exp );
    2466             : 
    2467    13918420 :         exp = sub( norm_l( targetOutputEne_fx ), 2 );
    2468    13918420 :         targetOutputEne_fx = L_shl( targetOutputEne_fx, exp );
    2469    13918420 :         q_targetOutputEne = add( q_targetOutputEne, exp );
    2470    13918420 :         exp = sub( norm_l( -realizedOutputEne_fx ), 2 );
    2471    13918420 :         realizedOutputEne_fx = L_shl( -realizedOutputEne_fx, exp );
    2472    13918420 :         q_realizedOutputEne = add( q_realizedOutputEne, exp );
    2473    13918420 :         IF( LT_16( q_realizedOutputEne, q_targetOutputEne ) )
    2474             :         {
    2475      103453 :             missingOutputEne_fx = L_max( 0, L_add( L_shr( targetOutputEne_fx, sub( q_targetOutputEne, q_realizedOutputEne ) ), realizedOutputEne_fx ) );
    2476      103453 :             q_missingOutputEne = q_realizedOutputEne;
    2477      103453 :             move16();
    2478             :         }
    2479             :         ELSE
    2480             :         {
    2481    13814967 :             missingOutputEne_fx = L_max( 0, L_add( targetOutputEne_fx, L_shr( realizedOutputEne_fx, sub( q_realizedOutputEne, q_targetOutputEne ) ) ) );
    2482    13814967 :             q_missingOutputEne = q_targetOutputEne;
    2483    13814967 :             move16();
    2484             :         }
    2485             : 
    2486    13918420 :         tmp1 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), missingOutputEne_fx, sub( 31, q_missingOutputEne ), &exp1 );
    2487             : 
    2488             :         {
    2489    13918420 :             tmp2 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), EPSILON_MANT, EPSILON_EXP, &exp2 );
    2490    13918420 :             tmp2 = ISqrt32( tmp2, &exp2 );
    2491    13918420 :             gain_fx = Mpy_32_32( tmp2, Sqrt32( tmp1, &exp1 ) );
    2492    13918420 :             q_gain = sub( 31, add( exp2, exp1 ) );
    2493             :         }
    2494             : 
    2495             : 
    2496             :         // 1073741824 = 4 in Q28
    2497    13918420 :         IF( LT_16( q_gain, Q28 ) )
    2498             :         {
    2499      269570 :             gain_fx = L_min( gain_fx, L_shr( 1073741824, sub( Q28, q_gain ) ) );
    2500             :         }
    2501             :         ELSE
    2502             :         {
    2503    13648850 :             gain_fx = L_min( L_shr( gain_fx, sub( q_gain, Q28 ) ), 1073741824 );
    2504    13648850 :             q_gain = Q28;
    2505    13648850 :             move16();
    2506             :         }
    2507             : 
    2508    41755260 :         FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2509             :         {
    2510    83510520 :             FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2511             :             {
    2512    55673680 :                 Mre_fx[chA][chB] = Mpy_32_32( Mre_fx[chA][chB], gain_fx );
    2513    55673680 :                 move32();
    2514    55673680 :                 Mim_fx[chA][chB] = Mpy_32_32( Mim_fx[chA][chB], gain_fx );
    2515    55673680 :                 move32();
    2516             :             }
    2517             :         }
    2518    13918420 :         q_M = sub( add( q_M, q_gain ), 31 );
    2519             : 
    2520    13918420 :         exp = s_min( L_norm_arr( Mre_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ), L_norm_arr( Mim_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ) );
    2521    13918420 :         scale_sig32( Mre_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
    2522    13918420 :         scale_sig32( Mim_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
    2523    13918420 :         q_M = add( q_M, exp );
    2524             : 
    2525    13918420 :         exp = s_min( L_norm_arr( MdecRe_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ), L_norm_arr( MdecIm_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS ) );
    2526    13918420 :         scale_sig32( MdecRe_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
    2527    13918420 :         scale_sig32( MdecIm_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
    2528    13918420 :         q_Mdec = add( q_Mdec, exp );
    2529             : 
    2530    13918420 :         q_processMtx_bin = q_processMtx[bin];
    2531    13918420 :         q_processMtxDec_bin = q_processMtxDec[bin];
    2532    13918420 :         move16();
    2533    13918420 :         move16();
    2534             :         /* Store processing matrices */
    2535    41755260 :         FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2536             :         {
    2537    83510520 :             FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2538             :             {
    2539    55673680 :                 hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxRe_fx[chA][chB][bin]; // q_processMtx_bin
    2540    55673680 :                 move16();
    2541    55673680 :                 hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxIm_fx[chA][chB][bin]; // q_processMtx_bin
    2542    55673680 :                 move16();
    2543             : 
    2544    55673680 :                 hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecRe_fx[chA][chB][bin]; // q_processMtxDec_bin
    2545    55673680 :                 move16();
    2546    55673680 :                 hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = hDiracDecBin->processMtxDecIm_fx[chA][chB][bin]; // q_processMtxDec_bin
    2547    55673680 :                 move16();
    2548             : 
    2549    55673680 :                 hDiracDecBin->processMtxRe_fx[chA][chB][bin] = extract_h( Mre_fx[chA][chB] ); // q_M -16
    2550    55673680 :                 move16();
    2551    55673680 :                 hDiracDecBin->processMtxIm_fx[chA][chB][bin] = extract_h( Mim_fx[chA][chB] ); // q_M -16
    2552    55673680 :                 move16();
    2553             : 
    2554    55673680 :                 hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = extract_h( MdecRe_fx[chA][chB] ); // q_Mdec -16
    2555    55673680 :                 move16();
    2556    55673680 :                 hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = extract_h( MdecIm_fx[chA][chB] ); // q_Mdec -16
    2557    55673680 :                 move16();
    2558             :             }
    2559             :         }
    2560    13918420 :         q_processMtxPrev[bin] = q_processMtx_bin;
    2561    13918420 :         move16();
    2562    13918420 :         q_processMtxDecPrev[bin] = q_processMtxDec_bin;
    2563    13918420 :         move16();
    2564    13918420 :         q_processMtx[bin] = sub( q_M, 16 );
    2565    13918420 :         move16();
    2566    13918420 :         q_processMtxDec[bin] = sub( q_Mdec, 16 );
    2567    13918420 :         move16();
    2568             : 
    2569    13918420 :         IF( separateCenterChannelRendering )
    2570             :         {
    2571             :             /* The rendering of the separate center channel in masa + mono mode.
    2572             :              * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */
    2573             :             Word32 lRealp_fx, lImagp_fx, rRealp_fx, rImagp_fx;
    2574             :             Word32 gainFactor_fx;
    2575             :             Word16 q_tmp_sq;
    2576      450660 :             Word16 aziDeg = 0;
    2577      450660 :             move16();
    2578      450660 :             Word16 eleDeg = 0;
    2579      450660 :             move16();
    2580      450660 :             UWord8 instantChange = 0;
    2581      450660 :             move16();
    2582             : 
    2583      450660 :             exp = sub( 31, hDiracDecBin->q_earlyPartEneCorrection );
    2584      450660 :             tmp1 = Sqrt32( hDiracDecBin->earlyPartEneCorrection_fx[bin], &exp );
    2585      450660 :             q_tmp_sq = sub( 31, exp );
    2586      450660 :             IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) )
    2587             :             {
    2588      444660 :                 Word32 gainfactor_fx = L_shl( (Word32) OMASA_TDREND_MATCHING_GAIN_FX, Q16 ); // constant in Q31 as Word32
    2589      444660 :                 gainFactor_fx = Mpy_32_32( gainfactor_fx, tmp1 );                            // 1705746262 = 0.7943f in Q31
    2590             :             }
    2591             :             ELSE
    2592             :             {
    2593        6000 :                 gainFactor_fx = Mpy_32_32( 1806892741, tmp1 ); // 1806892741 = 0.8414f in Q31
    2594             :             }
    2595      450660 :             q_gain = sub( add( q_tmp_sq, 31 ), 31 );
    2596             : 
    2597      450660 :             q_processMtx_bin = q_processMtx_SCCR[bin];
    2598      450660 :             move16();
    2599             : 
    2600     1137960 :             FOR( chB = 0; chB < nchanSeparateChannels; chB++ )
    2601             :             {
    2602      687300 :                 IF( EQ_16( ivas_format, MASA_ISM_FORMAT ) )
    2603             :                 {
    2604      681300 :                     IF( EQ_16( ism_mode, ISM_MASA_MODE_DISC ) )
    2605             :                     {
    2606      377160 :                         aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx];
    2607      377160 :                         move16();
    2608      377160 :                         eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx];
    2609      377160 :                         move16();
    2610             :                     }
    2611             :                     ELSE
    2612             :                     {
    2613      304140 :                         aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx];
    2614      304140 :                         move16();
    2615      304140 :                         eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx];
    2616      304140 :                         move16();
    2617      304140 :                         instantChange = 1;
    2618      304140 :                         move16();
    2619             :                     }
    2620             :                 }
    2621             : 
    2622     2061900 :                 FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2623             :                 {
    2624     1374600 :                     hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin];
    2625     1374600 :                     move16();
    2626     1374600 :                     hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin];
    2627     1374600 :                     move16();
    2628             :                 }
    2629      687300 :                 q_processMtxPrev_SCCR[bin] = q_processMtx_bin;
    2630      687300 :                 move16();
    2631             : 
    2632             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    2633      687300 :                 getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    2634             : #else
    2635             :                 getDirectPartGains_fx( bin, aziDeg, eleDeg, &lRealp_fx, &lImagp_fx, &rRealp_fx, &rImagp_fx, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked );
    2636             : #endif
    2637             : 
    2638      687300 :                 hDiracDecBin->processMtxRe_fx[0][chB + 2][bin] = extract_h( Mpy_32_32( lRealp_fx, gainFactor_fx ) );
    2639      687300 :                 move16();
    2640      687300 :                 hDiracDecBin->processMtxIm_fx[0][chB + 2][bin] = extract_h( Mpy_32_32( lImagp_fx, gainFactor_fx ) );
    2641      687300 :                 move16();
    2642      687300 :                 hDiracDecBin->processMtxRe_fx[1][chB + 2][bin] = extract_h( Mpy_32_32( rRealp_fx, gainFactor_fx ) );
    2643      687300 :                 move16();
    2644      687300 :                 hDiracDecBin->processMtxIm_fx[1][chB + 2][bin] = extract_h( Mpy_32_32( rImagp_fx, gainFactor_fx ) );
    2645      687300 :                 move16();
    2646      687300 :                 q_processMtx_SCCR[bin] = sub( sub( add( Q28, q_gain ), 31 ), 16 );
    2647      687300 :                 move16();
    2648             : 
    2649      687300 :                 IF( instantChange )
    2650             :                 {
    2651      912420 :                     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2652             :                     {
    2653      608280 :                         hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin];
    2654      608280 :                         move16();
    2655      608280 :                         hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin] = hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin];
    2656      608280 :                         move16();
    2657             :                     }
    2658      304140 :                     q_processMtxPrev_SCCR[bin] = q_processMtx_SCCR[bin];
    2659      304140 :                     move16();
    2660             :                 }
    2661             :             }
    2662             :         }
    2663             :     }
    2664             :     /* Aligning Q-factors of all bins in the processing matrices to a common Q-factor */
    2665      282525 :     minimum_s( q_processMtx, nBins, &hDiracDecBin->q_processMtx );
    2666      282525 :     minimum_s( q_processMtxPrev, nBins, &hDiracDecBin->q_processMtxPrev );
    2667      282525 :     IF( separateCenterChannelRendering )
    2668             :     {
    2669        9753 :         minimum_s( q_processMtx_SCCR, nBins, &hDiracDecBin->q_processMtxSCCR );
    2670        9753 :         minimum_s( q_processMtxPrev_SCCR, nBins, &hDiracDecBin->q_processMtxPrevSCCR );
    2671             :     }
    2672      282525 :     hDiracDecBin->q_processMtx = s_min( hDiracDecBin->q_processMtx, hDiracDecBin->q_processMtxSCCR );
    2673      282525 :     move16();
    2674      282525 :     hDiracDecBin->q_processMtxPrev = s_min( hDiracDecBin->q_processMtxPrev, hDiracDecBin->q_processMtxPrevSCCR );
    2675      282525 :     move16();
    2676      282525 :     hDiracDecBin->q_processMtxSCCR = hDiracDecBin->q_processMtx;
    2677      282525 :     move16();
    2678      282525 :     hDiracDecBin->q_processMtxPrevSCCR = hDiracDecBin->q_processMtxPrev;
    2679      282525 :     move16();
    2680      282525 :     minimum_s( q_processMtxDec, nBins, &hDiracDecBin->q_processMtxDec );
    2681      282525 :     minimum_s( q_processMtxDecPrev, nBins, &hDiracDecBin->q_processMtxDecPrev );
    2682             : 
    2683    14200945 :     FOR( bin = 0; bin < nBins; bin++ )
    2684             :     {
    2685    41755260 :         FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2686             :         {
    2687    83510520 :             FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2688             :             {
    2689    55673680 :                 hDiracDecBin->processMtxRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
    2690    55673680 :                 move16();
    2691    55673680 :                 hDiracDecBin->processMtxIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][chB][bin], sub( q_processMtx[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
    2692    55673680 :                 move16();
    2693    55673680 :                 hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
    2694    55673680 :                 move16();
    2695    55673680 :                 hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][chB][bin], sub( q_processMtxPrev[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
    2696    55673680 :                 move16();
    2697    55673680 :                 hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRe_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); // hDiracDecBin->q_processMtxDec
    2698    55673680 :                 move16();
    2699    55673680 :                 hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecIm_fx[chA][chB][bin], sub( q_processMtxDec[bin], hDiracDecBin->q_processMtxDec ) ); // hDiracDecBin->q_processMtxDec
    2700    55673680 :                 move16();
    2701    55673680 :                 hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); // hDiracDecBin->q_processMtxDecPrev
    2702    55673680 :                 move16();
    2703    55673680 :                 hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] = shr( hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin], sub( q_processMtxDecPrev[bin], hDiracDecBin->q_processMtxDecPrev ) ); // hDiracDecBin->q_processMtxDecPrev
    2704    55673680 :                 move16();
    2705             :             }
    2706    27836840 :             IF( separateCenterChannelRendering )
    2707             :             {
    2708     2275920 :                 FOR( chB = 0; chB < nchanSeparateChannels; chB++ )
    2709             :                 {
    2710     1374600 :                     hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxRe_fx[chA][chB + 2][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
    2711     1374600 :                     move16();
    2712     1374600 :                     hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxIm_fx[chA][chB + 2][bin], sub( q_processMtx_SCCR[bin], hDiracDecBin->q_processMtx ) ); // hDiracDecBin->q_processMtx
    2713     1374600 :                     move16();
    2714     1374600 :                     hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxRePrev_fx[chA][chB + 2][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
    2715     1374600 :                     move16();
    2716     1374600 :                     hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin] = shr( hDiracDecBin->processMtxImPrev_fx[chA][chB + 2][bin], sub( q_processMtxPrev_SCCR[bin], hDiracDecBin->q_processMtxPrev ) ); // hDiracDecBin->q_processMtxPrev
    2717     1374600 :                     move16();
    2718             :                 }
    2719             :             }
    2720             :         }
    2721             :     }
    2722             : 
    2723      282525 :     return;
    2724             : }
    2725             : 
    2726      282525 : static void ivas_dirac_dec_binaural_process_output_fx(
    2727             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    2728             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    2729             :     HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS],
    2730             :     Word32 *output_fx[], /*q_out*/
    2731             :     Word16 *q_out,
    2732             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_input*/
    2733             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_input*/
    2734             :     const Word16 q_input,
    2735             :     const Word16 max_band_decorr,
    2736             :     const Word16 numInChannels,
    2737             :     const Word16 processReverb,
    2738             :     const Word16 subframe,
    2739             :     const Word16 q_mat,
    2740             :     Word32 outRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2741             :     Word32 outIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2742             :     Word32 reverbRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2743             :     Word32 reverbIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2744             :     Word32 decorrRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2745             :     Word32 decorrIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2746             :     Word16 *Q_inp_mix,
    2747             :     const Word8 recompute )
    2748             : {
    2749             :     Word16 slot, bin, chA, chB;
    2750             :     Word16 nBins;
    2751             :     Word16 offsetSamples;
    2752             :     Word16 nSlots;
    2753             : 
    2754      282525 :     nBins = hSpatParamRendCom->num_freq_bands;
    2755      282525 :     offsetSamples = 0;
    2756      282525 :     nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
    2757      282525 :     move16();
    2758      282525 :     move16();
    2759      282525 :     move16();
    2760             : 
    2761             :     Word32 decSlotRe_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm_fx[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    2762             :     Word32 outSlotRe_fx[CLDFB_NO_CHANNELS_MAX], outSlotIm_fx[CLDFB_NO_CHANNELS_MAX];
    2763             :     Word16 q_inp[6][CLDFB_SLOTS_PER_SUBFRAME];
    2764             :     Word16 interpVal_fx;
    2765             :     Word32 *decSlotRePointer_fx;
    2766             :     Word32 *decSlotImPointer_fx;
    2767      282525 :     Word16 q_inp_mix, q_reverb = 31;
    2768      282525 :     move16();
    2769      282525 :     Word16 ch_len = s_max( 4, numInChannels );
    2770             :     Word16 eff_q;
    2771             : 
    2772             : 
    2773      282525 :     IF( processReverb )
    2774             :     {
    2775      118411 :         if ( recompute == 1 )
    2776             :         {
    2777             :             /* Process second / room effect part of binaural output when needed */
    2778      118411 :             ivas_binaural_reverb_processSubframe_fx( hDiracDecBin->hReverb, numInChannels, nSlots, inRe_fx, inIm_fx, reverbRe_fx, reverbIm_fx );
    2779             :         }
    2780             :     }
    2781             : 
    2782      282525 :     IF( EQ_16( recompute, 1 ) )
    2783             :     {
    2784             :         // scaling input and reverb to same q//
    2785             :         // input scaling is to maintain precision in ivas_dirac_dec_decorrelate_slot fn//
    2786      282525 :         Word16 shift = s_min( L_norm_arr( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length ), L_norm_arr( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length ) );
    2787      282525 :         q_inp_mix = 31;
    2788      282525 :         move16();
    2789             : 
    2790     1414793 :         FOR( Word16 i = 0; i < ch_len; i++ )
    2791             : 
    2792             :         {
    2793     5646832 :             FOR( Word16 j = 0; j < nSlots; j++ )
    2794             :             {
    2795     4514564 :                 q_inp[i][j] = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) );
    2796     4514564 :                 move16();
    2797     4514564 :                 test();
    2798     4514564 :                 IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) )
    2799             :                 {
    2800      942500 :                     q_reverb = s_min( L_norm_arr( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX ), L_norm_arr( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX ) );
    2801      942500 :                     q_inp[i][j] = s_min( q_reverb, q_inp[i][j] );
    2802      942500 :                     move16();
    2803             :                 }
    2804     4514564 :                 q_inp_mix = s_min( q_inp[i][j], q_inp_mix );
    2805             :             }
    2806             :         }
    2807             : 
    2808      282525 :         q_inp_mix = sub( q_inp_mix, 3 ); // gaurded bits//
    2809             : 
    2810      282525 :         Word16 cldfb_state_shift = sub( add( add( q_inp_mix, q_mat ), sub( q_input, 16 ) ), cldfbSynDec[0]->Q_cldfb_state );
    2811      282525 :         IF( GT_16( cldfb_state_shift, shift ) )
    2812             :         {
    2813           0 :             q_inp_mix = sub( add( q_inp_mix, shift ), cldfb_state_shift );
    2814           0 :             cldfb_state_shift = shift;
    2815           0 :             move16();
    2816             :         }
    2817             : 
    2818             : 
    2819      282525 :         eff_q = sub( add( q_inp_mix, q_mat ), 15 );
    2820             : 
    2821     1414793 :         FOR( Word16 i = 0; i < ch_len; i++ )
    2822             : 
    2823             :         {
    2824     5646832 :             FOR( Word16 j = 0; j < nSlots; j++ )
    2825             :             {
    2826             : 
    2827     4514564 :                 scale_sig32( inRe_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/
    2828     4514564 :                 scale_sig32( inIm_fx[i][j], nBins, q_inp_mix ); /*q_input + q_inp_mix*/
    2829     4514564 :                 test();
    2830     4514564 :                 IF( ( processReverb && EQ_16( recompute, 1 ) ) && LT_16( i, 2 ) )
    2831             :                 {
    2832      942500 :                     scale_sig32( reverbRe_fx[i][j], CLDFB_NO_CHANNELS_MAX, eff_q ); /*q_inp_mix+q_mat-15*/
    2833      942500 :                     scale_sig32( reverbIm_fx[i][j], CLDFB_NO_CHANNELS_MAX, eff_q ); /*q_inp_mix+q_mat-15*/
    2834             :                 }
    2835             :             }
    2836             :         }
    2837             : 
    2838             :         // scaling cldfb states to q_result-1//
    2839      282525 :         scale_sig32( cldfbSynDec[0]->cldfb_state_fx, cldfbSynDec[0]->p_filter_length, cldfb_state_shift );
    2840      282525 :         cldfbSynDec[0]->Q_cldfb_state = add( cldfbSynDec[0]->Q_cldfb_state, cldfb_state_shift );
    2841      282525 :         scale_sig32( cldfbSynDec[1]->cldfb_state_fx, cldfbSynDec[1]->p_filter_length, cldfb_state_shift );
    2842      282525 :         cldfbSynDec[1]->Q_cldfb_state = add( cldfbSynDec[1]->Q_cldfb_state, cldfb_state_shift );
    2843      282525 :         move16();
    2844      282525 :         move16();
    2845      282525 :         *Q_inp_mix = q_inp_mix;
    2846      282525 :         move16();
    2847             :     }
    2848             :     ELSE
    2849             :     {
    2850           0 :         q_inp_mix = *Q_inp_mix;
    2851             :     }
    2852             : 
    2853      282525 :     q_inp_mix = add( q_inp_mix, q_input );
    2854             : 
    2855      282525 :     interpVal_fx = 0;
    2856      282525 :     move16();
    2857      282525 :     Word16 q_result = sub( add( q_inp_mix, q_mat ), 15 ); // setting it prior//
    2858      282525 :     cldfbSynDec[0]->Q_cldfb_state = sub( q_result, 1 );
    2859      282525 :     cldfbSynDec[1]->Q_cldfb_state = sub( q_result, 1 );
    2860      282525 :     move16();
    2861      282525 :     move16();
    2862             : 
    2863     1409046 :     FOR( slot = 0; slot < nSlots; slot++ )
    2864             :     {
    2865     1126521 :         IF( NE_16( slot, sub( nSlots, 1 ) ) )
    2866             :         {
    2867      843996 :             interpVal_fx = add( interpVal_fx, slot_fx[nSlots - 1] ); /*Q15*/
    2868             :         }
    2869             :         ELSE
    2870             :         {
    2871      282525 :             interpVal_fx = 32767; /*Q15*/
    2872      282525 :             move16();
    2873             :         }
    2874     1126521 :         test();
    2875     1126521 :         IF( !hDiracDecBin->useTdDecorr && ( max_band_decorr > 0 ) )
    2876             :         {
    2877      564275 :             if ( recompute == 1 )
    2878             :             {
    2879      564275 :                 ivas_dirac_dec_decorrelate_slot_fx( hDiracDecBin, nBins, slot, inRe_fx, inIm_fx, q_inp_mix, decSlotRe_fx, decSlotIm_fx );
    2880     1692825 :                 FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2881             :                 {
    2882     1128550 :                     Copy32( decSlotRe_fx[chA], decorrRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
    2883     1128550 :                     Copy32( decSlotIm_fx[chA], decorrIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
    2884             :                 }
    2885             :             }
    2886             :             else
    2887             :             {
    2888           0 :                 FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2889             :                 {
    2890           0 :                     Copy32( decorrRe_fx[chA][slot], decSlotRe_fx[chA], CLDFB_NO_CHANNELS_MAX );
    2891           0 :                     Copy32( decorrIm_fx[chA][slot], decSlotIm_fx[chA], CLDFB_NO_CHANNELS_MAX );
    2892             :                 }
    2893             :             }
    2894             :         }
    2895             : 
    2896     3379563 :         FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2897             :         {
    2898             :             Word32 *outSlotRePr_fx, *outSlotImPr_fx; /* Pointers needed for function call compatibility */
    2899             : 
    2900     2253042 :             set_zero_fx( outSlotRe_fx, CLDFB_NO_CHANNELS_MAX );
    2901     2253042 :             set_zero_fx( outSlotIm_fx, CLDFB_NO_CHANNELS_MAX );
    2902             : 
    2903             :             /* Processing of the first / HRTF part of the binaural output. */
    2904     6873178 :             FOR( chB = 0; chB < numInChannels; chB++ )
    2905             :             {
    2906     4620136 :                 IF( LT_16( chB, BINAURAL_CHANNELS ) )
    2907             :                 {
    2908             :                     /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs.
    2909             :                      * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this
    2910             :                      * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the
    2911             :                      * pointers to buffers. */
    2912     4506084 :                     IF( hDiracDecBin->useTdDecorr )
    2913             :                     {
    2914     1739892 :                         decSlotRePointer_fx = inRe_fx[chB + 2][slot];
    2915     1739892 :                         decSlotImPointer_fx = inIm_fx[chB + 2][slot];
    2916             :                     }
    2917             :                     ELSE
    2918             :                     {
    2919     2766192 :                         decSlotRePointer_fx = decSlotRe_fx[chB];
    2920     2766192 :                         decSlotImPointer_fx = decSlotIm_fx[chB];
    2921             :                     }
    2922             :                 }
    2923             :                 ELSE
    2924             :                 {
    2925      114052 :                     decSlotRePointer_fx = NULL; /* below these pointers are used only for chB < 2 */
    2926      114052 :                     decSlotImPointer_fx = NULL;
    2927             :                 }
    2928             : 
    2929             : 
    2930   232019736 :                 FOR( bin = 0; bin < nBins; bin++ )
    2931             :                 {
    2932             :                     Word16 gain;
    2933             :                     /* Mixing using the formulated processing matrix M */
    2934   227399600 :                     gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxRe_fx[chA][chB][bin] ) ); // Q11
    2935             : 
    2936   227399600 :                     outSlotRe_fx[bin] = Madd_32_16( outSlotRe_fx[bin], inRe_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
    2937   227399600 :                     outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], inIm_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
    2938   227399600 :                     move32();
    2939   227399600 :                     move32();
    2940             : 
    2941   227399600 :                     gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxIm_fx[chA][chB][bin] ) ); // Q11
    2942             : 
    2943             :                     // interpVal * hDiracDecBin->processMtxIm[chA][chB][bin];
    2944   227399600 :                     outSlotRe_fx[bin] = Msub_32_16( outSlotRe_fx[bin], inIm_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
    2945   227399600 :                     outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], inRe_fx[chB][slot][bin], gain ); // q_inp_mix-4//q_result
    2946             : 
    2947   227399600 :                     move32();
    2948   227399600 :                     move32();
    2949             : 
    2950             :                     /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */
    2951   227399600 :                     test();
    2952   227399600 :                     IF( LT_16( bin, max_band_decorr ) && LT_16( chB, 2 ) )
    2953             :                     {
    2954   119554900 :                         gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecRePrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecRe_fx[chA][chB][bin] ) ); // Q11
    2955             :                         // interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin];
    2956   119554900 :                         outSlotRe_fx[bin] = Madd_32_16( outSlotRe_fx[bin], decSlotRePointer_fx[bin], gain ); // q_inp_mix-4//q_result
    2957   119554900 :                         outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotImPointer_fx[bin], gain ); // q_inp_mix-4//q_result
    2958   119554900 :                         move32();
    2959   119554900 :                         move32();
    2960             : 
    2961             : 
    2962   119554900 :                         gain = add( mult( sub( 32767, interpVal_fx ), hDiracDecBin->processMtxDecImPrev_fx[chA][chB][bin] ), mult( interpVal_fx, hDiracDecBin->processMtxDecIm_fx[chA][chB][bin] ) ); // Q11
    2963   119554900 :                         outSlotRe_fx[bin] = Msub_32_16( outSlotRe_fx[bin], decSlotImPointer_fx[bin], gain );                                                                                          // q_inp_mix-4//q_result
    2964   119554900 :                         outSlotIm_fx[bin] = Madd_32_16( outSlotIm_fx[bin], decSlotRePointer_fx[bin], gain );                                                                                          // q_inp_mix-4//q_result
    2965   119554900 :                         move32();
    2966   119554900 :                         move32();
    2967             :                     }
    2968             :                 }
    2969             :             }
    2970             : 
    2971             : 
    2972     2253042 :             IF( processReverb )
    2973             :             {
    2974             :                 /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */
    2975      942500 :                 v_add_fx( outSlotRe_fx, reverbRe_fx[chA][slot], outSlotRe_fx, CLDFB_NO_CHANNELS_MAX );
    2976      942500 :                 v_add_fx( outSlotIm_fx, reverbIm_fx[chA][slot], outSlotIm_fx, CLDFB_NO_CHANNELS_MAX );
    2977             :             }
    2978             : 
    2979             : 
    2980     2253042 :             outSlotRePr_fx = &( outSlotRe_fx[0] );
    2981     2253042 :             outSlotImPr_fx = &( outSlotIm_fx[0] );
    2982             : 
    2983     2253042 :             IF( outRe_fx != NULL && outIm_fx != NULL )
    2984             :             {
    2985             :                 /* provide the data outside in CLDFB domain => mainly for split rendering */
    2986           0 :                 Copy32( outSlotRePr_fx, outRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
    2987           0 :                 Copy32( outSlotImPr_fx, outIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX );
    2988           0 :                 Scale_sig32( outRe_fx[chA][slot], CLDFB_NO_CHANNELS_MAX, sub( Q6, q_result ) ); // Q6
    2989           0 :                 Scale_sig32( outIm_fx[chA][slot], CLDFB_NO_CHANNELS_MAX, sub( Q6, q_result ) ); // Q6
    2990             :             }
    2991     2253042 :             if ( recompute == 1 )
    2992             :             {
    2993             :                 /* Inverse filter bank */
    2994     2253042 :                 cldfbSynthesis_ivas_fx( &outSlotRePr_fx, &outSlotImPr_fx, &( output_fx[chA][nBins * slot + offsetSamples] ), nBins, 0, 0, cldfbSynDec[chA] );
    2995     2253042 :                 cldfbSynDec[chA]->Q_cldfb_state = sub( q_result, 1 );
    2996     2253042 :                 move16();
    2997             :             }
    2998             :         }
    2999             :     }
    3000      282525 :     if ( recompute == 1 )
    3001             :     {
    3002      282525 :         *q_out = sub( q_result, 1 );
    3003      282525 :         move16();
    3004             :     }
    3005             : 
    3006      282525 :     return;
    3007             : }
    3008             : 
    3009             : 
    3010       72000 : static void adaptTransportSignalsHeadtracked_fx(
    3011             :     COMBINED_ORIENTATION_HANDLE hHeadTrackData,
    3012             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
    3013             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*q_inp*/
    3014             :     Word16 q_inp,
    3015             :     const Word16 nBins,
    3016             :     const Word16 nSlots,
    3017             :     Word32 Rmat[3][3] /*Q30*/ )
    3018             : {
    3019             :     Word16 slot, ch, bin, louderCh;
    3020             :     Word32 mono_factor_ILD, mono_factor;
    3021             :     Word32 y_val, mono_factor_rotation, ene_proc, ene_target, ILD;
    3022             :     Word16 ene_proc_e, ene_target_e;
    3023             :     Word16 max_band;
    3024             :     Word32 eqVal;
    3025       72000 :     Word16 band_idx, bin_lo, bin_hi, norm, shift = 31;
    3026             :     Word32 temp_div;
    3027             :     Word16 e_div, is_zero, i;
    3028       72000 :     move16();
    3029             : 
    3030      216000 :     FOR( i = 0; i < 2; i++ )
    3031             :     {
    3032      720000 :         FOR( Word16 j = 0; j < nSlots; j++ )
    3033             :         {
    3034      576000 :             norm = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) );
    3035      576000 :             shift = s_min( norm, shift );
    3036             :         }
    3037             :     }
    3038             : 
    3039             :     /* Determine head-orientation-based mono factor.
    3040             :     Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */
    3041             : 
    3042       72000 :     y_val = L_sub( ONE_IN_Q30, L_abs( Rmat[1][1] ) );                                                        // Q30
    3043       72000 :     mono_factor_rotation = Mpy_32_16_1( L_sub( y_val, ADAPT_HTPROTO_ROT_LIM_0_FX ), TWO_POINT_FIVE_IN_Q13 ); // Q28
    3044       72000 :     mono_factor_rotation = L_max( 0, L_min( ONE_IN_Q28, mono_factor_rotation ) );
    3045             : 
    3046       72000 :     IF( EQ_32( mono_factor_rotation, ONE_IN_Q28 ) )
    3047             :     {
    3048       19453 :         mono_factor_rotation = ONE_IN_Q31;
    3049             :     }
    3050             :     ELSE
    3051             :     {
    3052       52547 :         mono_factor_rotation = L_shl( mono_factor_rotation, 3 ); // Q31
    3053             :     }
    3054       72000 :     move32();
    3055             : 
    3056             :     /* Adapt transport signals in frequency bands */
    3057             :     /* optimization grouping CLDFB bins into MASA bands (they are readily available in ROM and suitable for the task) AND group CLDFB slots into sub-frames */
    3058             : 
    3059       72000 :     max_band = 0;
    3060       72000 :     move16();
    3061     1746000 :     WHILE( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
    3062             :     {
    3063     1674000 :         max_band = add( max_band, 1 );
    3064             :     }
    3065             : 
    3066       72000 :     shift = sub( shift, 5 );
    3067             :     // 5 is gaurded bits needed//
    3068             :     Word32 re, img, temp;
    3069             :     Word16 s, q_band_nrg, q_temp[2];
    3070     1746000 :     FOR( band_idx = 0; band_idx < max_band; band_idx++ )
    3071             :     {
    3072             :         Word32 ch_nrg[2];   /* storage for input signal channel energies */
    3073             :         Word64 W_ch_nrg[2]; /* storage for input signal channel energies */
    3074     1674000 :         bin_lo = MASA_band_grouping_24[band_idx];
    3075     1674000 :         bin_hi = s_min( MASA_band_grouping_24[band_idx + 1], (Word16) nBins );
    3076             : 
    3077     5022000 :         FOR( ch = 0; ch < 2; ch++ )
    3078             :         {
    3079     3348000 :             W_ch_nrg[ch] = 0;
    3080     3348000 :             move32();
    3081    16740000 :             FOR( slot = 0; slot < nSlots; slot++ )
    3082             :             {
    3083    39312000 :                 FOR( bin = bin_lo; bin < bin_hi; bin++ )
    3084             :                 {
    3085    25920000 :                     re = L_shl( inRe_fx[ch][slot][bin], shift );
    3086    25920000 :                     img = L_shl( inIm_fx[ch][slot][bin], shift );
    3087             : 
    3088    25920000 :                     W_ch_nrg[ch] = W_add( W_ch_nrg[ch], ( W_add( W_mult0_32_32( re, re ), W_mult0_32_32( img, img ) ) ) ); // 2(q_inp +shift)
    3089    25920000 :                     move64();
    3090             :                 }
    3091             :             }
    3092     3348000 :             s = W_norm( W_ch_nrg[ch] );
    3093     3348000 :             ch_nrg[ch] = W_extract_h( W_shl( W_ch_nrg[ch], s ) ); // Q: 2*(q_inp+shift) + s - 32
    3094     3348000 :             q_temp[ch] = sub( add( shl( add( q_inp, shift ), 1 ), s ), 32 );
    3095     3348000 :             move32();
    3096     3348000 :             move16();
    3097             : 
    3098     3348000 :             hHeadTrackData->chEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->chEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_chEneIIR
    3099     3348000 :             move32();
    3100     3348000 :             temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); // q_temp[ch]
    3101     3348000 :             IF( LT_16( hHeadTrackData->q_chEneIIR[ch][band_idx], q_temp[ch] ) )
    3102             :             {
    3103     3293874 :                 hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp[ch], hHeadTrackData->q_chEneIIR[ch][band_idx] ) ), hHeadTrackData->chEneIIR_fx[ch][band_idx] ); // hHeadTrackData->q_chEneIIR[ch][band_idx]
    3104             :             }
    3105             :             ELSE
    3106             :             {
    3107       54126 :                 hHeadTrackData->chEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->chEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_chEneIIR[ch][band_idx], q_temp[ch] ) ), temp ); // q_temp[ch]
    3108             :             }
    3109     3348000 :             move32();
    3110     3348000 :             hHeadTrackData->q_chEneIIR[ch][band_idx] = s_min( hHeadTrackData->q_chEneIIR[ch][band_idx], q_temp[ch] );
    3111     3348000 :             move16();
    3112             :         }
    3113             :         /* Determine ILD */
    3114             : 
    3115     1674000 :         IF( EQ_32( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ) ) )
    3116             :         {
    3117        2272 :             ILD = 0;
    3118        2272 :             move32();
    3119             :         }
    3120             :         ELSE
    3121             :         {
    3122     1671728 :             temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( L_max( 1, hHeadTrackData->chEneIIR_fx[0][band_idx] ), L_max( 1, hHeadTrackData->chEneIIR_fx[1][band_idx] ), &e_div ) );
    3123     1671728 :             e_div = add( e_div, sub( hHeadTrackData->q_chEneIIR[1][band_idx], hHeadTrackData->q_chEneIIR[0][band_idx] ) );
    3124     1671728 :             temp = BASOP_Util_Log2( temp_div ); // Q25
    3125     1671728 :             IF( e_div > 0 )
    3126             :             {
    3127      795388 :                 temp = L_add( temp, L_shl( e_div, 25 ) ); // Q25
    3128             :             }
    3129             :             ELSE
    3130             :             {
    3131      876340 :                 temp = L_sub( temp, L_shl( L_abs( e_div ), 25 ) ); // Q25
    3132             :             }
    3133             : 
    3134     1671728 :             temp = Mpy_32_32( temp, 646462464 );       // logx base 10 = 0.30103* logx base 2//
    3135     1671728 :             ILD = L_abs( Mpy_32_16_1( temp, 20480 ) ); // Q21
    3136             :         }
    3137     1674000 :         IF( BASOP_Util_Cmp_Mant32Exp( hHeadTrackData->chEneIIR_fx[1][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[1][band_idx] ), hHeadTrackData->chEneIIR_fx[0][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[0][band_idx] ) ) > 0 )
    3138             :         {
    3139     1155432 :             louderCh = 1;
    3140             :         }
    3141             :         ELSE
    3142             :         {
    3143      518568 :             louderCh = 0;
    3144             :         }
    3145     1674000 :         move16();
    3146             : 
    3147             :         /* Determine ILD-based mono factor */
    3148     1674000 :         mono_factor_ILD = Mpy_32_16_1( L_sub( ILD, ONE_IN_Q21 ), 10911 ); // Q21
    3149             : 
    3150     1674000 :         mono_factor_ILD = L_max( 0, L_min( ONE_IN_Q21, mono_factor_ILD ) ); // Q21
    3151             : 
    3152     1674000 :         IF( EQ_32( mono_factor_ILD, ONE_IN_Q21 ) )
    3153             :         {
    3154      697078 :             mono_factor_ILD = ONE_IN_Q31;
    3155      697078 :             move32();
    3156             :         }
    3157             :         ELSE
    3158             :         {
    3159      976922 :             mono_factor_ILD = L_shl( mono_factor_ILD, 10 ); // Q31
    3160             :         }
    3161             : 
    3162             :         /* Combine mono factors */
    3163     1674000 :         mono_factor = Mpy_32_32( mono_factor_ILD, mono_factor_rotation ); // Q31
    3164             : 
    3165             :         /* Mix original audio and sum signal according to determined mono factor */
    3166     5022000 :         FOR( ch = 0; ch < 2; ch++ )
    3167             :         {
    3168     3348000 :             IF( NE_16( ch, louderCh ) )
    3169             :             {
    3170             :                 Word32 band_nrg;
    3171     1674000 :                 Word64 W_band_nrg = 0;
    3172     1674000 :                 move64();
    3173             : 
    3174     8370000 :                 FOR( slot = 0; slot < nSlots; slot++ )
    3175             :                 {
    3176    19656000 :                     FOR( bin = bin_lo; bin < bin_hi; bin++ )
    3177             :                     {
    3178             :                         /* mono sum signal with the computed weight + rest from the original channel */
    3179    12960000 :                         inRe_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inRe_fx[0][slot][bin], inRe_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inRe_fx[ch][slot][bin] ) ) );
    3180    12960000 :                         inIm_fx[ch][slot][bin] = L_add( ( Mpy_32_32( mono_factor, L_add( inIm_fx[0][slot][bin], inIm_fx[1][slot][bin] ) ) ), ( Mpy_32_32( L_sub( ONE_IN_Q31, mono_factor ), inIm_fx[ch][slot][bin] ) ) );
    3181    12960000 :                         move32();
    3182    12960000 :                         move32();
    3183    12960000 :                         re = L_shl( inRe_fx[ch][slot][bin], shift );  // q_inp +shift
    3184    12960000 :                         img = L_shl( inIm_fx[ch][slot][bin], shift ); // q_inp +shift
    3185             : 
    3186    12960000 :                         W_band_nrg = W_add( W_band_nrg, ( W_add( W_mult0_32_32( re, re ), W_mult0_32_32( img, img ) ) ) ); // 2(q_inp + shift)
    3187             :                     }
    3188             :                 }
    3189     1674000 :                 s = W_norm( W_band_nrg );
    3190     1674000 :                 band_nrg = W_extract_h( W_shl( W_band_nrg, s ) ); // Q: 2*(q_inp+shift) + s - 32
    3191     1674000 :                 q_band_nrg = sub( add( shl( add( q_inp, shift ), 1 ), s ), 32 );
    3192             : 
    3193     1674000 :                 hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // hHeadTrackData->q_procChEneIIR[ch][band_idx]
    3194     1674000 :                 move32();
    3195             : 
    3196     1674000 :                 temp = Mpy_32_16_1( band_nrg, sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) ); // q_band_nrg
    3197     1674000 :                 IF( LT_16( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_band_nrg ) )
    3198             :                 {
    3199     1648613 :                     hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_band_nrg, hHeadTrackData->q_procChEneIIR[ch][band_idx] ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); // hHeadTrackData->q_procChEneIIR[ch][band_idx]
    3200             :                 }
    3201             :                 ELSE
    3202             :                 {
    3203       25387 :                     hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_band_nrg ) ), temp ); // q_band_nrg
    3204             :                 }
    3205     1674000 :                 move32();
    3206     1674000 :                 hHeadTrackData->q_procChEneIIR[ch][band_idx] = s_min( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_band_nrg );
    3207     1674000 :                 move16();
    3208             :             }
    3209             :             ELSE
    3210             :             {
    3211             :                 /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */
    3212     1674000 :                 hHeadTrackData->procChEneIIR_fx[ch][band_idx] = Mpy_32_16_1( hHeadTrackData->procChEneIIR_fx[ch][band_idx], ADAPT_HTPROTO_IIR_FAC_FX ); // q_procChEneIIR
    3213     1674000 :                 move32();
    3214             : 
    3215     1674000 :                 temp = Mpy_32_16_1( ch_nrg[ch], sub( 32767, ADAPT_HTPROTO_IIR_FAC_FX ) );
    3216     1674000 :                 IF( LT_16( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_temp[ch] ) )
    3217             :                 {
    3218     1643735 :                     hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( temp, sub( q_temp[ch], hHeadTrackData->q_procChEneIIR[ch][band_idx] ) ), hHeadTrackData->procChEneIIR_fx[ch][band_idx] ); // hHeadTrackData->q_procChEneIIR[ch][band_idx]
    3219             :                 }
    3220             :                 ELSE
    3221             :                 {
    3222       30265 :                     hHeadTrackData->procChEneIIR_fx[ch][band_idx] = L_add( L_shr( hHeadTrackData->procChEneIIR_fx[ch][band_idx], sub( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_temp[ch] ) ), temp ); // q_temp[ch]
    3223             :                 }
    3224     1674000 :                 move32();
    3225     1674000 :                 hHeadTrackData->q_procChEneIIR[ch][band_idx] = s_min( hHeadTrackData->q_procChEneIIR[ch][band_idx], q_temp[ch] );
    3226     1674000 :                 move16();
    3227             :             }
    3228             :         }
    3229             : 
    3230             :         /* Equalize */
    3231     1674000 :         ene_target = BASOP_Util_Add_Mant32Exp( hHeadTrackData->chEneIIR_fx[0][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[0][band_idx] ), hHeadTrackData->chEneIIR_fx[1][band_idx], sub( 31, hHeadTrackData->q_chEneIIR[1][band_idx] ), &ene_target_e );
    3232             : 
    3233     1674000 :         ene_proc = BASOP_Util_Add_Mant32Exp( hHeadTrackData->procChEneIIR_fx[0][band_idx], sub( 31, hHeadTrackData->q_procChEneIIR[0][band_idx] ), hHeadTrackData->procChEneIIR_fx[1][band_idx], sub( 31, hHeadTrackData->q_procChEneIIR[1][band_idx] ), &ene_proc_e );
    3234             : 
    3235     1674000 :         temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( ene_target, L_max( 1, ene_proc ), &e_div ) );
    3236     1674000 :         e_div = add( e_div, sub( ene_target_e, ene_proc_e ) );
    3237             : 
    3238     1674000 :         eqVal = Sqrt32( temp_div, &e_div );
    3239             : 
    3240     1674000 :         Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eqVal, e_div );
    3241     1674000 :         IF( EQ_16( comp_flag, -1 ) )
    3242             :         {
    3243         321 :             eqVal = 1073741824; // 4inQ28
    3244         321 :             move32();
    3245             :         }
    3246             :         ELSE
    3247             :         {
    3248     1673679 :             eqVal = L_shl( eqVal, sub( e_div, 3 ) ); // Q28
    3249             :         }
    3250             : 
    3251     8370000 :         FOR( slot = 0; slot < nSlots; slot++ )
    3252             :         {
    3253    20088000 :             FOR( ch = 0; ch < 2; ch++ )
    3254             :             {
    3255    39312000 :                 FOR( bin = bin_lo; bin < bin_hi; bin++ )
    3256             :                 {
    3257    25920000 :                     Word16 temp_shift = s_min( norm_l( inRe_fx[ch][slot][bin] ), norm_l( inIm_fx[ch][slot][bin] ) );
    3258    25920000 :                     re = L_shl( inRe_fx[ch][slot][bin], temp_shift );
    3259    25920000 :                     img = L_shl( inIm_fx[ch][slot][bin], temp_shift );
    3260             : 
    3261    25920000 :                     re = L_shr( Mpy_32_32( re, eqVal ), sub( temp_shift, 3 ) );
    3262    25920000 :                     img = L_shr( Mpy_32_32( img, eqVal ), sub( temp_shift, 3 ) );
    3263    25920000 :                     inRe_fx[ch][slot][bin] = re;  // q_inp
    3264    25920000 :                     inIm_fx[ch][slot][bin] = img; // q_inp
    3265    25920000 :                     move32();
    3266    25920000 :                     move32();
    3267             :                 }
    3268             :             }
    3269             :         }
    3270             :     }
    3271             : 
    3272       72000 :     is_zero = 1;
    3273       72000 :     move16();
    3274       73139 :     FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    3275             :     {
    3276       73107 :         test();
    3277       73107 :         if ( ( hHeadTrackData->chEneIIR_fx[0][i] != 0 ) || ( hHeadTrackData->chEneIIR_fx[1][i] != 0 ) )
    3278             :         {
    3279       71968 :             is_zero = 0;
    3280       71968 :             move16();
    3281       71968 :             BREAK;
    3282             :         }
    3283             :     }
    3284       72000 :     IF( is_zero )
    3285             :     {
    3286          32 :         set16_fx( hHeadTrackData->q_chEneIIR[0], 31, MASA_FREQUENCY_BANDS );
    3287          32 :         set16_fx( hHeadTrackData->q_chEneIIR[1], 31, MASA_FREQUENCY_BANDS );
    3288             :     }
    3289             : 
    3290       72000 :     is_zero = 1;
    3291       72000 :     move16();
    3292       73194 :     FOR( i = 0; i < MASA_FREQUENCY_BANDS; i++ )
    3293             :     {
    3294       73162 :         test();
    3295       73162 :         if ( ( hHeadTrackData->procChEneIIR_fx[0][i] != 0 ) || ( hHeadTrackData->procChEneIIR_fx[1][i] != 0 ) )
    3296             :         {
    3297       71968 :             is_zero = 0;
    3298       71968 :             move16();
    3299       71968 :             BREAK;
    3300             :         }
    3301             :     }
    3302       72000 :     IF( is_zero )
    3303             :     {
    3304          32 :         set16_fx( hHeadTrackData->q_procChEneIIR[0], 31, MASA_FREQUENCY_BANDS );
    3305          32 :         set16_fx( hHeadTrackData->q_procChEneIIR[1], 31, MASA_FREQUENCY_BANDS );
    3306             :     }
    3307             : 
    3308       72000 :     return;
    3309             : }
    3310             : 
    3311             : 
    3312       72000 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx(
    3313             :     COMBINED_ORIENTATION_HANDLE hHeadTrackData,
    3314             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    3315             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    3316             :     const Word16 nBins,
    3317             :     const Word16 nSlots,
    3318             :     Word32 Rmat_fx[3][3] /*Q30*/ )
    3319             : {
    3320             :     Word16 slot, bin, ch;
    3321             :     Word32 tmpVal;
    3322       72000 :     Word16 norm, e_div, shift = 31;
    3323       72000 :     move16();
    3324             :     Word32 Re, Im, temp_div;
    3325             : 
    3326             :     /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */
    3327       72000 :     IF( EQ_16( hHeadTrackData->lrSwitchedNext, hHeadTrackData->lrSwitchedCurrent ) )
    3328             :     {
    3329       65108 :         Word32 thresholdDotProduct = 182536112; // 0.17 in Q30//       /* Corresponds to 10-degree switching threshold */
    3330       65108 :         move32();
    3331       65108 :         test();
    3332       65108 :         if ( hHeadTrackData->lrSwitchedCurrent == 0 && ( LT_32( Rmat_fx[1][1], L_negate( thresholdDotProduct ) ) ) )
    3333             :         {
    3334          38 :             hHeadTrackData->lrSwitchedNext = 1;
    3335          38 :             move16();
    3336             :         }
    3337       65108 :         test();
    3338       65108 :         if ( EQ_16( hHeadTrackData->lrSwitchedCurrent, 1 ) && ( GT_32( Rmat_fx[1][1], thresholdDotProduct ) ) )
    3339             :         {
    3340          32 :             hHeadTrackData->lrSwitchedNext = 0;
    3341          32 :             move16();
    3342             :         }
    3343             :     }
    3344             : 
    3345      216000 :     FOR( Word16 i = 0; i < 2; i++ )
    3346             :     {
    3347      720000 :         FOR( Word16 j = 0; j < nSlots; j++ )
    3348             :         {
    3349      576000 :             norm = s_min( L_norm_arr( inRe_fx[i][j], nBins ), L_norm_arr( inIm_fx[i][j], nBins ) );
    3350      576000 :             shift = s_min( norm, shift );
    3351             :         }
    3352             :     }
    3353             : 
    3354       72000 :     shift = sub( shift, 3 ); // guard bits//
    3355             :                              /* When currently in interpolation */
    3356       72000 :     IF( NE_16( hHeadTrackData->lrSwitchedNext, hHeadTrackData->lrSwitchedCurrent ) )
    3357             :     {
    3358       34810 :         FOR( slot = 0; slot < nSlots; slot++ )
    3359             :         {
    3360             :             Word32 switchOrderFactor, origOrderFactor;
    3361             :             Word16 e_switchOrderFactor, e_origOrderFactor;
    3362             : 
    3363       27848 :             hHeadTrackData->lrSwitchInterpVal_fx = L_add( hHeadTrackData->lrSwitchInterpVal_fx, 2684354 /* 0.0025f in Q30 */ ); /* Corresponds to 0.5 seconds interpolation time */ /* Q30 */
    3364       27848 :             move32();
    3365             : 
    3366       27848 :             IF( GT_32( hHeadTrackData->lrSwitchInterpVal_fx, 1072668096 /* 0.999f in Q30 */ ) )
    3367             :             {
    3368             :                 /* Stop interpolation, reset values */
    3369          68 :                 hHeadTrackData->lrSwitchInterpVal_fx = 0;
    3370          68 :                 hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext;
    3371          68 :                 move32();
    3372          68 :                 move16();
    3373             :             }
    3374             : 
    3375             :             /* Gains for determining portion of switched channel order and original channel order */
    3376       27848 :             tmpVal = Mpy_32_16_1( hHeadTrackData->lrSwitchInterpVal_fx, (Word16) hHeadTrackData->lrSwitchedNext );                                          /* Q15 */
    3377       27848 :             tmpVal = L_add( tmpVal, Mpy_32_16_1( L_sub( ONE_IN_Q30, hHeadTrackData->lrSwitchInterpVal_fx ), (Word16) hHeadTrackData->lrSwitchedCurrent ) ); /* Q15 */
    3378             : 
    3379       27848 :             e_switchOrderFactor = 0;
    3380       27848 :             e_origOrderFactor = 0;
    3381       27848 :             move16();
    3382       27848 :             move16();
    3383       27848 :             IF( EQ_32( tmpVal, 32768 ) )
    3384             :             {
    3385          38 :                 tmpVal = ONE_IN_Q31;
    3386          38 :                 move32();
    3387             :             }
    3388             :             ELSE
    3389       27810 :                 tmpVal = L_shl( tmpVal, 16 ); // Q31
    3390       27848 :             switchOrderFactor = Sqrt32( tmpVal, &e_switchOrderFactor );
    3391       27848 :             switchOrderFactor = L_shl( switchOrderFactor, e_switchOrderFactor );         // Q31
    3392       27848 :             origOrderFactor = Sqrt32( L_sub( ONE_IN_Q31, tmpVal ), &e_origOrderFactor ); // Q31
    3393       27848 :             origOrderFactor = L_shl( origOrderFactor, e_origOrderFactor );
    3394     1298728 :             FOR( bin = 0; bin < nBins; bin++ )
    3395             :             {
    3396             :                 /* determine original order (1) signals and switched order (2) signals */
    3397             :                 Word32 re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS];
    3398             : 
    3399     3812640 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3400             :                 {
    3401     2541760 :                     re1[ch] = Mpy_32_32( inRe_fx[ch][slot][bin], origOrderFactor );       // q_inp
    3402     2541760 :                     re2[ch] = Mpy_32_32( inRe_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp
    3403     2541760 :                     im1[ch] = Mpy_32_32( inIm_fx[ch][slot][bin], origOrderFactor );       // q_inp
    3404     2541760 :                     im2[ch] = Mpy_32_32( inIm_fx[1 - ch][slot][bin], switchOrderFactor ); // q_inp
    3405     2541760 :                     move32();
    3406     2541760 :                     move32();
    3407     2541760 :                     move32();
    3408     2541760 :                     move32();
    3409             :                 }
    3410             : 
    3411     3812640 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3412             :                 {
    3413             :                     Word32 eneRef, ene, eq;
    3414             : 
    3415     2541760 :                     re1[ch] = L_shl( re1[ch], shift ); // q_inp+shift//
    3416     2541760 :                     re2[ch] = L_shl( re2[ch], shift ); // q_inp+shift//
    3417     2541760 :                     im1[ch] = L_shl( im1[ch], shift ); // q_inp+shift//
    3418     2541760 :                     im2[ch] = L_shl( im2[ch], shift ); // q_inp+shift//
    3419     2541760 :                     move32();
    3420     2541760 :                     move32();
    3421     2541760 :                     move32();
    3422     2541760 :                     move32();
    3423             : 
    3424             :                     /* Interpolate / mix original and switched order signals */
    3425     2541760 :                     Re = L_add( re1[ch], re2[ch] ); // q_inp+shift//
    3426     2541760 :                     Im = L_add( im1[ch], im2[ch] ); // q_inp+shift//
    3427             : 
    3428             :                     /* Equalize interpolated signals to preserve energy per bin */
    3429             : 
    3430     2541760 :                     eneRef = L_add( ( L_add( Mpy_32_32( re1[ch], re1[ch] ), Mpy_32_32( re2[ch], re2[ch] ) ) ), ( L_add( Mpy_32_32( im1[ch], im1[ch] ), Mpy_32_32( im2[ch], im2[ch] ) ) ) ); // 2*(q_inp+shift) -31//
    3431     2541760 :                     ene = L_add( Mpy_32_32( Re, Re ), Mpy_32_32( Im, Im ) );                                                                                                                // 2*(q_inp+shift) -31//
    3432             : 
    3433     2541760 :                     temp_div = L_deposit_h( BASOP_Util_Divide3232_Scale( eneRef, L_max( 1, ene ), &e_div ) );
    3434             : 
    3435     2541760 :                     eq = Sqrt32( temp_div, &e_div );
    3436             : 
    3437     2541760 :                     Word16 comp_flag = BASOP_Util_Cmp_Mant32Exp( 1073741824, 3, eq, e_div );
    3438     2541760 :                     IF( EQ_16( comp_flag, -1 ) )
    3439             :                     {
    3440       15385 :                         eq = 1073741824; // 4inQ28
    3441       15385 :                         move32();
    3442             :                     }
    3443             :                     ELSE
    3444             :                     {
    3445     2526375 :                         eq = L_shl( eq, sub( e_div, 3 ) ); // Q28
    3446             :                     }
    3447             : 
    3448     2541760 :                     Re = L_shr( Mpy_32_32( Re, eq ), sub( shift, 3 ) ); // q_inp
    3449     2541760 :                     Im = L_shr( Mpy_32_32( Im, eq ), sub( shift, 3 ) ); // q_inp
    3450             : 
    3451     2541760 :                     inRe_fx[ch][slot][bin] = Re;
    3452     2541760 :                     inIm_fx[ch][slot][bin] = Im;
    3453     2541760 :                     move32();
    3454     2541760 :                     move32();
    3455             :                 }
    3456             :             }
    3457             :         }
    3458             :     }
    3459             :     ELSE
    3460             :     {
    3461             :         /* If not in interpolation, but in switched prototype situation, then switch left and right channels */
    3462       65038 :         IF( EQ_16( hHeadTrackData->lrSwitchedCurrent, 1 ) )
    3463             :         {
    3464       37425 :             FOR( slot = 0; slot < nSlots; slot++ )
    3465             :             {
    3466     1333140 :                 FOR( bin = 0; bin < nBins; bin++ )
    3467             :                 {
    3468     1303200 :                     tmpVal = inRe_fx[0][slot][bin];
    3469     1303200 :                     inRe_fx[0][slot][bin] = inRe_fx[1][slot][bin];
    3470     1303200 :                     inRe_fx[1][slot][bin] = tmpVal;
    3471     1303200 :                     tmpVal = inIm_fx[0][slot][bin];
    3472     1303200 :                     inIm_fx[0][slot][bin] = inIm_fx[1][slot][bin];
    3473     1303200 :                     inIm_fx[1][slot][bin] = tmpVal;
    3474     1303200 :                     move32();
    3475     1303200 :                     move32();
    3476     1303200 :                     move32();
    3477     1303200 :                     move32();
    3478             :                 }
    3479             :             }
    3480             :         }
    3481             :     }
    3482             : 
    3483       72000 :     return;
    3484             : }
    3485             : 
    3486             : 
    3487    42829130 : static void eig2x2_fx(
    3488             :     const Word32 E1_fx, /*q_E*/
    3489             :     const Word32 E2_fx, /*q_E*/
    3490             :     Word16 q_E,
    3491             :     const Word32 Cre_fx, /*q_C*/
    3492             :     const Word32 Cim_fx, /*q_C*/
    3493             :     Word16 q_C,
    3494             :     Word32 Ure_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_U*/
    3495             :     Word32 Uim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_U*/
    3496             :     Word16 *q_U,
    3497             :     Word32 D_fx[BINAURAL_CHANNELS], /*q_D*/
    3498             :     Word16 *q_D )
    3499             : {
    3500             :     Word16 chA, chB, ch;
    3501             :     Word32 s_fx, normVal_fx, crossSquare_fx, a_fx, pm_fx, add_fx;
    3502             :     Word32 tmp1, tmp2, tmp3, e1, e2, c_re, c_im;
    3503             :     Word16 q_crossSquare, q_tmp1, q_tmp2, exp_tmp3, exp, q_e, q_c, q_U_1, q_U_2;
    3504    42829130 :     Word32 epsilon_mant = 1180591621;
    3505    42829130 :     Word16 epsilon_exp = -39;
    3506    42829130 :     move32();
    3507    42829130 :     move16();
    3508             : 
    3509    42829130 :     pm_fx = 0;
    3510    42829130 :     move32();
    3511    42829130 :     add_fx = 0;
    3512    42829130 :     move32();
    3513    42829130 :     q_tmp2 = 0;
    3514    42829130 :     move16();
    3515             : 
    3516   128487390 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    3517             :     {
    3518   256974780 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    3519             :         {
    3520   171316520 :             Ure_fx[chA][chB] = 0;
    3521   171316520 :             move32();
    3522   171316520 :             Uim_fx[chA][chB] = 0;
    3523   171316520 :             move32();
    3524             :         }
    3525             :     }
    3526             : 
    3527    42829130 :     exp = sub( get_min_scalefactor( Cre_fx, Cim_fx ), 2 );
    3528    42829130 :     c_re = L_shl( Cre_fx, exp );
    3529    42829130 :     c_im = L_shl( Cim_fx, exp );
    3530    42829130 :     q_c = add( q_C, exp );
    3531             : 
    3532    42829130 :     exp = sub( get_min_scalefactor( E1_fx, E2_fx ), 2 );
    3533    42829130 :     e1 = L_shl( E1_fx, exp );
    3534    42829130 :     e2 = L_shl( E2_fx, exp );
    3535    42829130 :     q_e = add( q_E, exp );
    3536             : 
    3537             :     /*crossSquare_fx = (c_re * c_re) + (c_im * c_im)
    3538             :     a_fx = (e1 + e2) * (e1 + e2) - 4.0f * ((e1 * e2) - crossSquare_fx) = (e1 - e2)^2 + 4 * crossSquare_fx
    3539             :     pm_fx = 0.5f * sqrtf(max(0.0f, a_fx))
    3540             :     add_fx = 0.5f * (e1 + e2)*/
    3541             : 
    3542    42829130 :     IF( L_and( c_re == 0, c_im == 0 ) )
    3543             :     {
    3544             :         /* if c_re = 0 and c_im = 0, then crossSquare_fx = (c_re * c_re) + (c_im * c_im) = 0
    3545             :         a_fx = (E1 - E2)^2
    3546             :         pm_fx = 0.5 * sqrt(max(0, a_fx)) = 0.5 * max(0, (e1 - e2)) */
    3547    11844223 :         crossSquare_fx = 0;
    3548    11844223 :         move32();
    3549    11844223 :         q_crossSquare = Q31;
    3550    11844223 :         move16();
    3551    11844223 :         pm_fx = L_shr( L_max( 0, L_abs( L_sub( e1, e2 ) ) ), 1 );
    3552    11844223 :         q_tmp2 = q_e;
    3553    11844223 :         move16();
    3554             :     }
    3555             :     ELSE
    3556             :     {
    3557    30984907 :         crossSquare_fx = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im );
    3558    30984907 :         q_crossSquare = sub( add( q_c, q_c ), 31 );
    3559    30984907 :         IF( EQ_32( e1, e2 ) )
    3560             :         {
    3561             :             /* if e1 - e2 = 0, then a_fx = 4 * crossSquare_fx
    3562             :             pm_fx = 0.5 * sqrt(max(0, 4 * crossSquare_fx)) =  sqrt(0, crossSquare_fx)*/
    3563     4290447 :             test();
    3564     4290447 :             test();
    3565     4290447 :             IF( EQ_32( c_re, 0 ) || LT_32( L_abs( c_re ), ONE_IN_Q15 ) )
    3566             :             {
    3567             :                 /* if c_re = 0, then crossSquare_fx = c_im^2 => pm_fx = max(0, c_im) */
    3568        8634 :                 pm_fx = L_max( 0, L_abs( c_im ) );
    3569        8634 :                 q_tmp2 = q_c;
    3570        8634 :                 move16();
    3571             :             }
    3572     4281813 :             ELSE IF( c_im == 0 || LT_32( L_abs( c_im ), ONE_IN_Q15 ) )
    3573             :             {
    3574             :                 /* if c_im = 0, then crossSquare_fx = c_re^2 => pm_fx = max(0, c_re) */
    3575     4246238 :                 pm_fx = L_max( 0, L_abs( c_re ) );
    3576     4246238 :                 q_tmp2 = q_c;
    3577     4246238 :                 move16();
    3578             :             }
    3579             :             ELSE
    3580             :             {
    3581       35575 :                 exp = sub( 31, q_crossSquare );
    3582       35575 :                 pm_fx = Sqrt32( L_max( 0, crossSquare_fx ), &exp );
    3583       35575 :                 q_tmp2 = sub( 31, exp );
    3584             :             }
    3585             :         }
    3586             :         ELSE
    3587             :         {
    3588             :             /* if e1, e2 >> c_re, c_im then (e1 - e2)^2 ~ (e1 - e2)^2 + 4 * crossSquare_fx
    3589             :                a_fx = (E1 - E2)^2
    3590             :                pm_fx = 0.5 * sqrt(max(0, a_fx)) = 0.5 * max(0, (e1 - e2)) */
    3591             : 
    3592    26694460 :             IF( GT_16( sub( q_c, q_e ), Q15 ) )
    3593             :             {
    3594       26962 :                 pm_fx = L_shr( L_max( 0, L_abs( L_sub( e1, e2 ) ) ), 1 );
    3595       26962 :                 q_tmp2 = q_e;
    3596       26962 :                 move16();
    3597             :             }
    3598             :             ELSE
    3599             :             {
    3600    26667498 :                 tmp2 = crossSquare_fx;
    3601    26667498 :                 move32();
    3602    26667498 :                 q_tmp2 = sub( q_crossSquare, 2 ); // crossSquare_fx = 4 * crossSquare_fx;
    3603             : 
    3604    26667498 :                 tmp1 = Mpy_32_32( L_sub( e1, e2 ), L_sub( e1, e2 ) );
    3605    26667498 :                 q_tmp1 = sub( add( q_e, q_e ), 31 );
    3606             : 
    3607    26667498 :                 a_fx = BASOP_Util_Add_Mant32Exp( tmp1, sub( 31, q_tmp1 ), tmp2, sub( 31, q_tmp2 ), &q_tmp2 ); // (E1 - E2)^2 + 4 * crossSquare_fx
    3608    26667498 :                 q_tmp2 = sub( 31, q_tmp2 );
    3609             : 
    3610    26667498 :                 exp = sub( 31, q_tmp2 );
    3611    26667498 :                 pm_fx = Sqrt32( L_max( 0, L_sub( a_fx, 1 ) ), &exp );
    3612    26667498 :                 pm_fx = L_shr( pm_fx, 1 );
    3613    26667498 :                 q_tmp2 = sub( 31, exp );
    3614             :             }
    3615             :         }
    3616             :     }
    3617             :     // add_fx = 0.5 * (e1 + e2)
    3618    42829130 :     add_fx = L_shr( L_add( e1, e2 ), 1 );
    3619    42829130 :     q_tmp1 = q_e;
    3620    42829130 :     move16();
    3621             : 
    3622    42829130 :     IF( LT_16( q_tmp1, q_tmp2 ) )
    3623             :     {
    3624    26760078 :         D_fx[0] = L_add( L_shr( add_fx, 1 ), L_shr( pm_fx, add( sub( q_tmp2, q_tmp1 ), 1 ) ) );
    3625    26760078 :         move32();
    3626    26760078 :         D_fx[1] = L_max( 0, L_sub( L_shr( add_fx, 1 ), L_shr( pm_fx, add( sub( q_tmp2, q_tmp1 ), 1 ) ) ) );
    3627    26760078 :         move32();
    3628    26760078 :         *q_D = sub( q_tmp1, 1 );
    3629    26760078 :         move16();
    3630             :     }
    3631             :     ELSE
    3632             :     {
    3633    16069052 :         D_fx[0] = L_add( L_shr( add_fx, add( sub( q_tmp1, q_tmp2 ), 1 ) ), L_shr( pm_fx, 1 ) );
    3634    16069052 :         move32();
    3635    16069052 :         D_fx[1] = L_max( 0, L_sub( L_shr( add_fx, add( sub( q_tmp1, q_tmp2 ), 1 ) ), L_shr( pm_fx, 1 ) ) );
    3636    16069052 :         move32();
    3637    16069052 :         *q_D = sub( q_tmp2, 1 );
    3638    16069052 :         move16();
    3639             :     }
    3640             : 
    3641             :     /* Numeric case, when input is practically zeros */
    3642             :     // IF( D_fx[0] < EPSILON_FX )
    3643             : 
    3644    42829130 :     IF( LT_32( L_shl_sat( D_fx[0], sub( sub( 31, *q_D ), EPSILON_EXP ) ), EPSILON_MANT ) )
    3645             :     {
    3646      216883 :         Ure_fx[0][0] = ONE_IN_Q31;
    3647      216883 :         move32();
    3648      216883 :         Ure_fx[1][1] = ONE_IN_Q31;
    3649      216883 :         move32();
    3650      216883 :         *q_U = Q31;
    3651      216883 :         move16();
    3652             : 
    3653      216883 :         return;
    3654             :     }
    3655             : 
    3656             :     /* Numeric case, when input is near an identity matrix with a gain */
    3657    42612247 :     tmp1 = Mpy_32_32( 2147484, add_fx ); // 2147484 = 1e-3f in Q31
    3658             : 
    3659    42612247 :     IF( LT_16( q_tmp1, q_tmp2 ) )
    3660             :     {
    3661    26682718 :         IF( LT_32( L_shr( pm_fx, sub( q_tmp2, q_tmp1 ) ), tmp1 ) )
    3662             :         {
    3663           0 :             Ure_fx[0][0] = ONE_IN_Q30;
    3664           0 :             move32();
    3665           0 :             Ure_fx[1][1] = ONE_IN_Q30;
    3666           0 :             move32();
    3667           0 :             *q_U = Q30;
    3668           0 :             move16();
    3669             : 
    3670           0 :             return;
    3671             :         }
    3672             :     }
    3673             :     ELSE
    3674             :     {
    3675    15929529 :         IF( LT_32( pm_fx, L_shr( tmp1, sub( q_tmp1, q_tmp2 ) ) ) )
    3676             :         {
    3677     4060974 :             Ure_fx[0][0] = ONE_IN_Q30;
    3678     4060974 :             move32();
    3679     4060974 :             Ure_fx[1][1] = ONE_IN_Q30;
    3680     4060974 :             move32();
    3681     4060974 :             *q_U = Q30;
    3682     4060974 :             move16();
    3683             : 
    3684     4060974 :             return;
    3685             :         }
    3686             :     }
    3687             : 
    3688    38551273 :     q_U_1 = 0;
    3689    38551273 :     q_U_2 = 0;
    3690    38551273 :     move16();
    3691    38551273 :     move16();
    3692             : 
    3693             :     /* Eigenvectors */
    3694   115653819 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3695             :     {
    3696    77102546 :         Word16 q_diff = sub( q_e, *q_D );
    3697    77102546 :         IF( q_diff > 0 )
    3698             :         {
    3699    77102546 :             tmp1 = L_sub( D_fx[ch], L_shr( e1, q_diff ) );
    3700    77102546 :             tmp2 = L_sub( D_fx[ch], L_shr( e2, q_diff ) );
    3701    77102546 :             q_tmp1 = *q_D;
    3702    77102546 :             move16();
    3703             :         }
    3704             :         ELSE
    3705             :         {
    3706           0 :             tmp1 = L_sub( L_shl( D_fx[ch], q_diff ), e1 );
    3707           0 :             tmp2 = L_sub( L_shl( D_fx[ch], q_diff ), e2 );
    3708           0 :             q_tmp1 = q_e;
    3709           0 :             move16();
    3710             :         }
    3711             : 
    3712    77102546 :         IF( GT_32( L_abs( tmp2 ), L_abs( tmp1 ) ) )
    3713             :         {
    3714    34335740 :             s_fx = tmp2;
    3715    34335740 :             move32();
    3716    34335740 :             exp = sub( norm_l( s_fx ), 1 );
    3717    34335740 :             tmp2 = Mpy_32_32( s_fx, s_fx );
    3718    34335740 :             q_tmp2 = sub( add( q_tmp1, q_tmp1 ), 31 );
    3719             : 
    3720    34335740 :             tmp2 = BASOP_Util_Add_Mant32Exp( crossSquare_fx, sub( 31, q_crossSquare ), tmp2, sub( 31, q_tmp2 ), &q_tmp2 );
    3721    34335740 :             q_tmp2 = sub( 31, q_tmp2 );
    3722             : 
    3723    34335740 :             tmp3 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), epsilon_mant, epsilon_exp, &exp_tmp3 );
    3724             : 
    3725    34335740 :             tmp2 = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, tmp3, &exp );
    3726    34335740 :             exp = sub( exp, sub( Q30, sub( 31, exp_tmp3 ) ) );
    3727    34335740 :             normVal_fx = Sqrt32( tmp2, &exp ); // q_tmp2
    3728    34335740 :             q_tmp2 = sub( 31, exp );
    3729             : 
    3730    34335740 :             q_diff = sub( q_c, q_tmp1 );
    3731    34335740 :             IF( q_diff > 0 )
    3732             :             {
    3733    16128007 :                 c_re = L_shr( c_re, q_diff );
    3734    16128007 :                 c_im = L_shr( c_im, q_diff );
    3735    16128007 :                 q_c = q_tmp1;
    3736    16128007 :                 move16();
    3737             :             }
    3738             :             ELSE
    3739             :             {
    3740    18207733 :                 s_fx = L_shl( s_fx, q_diff );
    3741    18207733 :                 q_tmp1 = q_c;
    3742    18207733 :                 move16();
    3743             :             }
    3744             : 
    3745    34335740 :             Ure_fx[0][ch] = Mpy_32_32( s_fx, normVal_fx );
    3746    34335740 :             move32();
    3747    34335740 :             Ure_fx[1][ch] = Mpy_32_32( c_re, normVal_fx );
    3748    34335740 :             move32();
    3749    34335740 :             Uim_fx[1][ch] = Mpy_32_32( c_im, normVal_fx );
    3750    34335740 :             move32();
    3751    34335740 :             q_U_1 = sub( add( q_tmp1, q_tmp2 ), 31 );
    3752             : 
    3753    34335740 :             IF( q_U_2 != 0 )
    3754             :             {
    3755    14001817 :                 q_diff = sub( q_U_2, q_U_1 );
    3756    14001817 :                 IF( q_diff > 0 )
    3757             :                 {
    3758           1 :                     Ure_fx[1][ch - 1] = L_shr( Ure_fx[1][ch - 1], q_diff );
    3759           1 :                     Ure_fx[0][ch - 1] = L_shr( Ure_fx[0][ch - 1], q_diff );
    3760           1 :                     Uim_fx[0][ch - 1] = L_shr( Uim_fx[0][ch - 1], q_diff );
    3761           1 :                     q_U_2 = q_U_1;
    3762           1 :                     move32();
    3763           1 :                     move32();
    3764           1 :                     move32();
    3765           1 :                     move16();
    3766             :                 }
    3767    14001816 :                 ELSE IF( GT_16( q_U_1, q_U_2 ) )
    3768             :                 {
    3769           0 :                     Ure_fx[1][ch] = L_shl( Ure_fx[1][ch], q_diff );
    3770           0 :                     Ure_fx[0][ch] = L_shl( Ure_fx[0][ch], q_diff );
    3771           0 :                     Uim_fx[1][ch] = L_shl( Uim_fx[1][ch], q_diff );
    3772           0 :                     q_U_1 = q_U_2;
    3773           0 :                     move32();
    3774           0 :                     move32();
    3775           0 :                     move32();
    3776           0 :                     move16();
    3777             :                 }
    3778             :             }
    3779    34335740 :             q_U_2 = q_U_1;
    3780    34335740 :             move16();
    3781             :         }
    3782             :         ELSE
    3783             :         {
    3784    42766806 :             s_fx = tmp1;
    3785    42766806 :             move32();
    3786             : 
    3787    42766806 :             exp = sub( norm_l( s_fx ), 1 );
    3788    42766806 :             tmp2 = Mpy_32_32( s_fx, s_fx );
    3789    42766806 :             q_tmp2 = sub( add( q_tmp1, q_tmp1 ), 31 );
    3790             : 
    3791    42766806 :             tmp2 = BASOP_Util_Add_Mant32Exp( crossSquare_fx, sub( 31, q_crossSquare ), tmp2, sub( 31, q_tmp2 ), &q_tmp2 );
    3792    42766806 :             q_tmp2 = sub( 31, q_tmp2 );
    3793             : 
    3794    42766806 :             tmp3 = BASOP_Util_Add_Mant32Exp( tmp2, sub( 31, q_tmp2 ), epsilon_mant, epsilon_exp, &exp_tmp3 );
    3795             : 
    3796    42766806 :             tmp2 = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, tmp3, &exp );
    3797    42766806 :             exp = sub( exp, sub( Q30, sub( 31, exp_tmp3 ) ) );
    3798    42766806 :             normVal_fx = Sqrt32( tmp2, &exp ); // q_tmp2
    3799    42766806 :             q_tmp2 = sub( 31, exp );
    3800             : 
    3801    42766806 :             q_diff = sub( q_c, q_tmp1 );
    3802    42766806 :             IF( q_diff > 0 )
    3803             :             {
    3804    18213306 :                 c_re = L_shr( c_re, q_diff );
    3805    18213306 :                 c_im = L_shr( c_im, q_diff );
    3806    18213306 :                 q_c = q_tmp1;
    3807    18213306 :                 move16();
    3808             :             }
    3809             :             ELSE
    3810             :             {
    3811    24553500 :                 s_fx = L_shl( s_fx, q_diff );
    3812    24553500 :                 q_tmp1 = q_c;
    3813    24553500 :                 move16();
    3814             :             }
    3815             : 
    3816    42766806 :             Ure_fx[1][ch] = Mpy_32_32( s_fx, normVal_fx );
    3817    42766806 :             move32();
    3818    42766806 :             Ure_fx[0][ch] = Mpy_32_32( c_re, normVal_fx );
    3819    42766806 :             move32();
    3820    42766806 :             Uim_fx[0][ch] = Mpy_32_32( L_negate( c_im ), normVal_fx );
    3821    42766806 :             move32();
    3822    42766806 :             q_U_2 = sub( add( q_tmp1, q_tmp2 ), 31 );
    3823             : 
    3824    42766806 :             IF( q_U_1 != 0 )
    3825             :             {
    3826    24549456 :                 q_diff = sub( q_U_2, q_U_1 );
    3827    24549456 :                 IF( q_diff > 0 )
    3828             :                 {
    3829           0 :                     Ure_fx[1][ch] = L_shr( Ure_fx[1][ch], q_diff );
    3830           0 :                     Ure_fx[0][ch] = L_shr( Ure_fx[0][ch], q_diff );
    3831           0 :                     Uim_fx[0][ch] = L_shr( Uim_fx[0][ch], q_diff );
    3832           0 :                     q_U_2 = q_U_1;
    3833           0 :                     move32();
    3834           0 :                     move32();
    3835           0 :                     move32();
    3836           0 :                     move16();
    3837             :                 }
    3838    24549456 :                 ELSE IF( GT_16( q_U_1, q_U_2 ) )
    3839             :                 {
    3840           2 :                     Ure_fx[1][ch - 1] = L_shl( Ure_fx[1][ch - 1], q_diff );
    3841           2 :                     Ure_fx[0][ch - 1] = L_shl( Ure_fx[0][ch - 1], q_diff );
    3842           2 :                     Uim_fx[1][ch - 1] = L_shl( Uim_fx[1][ch - 1], q_diff );
    3843           2 :                     q_U_1 = q_U_2;
    3844           2 :                     move32();
    3845           2 :                     move32();
    3846           2 :                     move32();
    3847           2 :                     move16();
    3848             :                 }
    3849             :             }
    3850    42766806 :             q_U_1 = q_U_2;
    3851    42766806 :             move16();
    3852             :         }
    3853             :     }
    3854             : 
    3855    38551273 :     if ( q_U_1 != 0 )
    3856             :     {
    3857    38551273 :         *q_U = q_U_1;
    3858    38551273 :         move16();
    3859             :     }
    3860             : 
    3861    38551273 :     if ( q_U_1 == 0 )
    3862             :     {
    3863           0 :         *q_U = q_U_2;
    3864           0 :         move16();
    3865             :     }
    3866             : 
    3867    38551273 :     return;
    3868             : }
    3869             : 
    3870    21414565 : static void matrixDiagMul_fx(
    3871             :     Word32 reIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_In*/
    3872             :     Word32 imIn_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_In*/
    3873             :     Word16 q_In,
    3874             :     const Word32 D_fx[BINAURAL_CHANNELS], /*q_D*/
    3875             :     Word16 q_D,
    3876             :     Word32 reOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_Out*/
    3877             :     Word32 imOut_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_Out*/
    3878             :     Word16 *q_Out )
    3879             : {
    3880             :     Word16 chA, chB;
    3881    21414565 :     Word16 size = i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS );
    3882             : 
    3883    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    3884             :     {
    3885   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    3886             :         {
    3887    85658260 :             reOut_fx[chA][chB] = Mpy_32_32( reIn_fx[chA][chB], D_fx[chB] );
    3888    85658260 :             imOut_fx[chA][chB] = Mpy_32_32( imIn_fx[chA][chB], D_fx[chB] );
    3889    85658260 :             move32();
    3890    85658260 :             move32();
    3891             :         }
    3892             :     }
    3893             : 
    3894    21414565 :     *q_Out = sub( add( q_In, q_D ), 31 );
    3895    21414565 :     move16();
    3896             : 
    3897    21414565 :     if ( L_and( is_zero_arr( reOut_fx[0], size ), is_zero_arr( imOut_fx[0], size ) ) )
    3898             :     {
    3899       48892 :         *q_Out = Q31;
    3900       48892 :         move16();
    3901             :     }
    3902             : 
    3903    21414565 :     return;
    3904             : }
    3905             : 
    3906    78162115 : static void matrixMul_fx(
    3907             :     Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
    3908             :     Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
    3909             :     Word16 *q_A,
    3910             :     Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
    3911             :     Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
    3912             :     Word16 *q_B,
    3913             :     Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    3914             :     Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    3915             :     Word16 *q_out )
    3916             : {
    3917             :     Word16 chA, chB;
    3918             :     Word16 min_q_shift1, min_q_shift2;
    3919    78162115 :     Word16 size = i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS );
    3920             : 
    3921    78162115 :     min_q_shift1 = sub( s_min( L_norm_arr( Are_fx[0], size ), L_norm_arr( Aim_fx[0], size ) ), 1 );
    3922    78162115 :     min_q_shift2 = sub( s_min( L_norm_arr( Bre_fx[0], size ), L_norm_arr( Bim_fx[0], size ) ), 1 );
    3923             : 
    3924    78162115 :     scale_sig32( Are_fx[0], size, min_q_shift1 );
    3925    78162115 :     scale_sig32( Aim_fx[0], size, min_q_shift1 );
    3926    78162115 :     scale_sig32( Bre_fx[0], size, min_q_shift2 );
    3927    78162115 :     scale_sig32( Bim_fx[0], size, min_q_shift2 );
    3928             : 
    3929    78162115 :     *q_A = add( *q_A, min_q_shift1 );
    3930    78162115 :     *q_B = add( *q_B, min_q_shift2 );
    3931    78162115 :     move16();
    3932    78162115 :     move16();
    3933             : 
    3934   234486345 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    3935             :     {
    3936   468972690 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    3937             :         {
    3938             : #ifdef IVAS_ENH64_CADENCE_CHANGES
    3939             :             outRe_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], Bre_fx[0][chB] ), Are_fx[chA][1], Bre_fx[1][chB] ) );
    3940             :             move32();
    3941             :             outRe_fx[chA][chB] = L_sub( outRe_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], Bim_fx[0][chB] ), Aim_fx[chA][1], Bim_fx[1][chB] ) ) );
    3942             :             move32();
    3943             :             outIm_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], Bre_fx[0][chB] ), Aim_fx[chA][1], Bre_fx[1][chB] ) );
    3944             :             move32();
    3945             :             outIm_fx[chA][chB] = L_add( outIm_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], Bim_fx[0][chB] ), Are_fx[chA][1], Bim_fx[1][chB] ) ) );
    3946             :             move32();
    3947             : #else
    3948   312648460 :             outRe_fx[chA][chB] = Msub_32_32( Msub_32_32( Madd_32_32( Mpy_32_32( Are_fx[chA][0], Bre_fx[0][chB] ),
    3949   312648460 :                                                                      Are_fx[chA][1], Bre_fx[1][chB] ),
    3950   312648460 :                                                          Aim_fx[chA][0], Bim_fx[0][chB] ),
    3951   312648460 :                                              Aim_fx[chA][1], Bim_fx[1][chB] );
    3952   312648460 :             move32();
    3953   312648460 :             outIm_fx[chA][chB] = Madd_32_32( Madd_32_32( Madd_32_32( Mpy_32_32( Aim_fx[chA][0], Bre_fx[0][chB] ),
    3954   312648460 :                                                                      Aim_fx[chA][1], Bre_fx[1][chB] ),
    3955   312648460 :                                                          Are_fx[chA][0], Bim_fx[0][chB] ),
    3956   312648460 :                                              Are_fx[chA][1], Bim_fx[1][chB] );
    3957   312648460 :             move32();
    3958             : #endif /* #ifdef IVAS_ENH64_CADENCE_CHANGES */
    3959             :         }
    3960             :     }
    3961    78162115 :     *q_out = sub( add( *q_A, *q_B ), 31 );
    3962             : 
    3963    78162115 :     move16();
    3964    78162115 :     if ( L_and( is_zero_arr( outRe_fx[0], size ), is_zero_arr( outIm_fx[0], size ) ) )
    3965             :     {
    3966      287100 :         *q_out = Q31;
    3967      287100 :         move16();
    3968             :     }
    3969             : 
    3970    78162115 :     return;
    3971             : }
    3972             : 
    3973    21414565 : static void matrixTransp1Mul_fx(
    3974             :     Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
    3975             :     Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
    3976             :     Word16 q_A,
    3977             :     Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
    3978             :     Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
    3979             :     Word16 q_B,
    3980             :     Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    3981             :     Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    3982             :     Word16 *q_out )
    3983             : {
    3984             :     Word16 chA, chB;
    3985    21414565 :     Word16 size = i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS );
    3986             : 
    3987             :     Word64 tmp_outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    3988             :     Word64 tmp_outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    3989             :     Word16 q_tmp_outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    3990             :     Word16 q_tmp_outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    3991             :     Word64 tmp64_1, tmp64_2;
    3992    21414565 :     Word16 tmp16, q_common = 63;
    3993    21414565 :     move16();
    3994             : 
    3995    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    3996             :     {
    3997   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    3998             :         {
    3999    85658260 :             tmp64_1 = W_mac_32_32( W_mult_32_32( Are_fx[0][chA], Bre_fx[0][chB] ), Are_fx[1][chA], Bre_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
    4000    85658260 :             tmp64_2 = W_mac_32_32( W_mult_32_32( Aim_fx[0][chA], Bim_fx[0][chB] ), Aim_fx[1][chA], Bim_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
    4001    85658260 :             tmp_outRe_fx[chA][chB] = W_add( tmp64_1, tmp64_2 );                                                      // Q: add( add( q_A, q_B ), 1 )
    4002    85658260 :             move64();
    4003    85658260 :             tmp16 = W_norm( tmp_outRe_fx[chA][chB] );
    4004    85658260 :             tmp_outRe_fx[chA][chB] = W_shl( tmp_outRe_fx[chA][chB], tmp16 ); // Q:add( tmp16, add( add( q_A, q_B ), 1 ) )
    4005    85658260 :             move64();
    4006    85658260 :             q_tmp_outRe_fx[chA][chB] = add( tmp16, add( add( q_A, q_B ), 1 ) );
    4007    85658260 :             move16();
    4008    85658260 :             q_common = s_min( q_tmp_outRe_fx[chA][chB], q_common );
    4009             : 
    4010             : 
    4011    85658260 :             tmp64_1 = W_mac_32_32( W_mult_32_32( Are_fx[0][chA], Bim_fx[0][chB] ), Are_fx[1][chA], Bim_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
    4012    85658260 :             tmp64_2 = W_mac_32_32( W_mult_32_32( Aim_fx[0][chA], Bre_fx[0][chB] ), Aim_fx[1][chA], Bre_fx[1][chB] ); // Q: add( add( q_A, q_B ), 1 )
    4013    85658260 :             tmp_outIm_fx[chA][chB] = W_sub( tmp64_1, tmp64_2 );                                                      // Q: add( add( q_A, q_B ), 1 )
    4014    85658260 :             move64();
    4015    85658260 :             tmp16 = W_norm( tmp_outIm_fx[chA][chB] );
    4016    85658260 :             tmp_outIm_fx[chA][chB] = W_shl( tmp_outIm_fx[chA][chB], tmp16 ); // Q:add( tmp16, add( add( q_A, q_B ), 1 ) )
    4017    85658260 :             move64();
    4018    85658260 :             q_tmp_outIm_fx[chA][chB] = add( tmp16, add( add( q_A, q_B ), 1 ) );
    4019    85658260 :             move16();
    4020    85658260 :             q_common = s_min( q_tmp_outIm_fx[chA][chB], q_common );
    4021             :         }
    4022             :     }
    4023    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4024             :     {
    4025   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4026             :         {
    4027             : #ifdef FIX_ISSUE_1811_EXCEEDING_W_SHIFTS
    4028    85658260 :             outRe_fx[chA][chB] = W_extract_h( W_shl( tmp_outRe_fx[chA][chB], s_max( -63, sub( q_common, q_tmp_outRe_fx[chA][chB] ) ) ) );
    4029    85658260 :             move32();
    4030    85658260 :             outIm_fx[chA][chB] = W_extract_h( W_shl( tmp_outIm_fx[chA][chB], s_max( -63, sub( q_common, q_tmp_outIm_fx[chA][chB] ) ) ) );
    4031    85658260 :             move32();
    4032             : #else
    4033             :             outRe_fx[chA][chB] = W_extract_h( W_shl( tmp_outRe_fx[chA][chB], sub( q_common, q_tmp_outRe_fx[chA][chB] ) ) );
    4034             :             move32();
    4035             :             outIm_fx[chA][chB] = W_extract_h( W_shl( tmp_outIm_fx[chA][chB], sub( q_common, q_tmp_outIm_fx[chA][chB] ) ) );
    4036             :             move32();
    4037             : #endif
    4038             :         }
    4039             :     }
    4040    21414565 :     *q_out = sub( q_common, 32 );
    4041    21414565 :     move16();
    4042    21414565 :     if ( L_and( is_zero_arr( outRe_fx[0], size ), is_zero_arr( outIm_fx[0], size ) ) )
    4043             :     {
    4044       82811 :         *q_out = Q31;
    4045       82811 :         move16();
    4046             :     }
    4047             : 
    4048    21414565 :     return;
    4049             : }
    4050             : 
    4051    56747550 : static void matrixTransp2Mul_fx(
    4052             :     Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
    4053             :     Word32 Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_A*/
    4054             :     Word16 *q_A,
    4055             :     Word32 Bre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
    4056             :     Word32 Bim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_B*/
    4057             :     Word16 *q_B,
    4058             :     Word32 Ascale,
    4059             :     Word32 Bscale,
    4060             :     Word32 outRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    4061             :     Word32 outIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    4062             :     Word16 *q_out )
    4063             : {
    4064             :     Word16 chA, chB;
    4065             :     Word16 min_q_shift;
    4066    56747550 :     Word16 size = BINAURAL_CHANNELS * BINAURAL_CHANNELS;
    4067             : 
    4068    56747550 :     IF( Ascale == 1 )
    4069             :     {
    4070    35332985 :         min_q_shift = sub( s_min( L_norm_arr( Are_fx[0], size ), L_norm_arr( Aim_fx[0], size ) ), 1 );
    4071    35332985 :         scale_sig32( Are_fx[0], size, min_q_shift );
    4072    35332985 :         scale_sig32( Aim_fx[0], size, min_q_shift );
    4073    35332985 :         *q_A = add( *q_A, min_q_shift );
    4074    35332985 :         move16();
    4075             :     }
    4076             : 
    4077    56747550 :     IF( Bscale == 1 )
    4078             :     {
    4079           0 :         min_q_shift = sub( s_min( L_norm_arr( Bre_fx[0], size ), L_norm_arr( Bim_fx[0], size ) ), 1 );
    4080           0 :         scale_sig32( Bre_fx[0], size, min_q_shift );
    4081           0 :         scale_sig32( Bim_fx[0], size, min_q_shift );
    4082           0 :         *q_B = add( *q_B, min_q_shift );
    4083           0 :         move16();
    4084             :     }
    4085             : 
    4086   170242650 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4087             :     {
    4088   340485300 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4089             :         {
    4090             : #ifdef IVAS_ENH64_CADENCE_CHANGES
    4091             :             outRe_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], Bre_fx[chB][0] ), Are_fx[chA][1], Bre_fx[chB][1] ) );
    4092             :             move32();
    4093             :             outRe_fx[chA][chB] = L_sub( outRe_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], L_negate( Bim_fx[chB][0] ) ), Aim_fx[chA][1], L_negate( Bim_fx[chB][1] ) ) ) );
    4094             :             move32();
    4095             :             outIm_fx[chA][chB] = W_extract_h( W_mac_32_32( W_mult_32_32( Aim_fx[chA][0], Bre_fx[chB][0] ), Aim_fx[chA][1], Bre_fx[chB][1] ) );
    4096             :             move32();
    4097             :             outIm_fx[chA][chB] = L_add( outIm_fx[chA][chB], W_extract_h( W_mac_32_32( W_mult_32_32( Are_fx[chA][0], L_negate( Bim_fx[chB][0] ) ), Are_fx[chA][1], L_negate( Bim_fx[chB][1] ) ) ) );
    4098             :             move32();
    4099             : #else
    4100   226990200 :             outRe_fx[chA][chB] = Madd_32_32( Madd_32_32( Madd_32_32( Mpy_32_32( Are_fx[chA][0], Bre_fx[chB][0] ),
    4101   226990200 :                                                                      Are_fx[chA][1], Bre_fx[chB][1] ),
    4102   226990200 :                                                          Aim_fx[chA][0], Bim_fx[chB][0] ),
    4103   226990200 :                                              Aim_fx[chA][1], Bim_fx[chB][1] );
    4104   226990200 :             move32();
    4105   226990200 :             outIm_fx[chA][chB] = Msub_32_32( Msub_32_32( Madd_32_32( Mpy_32_32( Aim_fx[chA][0], Bre_fx[chB][0] ),
    4106   226990200 :                                                                      Aim_fx[chA][1], Bre_fx[chB][1] ),
    4107   226990200 :                                                          Are_fx[chA][0], Bim_fx[chB][0] ),
    4108   226990200 :                                              Are_fx[chA][1], Bim_fx[chB][1] );
    4109   226990200 :             move32();
    4110             : #endif /* #ifdef IVAS_ENH64_CADENCE_CHANGES */
    4111             :         }
    4112             :     }
    4113    56747550 :     *q_out = sub( add( *q_A, *q_B ), 31 );
    4114    56747550 :     move16();
    4115             : 
    4116    56747550 :     if ( L_and( is_zero_arr( outRe_fx[0], size ), is_zero_arr( outIm_fx[0], size ) ) )
    4117             :     {
    4118      207374 :         *q_out = Q31;
    4119      207374 :         move16();
    4120             :     }
    4121    56747550 :     return;
    4122             : }
    4123             : 
    4124             : 
    4125    21414565 : static void chol2x2_fx(
    4126             :     const Word32 E1, /*q_E*/
    4127             :     const Word32 E2, /*q_E*/
    4128             :     Word16 q_E,
    4129             :     const Word32 Cre, /*q_C*/
    4130             :     const Word32 Cim, /*q_C*/
    4131             :     Word16 q_C,
    4132             :     Word32 outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    4133             :     Word32 outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_out*/
    4134             :     Word16 *q_out )
    4135             : {
    4136             :     Word16 chA, chB;
    4137             :     Word32 sqrtVal_fx, temp;
    4138             :     Word16 exp, q_re1, q_re2, q_re3, q_im, q_tmp;
    4139             :     Word32 e1, e2, c_re, c_im;
    4140             :     Word16 q_e, q_c;
    4141             : 
    4142    21414565 :     exp = sub( get_min_scalefactor( E1, E2 ), 1 );
    4143    21414565 :     e1 = L_shl( E1, exp );
    4144    21414565 :     e2 = L_shl( E2, exp );
    4145    21414565 :     q_e = add( q_E, exp );
    4146             : 
    4147    21414565 :     exp = sub( get_min_scalefactor( Cre, Cim ), 1 );
    4148    21414565 :     c_re = L_shl( Cre, exp );
    4149    21414565 :     c_im = L_shl( Cim, exp );
    4150    21414565 :     q_c = add( q_C, exp );
    4151             : 
    4152             : 
    4153    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4154             :     {
    4155   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4156             :         {
    4157    85658260 :             outRe[chA][chB] = 0;
    4158    85658260 :             move32();
    4159    85658260 :             outIm[chA][chB] = 0;
    4160    85658260 :             move32();
    4161             :         }
    4162             :     }
    4163             : 
    4164    21414565 :     IF( GT_32( e1, e2 ) ) /* Perform Cholesky decomposition according to louder channel first */
    4165             :     {
    4166    10763752 :         exp = sub( 31, q_e );
    4167    10763752 :         outRe[0][0] = Sqrt32( e1, &exp );
    4168    10763752 :         move32();
    4169    10763752 :         q_re1 = sub( 31, exp );
    4170             : 
    4171             :         // 4611686 = 1e-12 in Q62
    4172    10763752 :         IF( outRe[0][0] == 0 )
    4173             :         {
    4174           0 :             outRe[1][0] = BASOP_Util_Divide3232_Scale_newton( c_re, 4611686, &exp );
    4175           0 :             move32();
    4176           0 :             q_re2 = add( sub( 31, exp ), sub( q_c, 62 ) );
    4177             : 
    4178           0 :             outIm[1][0] = BASOP_Util_Divide3232_Scale_newton( c_im, 4611686, &exp );
    4179           0 :             move32();
    4180           0 :             q_im = add( sub( 31, exp ), sub( q_c, 62 ) );
    4181             :         }
    4182             :         ELSE
    4183             :         {
    4184             :             Word32 denom;
    4185             :             Word16 den_exp;
    4186             :             Word32 my_outRe, my_outIm;
    4187             : 
    4188             :             /* Compute denom = 1.0 / outRe[0][0] */
    4189    10763752 :             denom = ISqrt32( outRe[0][0], &exp );
    4190    10763752 :             denom = Mpy_32_32( denom, denom );
    4191    10763752 :             den_exp = shl( exp, 1 );
    4192             : 
    4193             :             /* Normalise c_re, c_im */
    4194    10763752 :             exp = norm_l( c_re );
    4195    10763752 :             my_outRe = L_shl( c_re, exp );
    4196    10763752 :             q_re2 = add( q_c, exp );
    4197    10763752 :             exp = norm_l( c_im );
    4198    10763752 :             my_outIm = L_shl( c_im, exp );
    4199    10763752 :             q_im = add( q_c, exp );
    4200             : 
    4201             :             /* Multiply and store c_re*denom and c_im*denom */
    4202    10763752 :             outRe[1][0] = Mpy_32_32( denom, my_outRe );
    4203    10763752 :             move32();
    4204    10763752 :             q_re2 = sub( q_re2, den_exp );
    4205             : 
    4206    10763752 :             outIm[1][0] = Mpy_32_32( denom, my_outIm );
    4207    10763752 :             move32();
    4208    10763752 :             q_im = sub( q_im, den_exp );
    4209             :         }
    4210    10763752 :         if ( outRe[1][0] == 0 )
    4211             :         {
    4212         658 :             q_re2 = Q31;
    4213         658 :             move16();
    4214             :         }
    4215    10763752 :         if ( outIm[1][0] == 0 )
    4216             :         {
    4217     7290235 :             q_im = Q31;
    4218     7290235 :             move16();
    4219             :         }
    4220             : 
    4221    10763752 :         temp = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im );
    4222    10763752 :         q_tmp = sub( add( q_c, q_c ), 31 );
    4223             : 
    4224             :         // 4611686 = Q62
    4225    10763752 :         IF( e1 == 0 )
    4226             :         {
    4227           0 :             Word16 norm = norm_l( temp );
    4228           0 :             temp = L_shl( temp, norm );
    4229           0 :             q_tmp = add( q_tmp, norm );
    4230           0 :             temp = Mpy_32_32( temp, ONE_DIV_EPSILON_MANT );
    4231           0 :             q_tmp = sub( q_tmp, ONE_DIV_EPSILON_EXP );
    4232             :         }
    4233             :         ELSE
    4234             :         {
    4235    10763752 :             temp = BASOP_Util_Divide3232_Scale_newton( temp, e1, &exp );
    4236    10763752 :             q_tmp = add( sub( 31, exp ), sub( q_tmp, q_e ) );
    4237             :         }
    4238    10763752 :         if ( temp == 0 )
    4239             :         {
    4240         633 :             q_tmp = Q31;
    4241         633 :             move16();
    4242             :         }
    4243             : 
    4244    10763752 :         IF( LT_16( q_e, q_tmp ) )
    4245             :         {
    4246     9611120 :             sqrtVal_fx = L_sub( e2, L_shr( temp, sub( q_tmp, q_e ) ) ); ////q_tmp
    4247     9611120 :             q_tmp = q_e;
    4248     9611120 :             move16();
    4249             :         }
    4250             :         ELSE
    4251             :         {
    4252     1152632 :             sqrtVal_fx = L_sub( L_shr( e2, sub( q_e, q_tmp ) ), temp ); // q_tmp
    4253             :         }
    4254             : 
    4255    10763752 :         exp = sub( 31, q_tmp );
    4256    10763752 :         outRe[1][1] = Sqrt32( L_max( 0, sqrtVal_fx ), &exp );
    4257    10763752 :         move32();
    4258    10763752 :         q_re3 = sub( 31, exp );
    4259             : 
    4260    10763752 :         *q_out = s_min( s_min( q_re1, q_re2 ), s_min( q_re3, q_im ) );
    4261    10763752 :         outRe[0][0] = L_shr( outRe[0][0], sub( q_re1, *q_out ) );
    4262    10763752 :         move32();
    4263    10763752 :         outRe[1][0] = L_shr( outRe[1][0], sub( q_re2, *q_out ) );
    4264    10763752 :         move32();
    4265    10763752 :         outIm[1][0] = L_shr( outIm[1][0], sub( q_im, *q_out ) );
    4266    10763752 :         move32();
    4267    10763752 :         outRe[1][1] = L_shr( outRe[1][1], sub( q_re3, *q_out ) );
    4268    10763752 :         move32();
    4269             :     }
    4270             :     ELSE
    4271             :     {
    4272    10650813 :         exp = sub( 31, q_e );
    4273    10650813 :         outRe[1][1] = Sqrt32( e2, &exp );
    4274    10650813 :         move32();
    4275    10650813 :         q_re1 = sub( 31, exp );
    4276             : 
    4277             :         // 4611686 = Q62
    4278    10650813 :         IF( outRe[1][1] == 0 )
    4279             :         {
    4280             :             // outRe[0][1] = BASOP_Util_Divide3232_Scale_newton( c_re, 4611686, &exp );
    4281       79726 :             Word32 tmp1 = 1953125005; /* 1/4611686 Q62 */
    4282       79726 :             exp = 9;
    4283             : 
    4284       79726 :             outRe[0][1] = Mpy_32_32( tmp1, c_re );
    4285       79726 :             move32();
    4286       79726 :             q_re2 = add( sub( 31, exp ), sub( q_c, 62 ) );
    4287             : 
    4288             :             // outIm[0][1] = BASOP_Util_Divide3232_Scale_newton( -c_im, 4611686, &exp );
    4289       79726 :             outIm[0][1] = Mpy_32_32( tmp1, -c_im );
    4290       79726 :             move32();
    4291       79726 :             q_im = add( sub( 31, exp ), sub( q_c, 62 ) );
    4292             :         }
    4293             :         ELSE
    4294             :         {
    4295             :             {
    4296             :                 // outRe[0][1] = BASOP_Util_Divide3232_Scale_newton( c_re, outRe[1][1], &exp );
    4297    10571087 :                 Word32 tmp1 = BASOP_Util_Divide3232_Scale_newton( 0x7FFFFFFF, outRe[1][1], &exp );
    4298    10571087 :                 outRe[0][1] = Mpy_32_32( tmp1, c_re );
    4299    10571087 :                 move32();
    4300    10571087 :                 q_re2 = add( sub( 31, exp ), sub( q_c, q_re1 ) );
    4301             : 
    4302             :                 // outIm[0][1] = BASOP_Util_Divide3232_Scale_newton( -c_im, outRe[1][1], &exp );
    4303    10571087 :                 outIm[0][1] = Mpy_32_32( tmp1, -c_im );
    4304    10571087 :                 move32();
    4305    10571087 :                 q_im = add( sub( 31, exp ), sub( q_c, q_re1 ) );
    4306             :             }
    4307             :         }
    4308    10650813 :         if ( outRe[0][1] == 0 )
    4309             :         {
    4310       87647 :             q_re2 = Q31;
    4311       87647 :             move16();
    4312             :         }
    4313    10650813 :         if ( outIm[0][1] == 0 )
    4314             :         {
    4315     8736027 :             q_im = Q31;
    4316     8736027 :             move16();
    4317             :         }
    4318             : 
    4319    10650813 :         temp = Madd_32_32( Mpy_32_32( c_re, c_re ), c_im, c_im );
    4320    10650813 :         q_tmp = sub( add( q_c, q_c ), 31 );
    4321             : 
    4322             :         // 4611686 = 1e-12 in Q62
    4323    10650813 :         IF( e2 == 0 )
    4324             :         {
    4325       79726 :             temp = BASOP_Util_Divide3232_Scale_newton( temp, 4611686, &exp );
    4326       79726 :             q_tmp = add( sub( 31, exp ), sub( q_tmp, 62 ) );
    4327             :         }
    4328             :         ELSE
    4329             :         {
    4330    10571087 :             temp = BASOP_Util_Divide3232_Scale_newton( temp, e2, &exp );
    4331    10571087 :             q_tmp = add( sub( 31, exp ), sub( q_tmp, q_e ) );
    4332             :         }
    4333    10650813 :         if ( temp == 0 )
    4334             :         {
    4335       87630 :             q_tmp = Q31;
    4336       87630 :             move16();
    4337             :         }
    4338             : 
    4339    10650813 :         IF( LT_16( q_e, q_tmp ) )
    4340             :         {
    4341     9683435 :             sqrtVal_fx = L_sub( e1, L_shr( temp, sub( q_tmp, q_e ) ) ); ////q_tmp
    4342     9683435 :             q_tmp = q_e;
    4343     9683435 :             move16();
    4344             :         }
    4345             :         ELSE
    4346             :         {
    4347      967378 :             sqrtVal_fx = L_sub( L_shr( e1, sub( q_e, q_tmp ) ), temp ); ////q_tmp
    4348             :         }
    4349             : 
    4350    10650813 :         exp = sub( 31, q_tmp );
    4351    10650813 :         outRe[0][0] = Sqrt32( L_max( 0, sqrtVal_fx ), &exp );
    4352    10650813 :         move32();
    4353    10650813 :         q_re3 = sub( 31, exp );
    4354             : 
    4355    10650813 :         *q_out = s_min( s_min( q_re1, q_re2 ), s_min( q_re3, q_im ) );
    4356    10650813 :         move16();
    4357    10650813 :         outRe[1][1] = L_shr( outRe[1][1], sub( q_re1, *q_out ) );
    4358    10650813 :         move32();
    4359    10650813 :         outRe[0][1] = L_shr( outRe[0][1], sub( q_re2, *q_out ) );
    4360    10650813 :         move32();
    4361    10650813 :         outIm[0][1] = L_shr( outIm[0][1], sub( q_im, *q_out ) );
    4362    10650813 :         move32();
    4363    10650813 :         outRe[0][0] = L_shr( outRe[0][0], sub( q_re3, *q_out ) );
    4364    10650813 :         move32();
    4365             :     }
    4366             : 
    4367    21414565 :     return;
    4368             : }
    4369    21414565 : static void formulate2x2MixingMatrix_fx(
    4370             :     Word32 Ein1_fx, /*q_Ein*/
    4371             :     Word32 Ein2_fx, /*q_Ein*/
    4372             :     Word16 q_Ein,
    4373             :     Word32 CinRe_fx, /*q_Cin*/
    4374             :     Word32 CinIm_fx, /*q_Cin*/
    4375             :     Word16 q_Cin,
    4376             :     Word32 Eout1_fx, /*q_Eout*/
    4377             :     Word32 Eout2_fx, /*q_Eout*/
    4378             :     Word16 q_Eout,
    4379             :     Word32 CoutRe_fx, /*q_Cout*/
    4380             :     Word32 CoutIm_fx, /*q_Cout*/
    4381             :     Word16 q_Cout,
    4382             :     Word32 Q_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS],   // Q31
    4383             :     Word32 Mre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_M*/
    4384             :     Word32 Mim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], /*q_M*/
    4385             :     Word16 *q_M,
    4386             :     const Word16 regularizationFactor_fx /*Q14*/ )
    4387             : {
    4388             :     /*
    4389             :      This function implements a 2x2 solution for an optimized spatial audio rendering algorithm
    4390             :      Vilkamo, J., Bäckström, T. and Kuntz, A., 2013.
    4391             :      "Optimized covariance domain framework for time–frequency processing of spatial audio."
    4392             :      Journal of the Audio Engineering Society, 61(6), pp.403-411.
    4393             : 
    4394             :      The result of the formulas below are the same as those in the publication, however, some
    4395             :      derivation details differ for as simple as possible 2x2 formulattion
    4396             :      */
    4397             :     Word16 chA, chB;
    4398             :     Word32 maxEne_fx, tmp, maxEneDiv_fx;
    4399             :     Word16 q_maxEne, q_maxEneDiv, exp, exp1;
    4400             :     Word32 KyRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4401             :     Word32 Uxre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uxim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4402             :     Word32 Sx_fx[BINAURAL_CHANNELS], Kxre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Kxim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4403             :     Word32 tmpRe_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpIm_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4404             :     Word32 Are_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Aim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4405             :     Word32 Ure_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4406             :     Word32 D_fx[BINAURAL_CHANNELS];
    4407             :     Word32 div_fx[BINAURAL_CHANNELS];
    4408             :     Word32 Ghat_fx[BINAURAL_CHANNELS];
    4409             :     Word32 GhatQ_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4410             :     Word32 Pre_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim_fx[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4411             :     Word16 q_ky, q_Sx, q_Ux, q_Kx, q_A, q_U, q_D, q_P;
    4412             :     Word32 E_in1, E_in2, E_out1, E_out2, Cout_re, Cout_im, Cin_re, Cin_im;
    4413             :     Word16 q_ein, q_eout, q_cin, q_cout, q_Ghat, q_GhatQ, q_temp, q_div, exp_temp;
    4414             :     Word32 temp;
    4415             :     Word16 q_Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], q_Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4416             :     Word16 hdrm_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS], hdrm_im[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    4417    21414565 :     set16_fx( hdrm_re[0], 63, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
    4418    21414565 :     set16_fx( hdrm_im[0], 63, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
    4419    21414565 :     set16_fx( q_Pre[0], Q31, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
    4420    21414565 :     set16_fx( q_Pim[0], Q31, i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) );
    4421             : 
    4422    21414565 :     q_ky = 0;
    4423    21414565 :     move16();
    4424    21414565 :     q_Sx = 0;
    4425    21414565 :     move16();
    4426    21414565 :     q_Ux = 0;
    4427    21414565 :     move16();
    4428    21414565 :     q_Kx = 0;
    4429    21414565 :     move16();
    4430             : 
    4431    21414565 :     exp = sub( get_min_scalefactor( Ein1_fx, Ein2_fx ), 1 );
    4432    21414565 :     E_in1 = L_shl( Ein1_fx, exp );
    4433    21414565 :     E_in2 = L_shl( Ein2_fx, exp );
    4434    21414565 :     q_ein = add( q_Ein, exp );
    4435             : 
    4436    21414565 :     exp = sub( get_min_scalefactor( Eout1_fx, Eout2_fx ), 1 );
    4437    21414565 :     E_out1 = L_shl( Eout1_fx, exp );
    4438    21414565 :     E_out2 = L_shl( Eout2_fx, exp );
    4439    21414565 :     q_eout = add( q_Eout, exp );
    4440             : 
    4441    21414565 :     exp = sub( get_min_scalefactor( CinRe_fx, CinIm_fx ), 1 );
    4442    21414565 :     Cin_re = L_shl( CinRe_fx, exp );
    4443    21414565 :     Cin_im = L_shl( CinIm_fx, exp );
    4444    21414565 :     q_cin = add( q_Cin, exp );
    4445             : 
    4446    21414565 :     exp = sub( get_min_scalefactor( CoutRe_fx, CoutIm_fx ), 1 );
    4447    21414565 :     Cout_re = L_shl( CoutRe_fx, exp );
    4448    21414565 :     Cout_im = L_shl( CoutIm_fx, exp );
    4449    21414565 :     q_cout = add( q_Cout, exp );
    4450             : 
    4451             :     /* Normalize energy values */
    4452    21414565 :     maxEne_fx = L_max( E_in1, E_in2 );
    4453    21414565 :     q_maxEne = q_ein;
    4454    21414565 :     move16();
    4455             : 
    4456    21414565 :     tmp = L_max( E_out1, E_out2 );
    4457    21414565 :     IF( LT_16( q_maxEne, q_eout ) )
    4458             :     {
    4459    11290014 :         maxEne_fx = L_max( maxEne_fx, L_shr( tmp, sub( q_eout, q_maxEne ) ) ); // q_maxEne
    4460             :     }
    4461             :     ELSE
    4462             :     {
    4463    10124551 :         maxEne_fx = L_max( L_shr( maxEne_fx, sub( q_maxEne, q_eout ) ), tmp ); // q_maxEne
    4464    10124551 :         q_maxEne = q_eout;
    4465    10124551 :         move16();
    4466             :     }
    4467             : 
    4468             :     // 4611686 = Q62
    4469    21414565 :     IF( maxEne_fx == 0 )
    4470             :     {
    4471       48892 :         maxEneDiv_fx = ONE_DIV_EPSILON_MANT;
    4472       48892 :         move32();
    4473       48892 :         q_maxEneDiv = 31 - ONE_DIV_EPSILON_EXP;
    4474       48892 :         move16();
    4475             :     }
    4476             :     ELSE
    4477             :     {
    4478    21365673 :         maxEneDiv_fx = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, maxEne_fx, &exp );
    4479    21365673 :         q_maxEneDiv = add( sub( 31, exp ), sub( Q30, q_maxEne ) );
    4480             :     }
    4481    21414565 :     exp = norm_l( maxEneDiv_fx );
    4482    21414565 :     maxEneDiv_fx = L_shl( maxEneDiv_fx, exp );
    4483    21414565 :     q_maxEneDiv = add( q_maxEneDiv, exp );
    4484             : 
    4485    21414565 :     E_in1 = Mpy_32_32( E_in1, maxEneDiv_fx );
    4486    21414565 :     E_in2 = Mpy_32_32( E_in2, maxEneDiv_fx );
    4487    21414565 :     q_ein = sub( add( q_ein, q_maxEneDiv ), 31 );
    4488             : 
    4489    21414565 :     Cin_re = Mpy_32_32( Cin_re, maxEneDiv_fx );
    4490    21414565 :     Cin_im = Mpy_32_32( Cin_im, maxEneDiv_fx );
    4491    21414565 :     q_cin = sub( add( q_cin, q_maxEneDiv ), 31 );
    4492             : 
    4493    21414565 :     E_out1 = Mpy_32_32( E_out1, maxEneDiv_fx );
    4494    21414565 :     E_out2 = Mpy_32_32( E_out2, maxEneDiv_fx );
    4495    21414565 :     q_eout = sub( add( q_eout, q_maxEneDiv ), 31 );
    4496             : 
    4497    21414565 :     Cout_re = Mpy_32_32( Cout_re, maxEneDiv_fx );
    4498    21414565 :     Cout_im = Mpy_32_32( Cout_im, maxEneDiv_fx );
    4499    21414565 :     q_cout = sub( add( q_cout, q_maxEneDiv ), 31 );
    4500             : 
    4501             :     /* Cholesky decomposition of target / output covariance matrix */
    4502    21414565 :     chol2x2_fx( E_out1, E_out2, q_eout, Cout_re, Cout_im, q_cout, KyRe_fx, KyIm_fx, &q_ky );
    4503             : 
    4504             :     /* Eigendecomposition of input covariance matrix */
    4505    21414565 :     eig2x2_fx( E_in1, E_in2, q_ein, Cin_re, Cin_im, q_cin, Uxre_fx, Uxim_fx, &q_Ux, Sx_fx, &q_Sx );
    4506             : 
    4507             :     /* Eigendecomposition to Kx -- Ux Sx Ux' -> Kx Kx'*/
    4508    21414565 :     exp = sub( 31, q_Sx );
    4509    21414565 :     exp1 = sub( 31, q_Sx );
    4510    21414565 :     Sx_fx[0] = Sqrt32( Sx_fx[0], &exp );
    4511    21414565 :     move32();
    4512    21414565 :     Sx_fx[1] = Sqrt32( Sx_fx[1], &exp1 );
    4513    21414565 :     move32();
    4514    21414565 :     q_Sx = sub( 31, s_max( exp, exp1 ) );
    4515    21414565 :     Word16 q_diff = sub( 31, q_Sx );
    4516    21414565 :     Sx_fx[0] = L_shr( Sx_fx[0], sub( q_diff, exp ) ); // q_Sx
    4517    21414565 :     move32();
    4518    21414565 :     Sx_fx[1] = L_shr( Sx_fx[1], sub( q_diff, exp1 ) ); // q_Sx
    4519    21414565 :     move32();
    4520             : 
    4521    21414565 :     matrixDiagMul_fx( Uxre_fx, Uxim_fx, q_Ux, Sx_fx, q_Sx, Kxre_fx, Kxim_fx, &q_Kx );
    4522             : 
    4523             :     /* Regularize the diagonal Sx for matrix inversion */
    4524    21414565 :     Sx_fx[0] = L_max( L_shr( Sx_fx[0], 1 ), Mpy_32_16_1( Sx_fx[1], regularizationFactor_fx ) );
    4525    21414565 :     Sx_fx[1] = L_max( L_shr( Sx_fx[1], 1 ), L_shl( Mpy_32_16_1( Sx_fx[0], regularizationFactor_fx ), 1 ) );
    4526    21414565 :     move32();
    4527    21414565 :     move32();
    4528    21414565 :     q_Sx = sub( add( q_Sx, Q14 ), 15 );
    4529             : 
    4530    21414565 :     temp = Mpy_32_32( E_in2, 2147484 ); // 2147484 = 0.001f in Q31
    4531    21414565 :     temp = L_max( temp, E_in1 );
    4532             : 
    4533    21414565 :     IF( temp == 0 )
    4534             :     {
    4535       48892 :         IF( E_out1 == 0 )
    4536             :         {
    4537       48892 :             Ghat_fx[0] = 0;
    4538       48892 :             exp = -19;
    4539       48892 :             move32();
    4540       48892 :             move16();
    4541             :         }
    4542             :         ELSE
    4543             :         {
    4544           0 :             temp = BASOP_Util_Divide3232_Scale_newton( E_out1, 4611686, &exp ); // 4611686 = Q62
    4545           0 :             exp = sub( exp, sub( q_eout, 62 ) );
    4546           0 :             Ghat_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp
    4547             :         }
    4548             :     }
    4549             :     ELSE
    4550             :     {
    4551    21365673 :         temp = BASOP_Util_Add_Mant32Exp( temp, sub( 31, q_ein ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
    4552             : 
    4553    21365673 :         temp = BASOP_Util_Divide3232_Scale_newton( E_out1, temp, &exp );
    4554    21365673 :         exp = sub( exp, sub( q_eout, sub( 31, exp_temp ) ) );
    4555    21365673 :         Ghat_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp
    4556             :     }
    4557    21414565 :     move32();
    4558             : 
    4559    21414565 :     temp = Mpy_32_32( E_in1, 2147484 ); // 2147484 = 0.001f in Q31
    4560    21414565 :     temp = L_max( temp, E_in2 );        // q_ein
    4561    21414565 :     IF( temp == 0 )
    4562             :     {
    4563       48892 :         IF( E_out2 == 0 )
    4564             :         { /* We can set hard-coded results */
    4565       48892 :             Ghat_fx[1] = 0;
    4566       48892 :             exp1 = -19;
    4567       48892 :             move16();
    4568             :         }
    4569             :         ELSE
    4570             :         {
    4571           0 :             temp = BASOP_Util_Divide3232_Scale_newton( E_out2, 4611686, &exp1 ); // 4611686 = Q62
    4572           0 :             exp1 = sub( exp1, sub( q_eout, 62 ) );
    4573           0 :             Ghat_fx[1] = Sqrt32( temp, &exp1 ); // Q = 31 - exp1
    4574             :         }
    4575             :     }
    4576             :     ELSE
    4577             :     {
    4578    21365673 :         temp = BASOP_Util_Add_Mant32Exp( temp, sub( 31, q_ein ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
    4579             : 
    4580    21365673 :         temp = BASOP_Util_Divide3232_Scale_newton( E_out2, temp, &exp1 );
    4581    21365673 :         exp1 = sub( exp1, sub( q_eout, sub( 31, exp_temp ) ) );
    4582    21365673 :         Ghat_fx[1] = Sqrt32( temp, &exp1 ); // Q = 31 - exp1
    4583             :     }
    4584    21414565 :     move32();
    4585             : 
    4586    21414565 :     q_Ghat = sub( 31, s_max( exp, exp1 ) );
    4587    21414565 :     q_diff = sub( 31, q_Ghat );
    4588    21414565 :     Ghat_fx[0] = L_shr( Ghat_fx[0], sub( q_diff, exp ) ); // q_Ghat
    4589    21414565 :     move32();
    4590    21414565 :     Ghat_fx[1] = L_shr( Ghat_fx[1], sub( q_diff, exp1 ) ); // q_Ghat
    4591    21414565 :     move32();
    4592             : 
    4593             :     /* Matrix multiplication, tmp = Ky' * G_hat * Q */
    4594    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4595             :     {
    4596    42829130 :         GhatQ_fx[chA][0] = Mpy_32_32( Q_fx[chA][0], Ghat_fx[chA] );
    4597    42829130 :         GhatQ_fx[chA][1] = Mpy_32_32( Q_fx[chA][1], Ghat_fx[chA] );
    4598    42829130 :         move32();
    4599    42829130 :         move32();
    4600             :     }
    4601    21414565 :     q_GhatQ = sub( add( Q31, q_Ghat ), 31 );
    4602             : 
    4603    21414565 :     exp = sub( s_min( L_norm_arr( KyRe_fx[0], i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) ), L_norm_arr( KyIm_fx[0], i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ) ) ), 1 );
    4604    21414565 :     scale_sig32( KyRe_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
    4605    21414565 :     scale_sig32( KyIm_fx[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, exp );
    4606    21414565 :     q_ky = add( q_ky, exp );
    4607             : 
    4608    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4609             :     {
    4610   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4611             :         {
    4612    85658260 :             tmpRe_fx[chA][chB] = Madd_32_32( Mpy_32_32( KyRe_fx[0][chA], GhatQ_fx[0][chB] ), KyRe_fx[1][chA], GhatQ_fx[1][chB] );
    4613    85658260 :             tmpIm_fx[chA][chB] = Msub_32_32( Mpy_32_32( L_negate( KyIm_fx[0][chA] ), GhatQ_fx[0][chB] ), KyIm_fx[1][chA], GhatQ_fx[1][chB] );
    4614    85658260 :             move32();
    4615    85658260 :             move32();
    4616             :         }
    4617             :     }
    4618             : 
    4619    21414565 :     q_temp = sub( add( q_ky, q_GhatQ ), 31 );
    4620             : 
    4621             :     /* A = Ky' * G_hat * Q * Kx (see publication) */
    4622    21414565 :     matrixMul_fx( tmpRe_fx, tmpIm_fx, &q_temp, Kxre_fx, Kxim_fx, &q_Kx, Are_fx, Aim_fx, &q_A );
    4623             : 
    4624             :     /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx
    4625             :        For matrix A that is P = A(A'A)^0.5 */
    4626    21414565 :     matrixTransp1Mul_fx( Are_fx, Aim_fx, q_A, Are_fx, Aim_fx, q_A, tmpRe_fx, tmpIm_fx, &q_temp );
    4627             : 
    4628    21414565 :     eig2x2_fx( tmpRe_fx[0][0], tmpRe_fx[1][1], q_temp, tmpRe_fx[1][0], tmpIm_fx[1][0], q_temp, Ure_fx, Uim_fx, &q_U, D_fx, &q_D );
    4629             : 
    4630    21414565 :     IF( D_fx[0] == 0 )
    4631             :     {
    4632      167991 :         temp = ONE_DIV_EPSILON_MANT; /* Result of 1.0/eps with full precision */
    4633      167991 :         move32();
    4634      167991 :         exp = ONE_DIV_EPSILON_EXP;
    4635      167991 :         move16();
    4636             :     }
    4637             :     ELSE
    4638             :     {
    4639    21246574 :         temp = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, D_fx[0], &exp );
    4640    21246574 :         exp = sub( exp, sub( Q30, q_D ) );
    4641             :     }
    4642    21414565 :     div_fx[0] = Sqrt32( temp, &exp ); // Q = 31 - exp
    4643    21414565 :     move32();
    4644             : 
    4645             :     // Sqrt(1)
    4646    21414565 :     div_fx[1] = L_add( 0, 2047986068 ); // Q = 31 - exp1
    4647    21414565 :     exp1 = add( 0, 20 );
    4648             : 
    4649    21414565 :     IF( D_fx[1] != 0 ) // This is the new code: replace div sqrt by isqrt
    4650             :     {
    4651    16760377 :         exp1 = sub( 31, q_D );
    4652    16760377 :         div_fx[1] = ISqrt32( D_fx[1], &exp1 );
    4653    16760377 :         move32();
    4654             :     }
    4655    21414565 :     q_div = sub( 31, s_max( exp, exp1 ) );
    4656             : 
    4657    21414565 :     div_fx[0] = L_shr( div_fx[0], sub( sub( 31, exp ), q_div ) ); // q_div
    4658    21414565 :     move32();
    4659    21414565 :     div_fx[1] = L_shr( div_fx[1], sub( sub( 31, exp1 ), q_div ) ); // q_div
    4660    21414565 :     move32();
    4661             : 
    4662             :     // 1310720000 = 10,000.0f in Q17
    4663    21414565 :     Word32 thresh = L_shl_sat( 1310720000, sub( q_div, Q17 ) ); // q_div
    4664    21414565 :     div_fx[0] = L_min( div_fx[0], thresh );                     // q_div
    4665    21414565 :     div_fx[1] = L_min( div_fx[1], thresh );                     // q_div
    4666             : 
    4667    21414565 :     matrixMul_fx( Are_fx, Aim_fx, &q_A, Ure_fx, Uim_fx, &q_U, tmpRe_fx, tmpIm_fx, &q_temp );
    4668             : 
    4669    21414565 :     exp = L_norm_arr( div_fx, BINAURAL_CHANNELS );
    4670    21414565 :     scale_sig32( div_fx, BINAURAL_CHANNELS, exp );
    4671    21414565 :     q_div = add( q_div, exp );
    4672             : 
    4673    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4674             :     {
    4675   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4676             :         {
    4677             :             Word64 W_tmp;
    4678             : 
    4679    85658260 :             W_tmp = W_mult0_32_32( tmpRe_fx[chA][chB], div_fx[chB] );
    4680    85658260 :             IF( W_tmp != 0 )
    4681             :             {
    4682    75353238 :                 Word16 hdrm = sub( W_norm( W_tmp ), 32 );
    4683    75353238 :                 tmpRe_fx[chA][chB] = W_shl_sat_l( W_tmp, hdrm );
    4684    75353238 :                 move32();
    4685    75353238 :                 hdrm_re[chA][chB] = add( add( q_temp, q_div ), hdrm );
    4686    75353238 :                 move16();
    4687             :             }
    4688             :             ELSE
    4689             :             {
    4690    10305022 :                 tmpRe_fx[chA][chB] = 0;
    4691    10305022 :                 move32();
    4692             :             }
    4693             : 
    4694    85658260 :             W_tmp = W_mult0_32_32( tmpIm_fx[chA][chB], div_fx[chB] );
    4695    85658260 :             IF( W_tmp != 0 )
    4696             :             {
    4697    53692700 :                 Word16 hdrm = sub( W_norm( W_tmp ), 32 );
    4698    53692700 :                 move16();
    4699    53692700 :                 tmpIm_fx[chA][chB] = W_shl_sat_l( W_tmp, hdrm );
    4700    53692700 :                 move32();
    4701    53692700 :                 hdrm_im[chA][chB] = add( add( q_temp, q_div ), hdrm );
    4702    53692700 :                 move16();
    4703             :             }
    4704             :             ELSE
    4705             :             {
    4706    31965560 :                 tmpIm_fx[chA][chB] = 0;
    4707    31965560 :                 move32();
    4708             :             }
    4709             :         }
    4710             :     }
    4711             : 
    4712    21414565 :     minimum_s( hdrm_re[0], i_mult( BINAURAL_CHANNELS, BINAURAL_CHANNELS ), &exp );
    4713    21414565 :     q_temp = exp;
    4714    21414565 :     move16();
    4715    21414565 :     minimum_s( hdrm_im[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, &exp );
    4716    21414565 :     q_temp = s_min( q_temp, exp );
    4717    21414565 :     q_temp = sub( q_temp, 1 );
    4718             : 
    4719    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4720             :     {
    4721   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4722             :         {
    4723    85658260 :             tmpRe_fx[chA][chB] = L_shr( tmpRe_fx[chA][chB], sub( hdrm_re[chA][chB], q_temp ) );
    4724    85658260 :             tmpIm_fx[chA][chB] = L_shr( tmpIm_fx[chA][chB], sub( hdrm_im[chA][chB], q_temp ) );
    4725    85658260 :             move32();
    4726    85658260 :             move32();
    4727             :         }
    4728             :     }
    4729             : 
    4730    21414565 :     matrixTransp2Mul_fx( tmpRe_fx, tmpIm_fx, &q_temp, Ure_fx, Uim_fx, &q_U,
    4731             :                          0 /*int Ascale*/,
    4732             :                          0 /*int Bscale*/,
    4733             :                          Pre_fx, Pim_fx, &q_P ); /* Nearest orthonormal matrix P to matrix A formulated */
    4734             : 
    4735             :     /* These are the final formulas of the JAES publication M = Ky P Kx^(-1) */
    4736             : #if ( BINAURAL_CHANNELS != 2 )
    4737             :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4738             :     {
    4739             :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4740             :         {
    4741             :             IF( Sx_fx[chB] == 0 )
    4742             :             {
    4743             :                 Pre_fx[chA][chB] = Mpy_32_32( Pre_fx[chA][chB], ONE_DIV_EPSILON_MANT );
    4744             :                 // q_Pre[chA][chB]  = add(sub(31, q_P), 31 - ONE_DIV_EPSILON_EXP);
    4745             :                 q_Pre[chA][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
    4746             : 
    4747             : 
    4748             :                 Pim_fx[chA][chB] = Mpy_32_32( Pim_fx[chA][chB], ONE_DIV_EPSILON_MANT );
    4749             :                 // q_Pim[chA][chB]  = add(sub(31, q_P), 31 - ONE_DIV_EPSILON_EXP);
    4750             :                 q_Pim[chA][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
    4751             :             }
    4752             :             ELSE
    4753             :             {
    4754             :                 Word16 Pre_shift, Pim_shift;
    4755             :                 temp = BASOP_Util_Add_Mant32Exp( Sx_fx[chB], sub( 31, q_Sx ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
    4756             : 
    4757             :                 temp = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, temp, &exp );
    4758             :                 Pre_shift = norm_l( Pre_fx[chA][chB] );
    4759             :                 Pim_shift = norm_l( Pim_fx[chA][chB] );
    4760             :                 Pre_fx[chA][chB] = Mpy_32_32( L_shl( Pre_fx[chA][chB], Pre_shift ), temp );
    4761             :                 Pim_fx[chA][chB] = Mpy_32_32( L_shl( Pim_fx[chA][chB], Pim_shift ), temp );
    4762             :                 q_temp = add( sub( sub( q_P, exp ), sub( 31, Q30 ) ), exp_temp );
    4763             :                 q_Pre[chA][chB] = add( q_temp, Pre_shift );
    4764             :                 q_Pim[chA][chB] = add( q_temp, Pim_shift );
    4765             :             }
    4766             :             if ( Pre_fx[chA][chB] == 0 )
    4767             :             {
    4768             :                 q_Pre[chA][chB] = 31;
    4769             :                 move16();
    4770             :             }
    4771             :             if ( Pim_fx[chA][chB] == 0 )
    4772             :             {
    4773             :                 q_Pim[chA][chB] = 31;
    4774             :                 move16();
    4775             :             }
    4776             :             move32();
    4777             :             move32();
    4778             :             move16();
    4779             :             move16();
    4780             :         }
    4781             :     }
    4782             : #else
    4783             :     /* BINAURAL_CHANNEL == 2 */
    4784    64243695 :     FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4785             :     {
    4786    42829130 :         IF( Sx_fx[chB] == 0 )
    4787             :         {
    4788       97784 :             Pre_fx[0][chB] = Mpy_32_32( Pre_fx[0][chB], ONE_DIV_EPSILON_MANT );
    4789       97784 :             q_Pre[0][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
    4790       97784 :             Pim_fx[0][chB] = Mpy_32_32( Pim_fx[0][chB], ONE_DIV_EPSILON_MANT );
    4791       97784 :             q_Pim[0][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
    4792       97784 :             Pre_fx[1][chB] = Mpy_32_32( Pre_fx[1][chB], ONE_DIV_EPSILON_MANT );
    4793       97784 :             q_Pre[1][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
    4794       97784 :             Pim_fx[1][chB] = Mpy_32_32( Pim_fx[1][chB], ONE_DIV_EPSILON_MANT );
    4795       97784 :             q_Pim[1][chB] = sub( 62 - ONE_DIV_EPSILON_EXP, q_P );
    4796             :         }
    4797             :         ELSE
    4798             :         {
    4799             :             Word16 Pre_shift, Pim_shift;
    4800    42731346 :             temp = BASOP_Util_Add_Mant32Exp( Sx_fx[chB], sub( 31, q_Sx ), EPSILON_MANT, EPSILON_EXP, &exp_temp );
    4801    42731346 :             temp = BASOP_Util_Divide3232_Scale_newton( ONE_IN_Q30, temp, &exp );
    4802    42731346 :             q_temp = add( sub( sub( q_P, exp ), sub( 31, Q30 ) ), exp_temp );
    4803             : 
    4804    42731346 :             Pre_shift = norm_l( Pre_fx[0][chB] );
    4805    42731346 :             Pim_shift = norm_l( Pim_fx[0][chB] );
    4806    42731346 :             Pre_fx[0][chB] = Mpy_32_32( L_shl( Pre_fx[0][chB], Pre_shift ), temp );
    4807    42731346 :             Pim_fx[0][chB] = Mpy_32_32( L_shl( Pim_fx[0][chB], Pim_shift ), temp );
    4808    42731346 :             q_Pre[0][chB] = add( q_temp, Pre_shift );
    4809    42731346 :             q_Pim[0][chB] = add( q_temp, Pim_shift );
    4810             : 
    4811    42731346 :             Pre_shift = norm_l( Pre_fx[1][chB] );
    4812    42731346 :             Pim_shift = norm_l( Pim_fx[1][chB] );
    4813    42731346 :             Pre_fx[1][chB] = Mpy_32_32( L_shl( Pre_fx[1][chB], Pre_shift ), temp );
    4814    42731346 :             Pim_fx[1][chB] = Mpy_32_32( L_shl( Pim_fx[1][chB], Pim_shift ), temp );
    4815    42731346 :             q_Pre[1][chB] = add( q_temp, Pre_shift );
    4816    42731346 :             q_Pim[1][chB] = add( q_temp, Pim_shift );
    4817             :         }
    4818    42829130 :         if ( Pre_fx[0][chB] == 0 )
    4819             :         {
    4820     4721698 :             q_Pre[0][chB] = 31;
    4821     4721698 :             move16();
    4822             :         }
    4823    42829130 :         if ( Pim_fx[0][chB] == 0 )
    4824             :         {
    4825    15586382 :             q_Pim[0][chB] = 31;
    4826    15586382 :             move16();
    4827             :         }
    4828    42829130 :         if ( Pre_fx[1][chB] == 0 )
    4829             :         {
    4830     5575535 :             q_Pre[1][chB] = 31;
    4831     5575535 :             move16();
    4832             :         }
    4833    42829130 :         if ( Pim_fx[1][chB] == 0 )
    4834             :         {
    4835    16288420 :             q_Pim[1][chB] = 31;
    4836    16288420 :             move16();
    4837             :         }
    4838    42829130 :         move32();
    4839    42829130 :         move32();
    4840    42829130 :         move16();
    4841    42829130 :         move16();
    4842    42829130 :         move32();
    4843    42829130 :         move32();
    4844    42829130 :         move16();
    4845    42829130 :         move16();
    4846             :     }
    4847             : #endif
    4848    21414565 :     minimum_s( q_Pre[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, &exp );
    4849    21414565 :     q_P = s_min( q_P, exp );
    4850    21414565 :     minimum_s( q_Pim[0], BINAURAL_CHANNELS * BINAURAL_CHANNELS, &exp );
    4851    21414565 :     q_P = s_min( q_P, exp );
    4852             : 
    4853    64243695 :     FOR( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    4854             :     {
    4855   128487390 :         FOR( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    4856             :         {
    4857    85658260 :             Pre_fx[chA][chB] = L_shr( Pre_fx[chA][chB], sub( q_Pre[chA][chB], q_P ) ); // q_P
    4858    85658260 :             Pim_fx[chA][chB] = L_shr( Pim_fx[chA][chB], sub( q_Pim[chA][chB], q_P ) ); // q_P
    4859    85658260 :             move32();
    4860    85658260 :             move32();
    4861             :         }
    4862             :     }
    4863             : 
    4864    21414565 :     matrixMul_fx( KyRe_fx, KyIm_fx, &q_ky, Pre_fx, Pim_fx, &q_P, tmpRe_fx, tmpIm_fx, &q_temp );
    4865             : 
    4866    21414565 :     matrixTransp2Mul_fx( tmpRe_fx, tmpIm_fx, &q_temp, Uxre_fx, Uxim_fx, &q_Ux,
    4867             :                          1 /*int Ascale*/,
    4868             :                          0 /*int Bscale*/,
    4869             :                          Mre_fx, Mim_fx, q_M );
    4870    21414565 :     return;
    4871             : }
    4872             : 
    4873             : 
    4874    20805489 : static void getDirectPartGains_fx(
    4875             :     const Word16 bin,
    4876             :     Word16 aziDeg,
    4877             :     Word16 eleDeg,
    4878             :     Word32 *lRealp,
    4879             :     Word32 *lImagp,
    4880             :     Word32 *rRealp,
    4881             :     Word32 *rImagp,
    4882             :     const UWord8 renderStereoOutputInsteadOfBinaural,
    4883             :     Word32 Rmat[3][3], /*Q30*/
    4884             :     PARAMBIN_HRTF_GAIN_CACHE *gainCache,
    4885             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    4886             :     const Word16 isHeadtracked,
    4887             :     HRTFS_PARAMBIN_HANDLE hHrtfParambin
    4888             : #else
    4889             :     const Word16 isHeadtracked
    4890             : #endif
    4891             : )
    4892             : {
    4893             :     // float aziRad, eleRad;
    4894             :     Word32 y, mappedX;
    4895             :     Word16 aziRadMapped, A, A2, A3;
    4896    20805489 :     const Word16 LsAngleRad = 17157; // Q15
    4897    20805489 :     move16();
    4898             :     Word32 *ptr_sin, *ptr_cos;
    4899             :     Word32 sin_val, cos_val;
    4900             :     Word16 e_mappedX;
    4901             : 
    4902    20805489 :     ptr_sin = &sine_table_Q31[180]; // sin[x] = sine_table_Q31[180 + x]
    4903    20805489 :     ptr_cos = cosine_table_Q31;
    4904             : 
    4905    20805489 :     IF( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */
    4906             :     {
    4907             :         /* Convert azi and ele to an azi value of the cone of confusion */
    4908             : 
    4909             :         // y = ( sinf( aziRad ) * cosf( eleRad ) );
    4910             : 
    4911     1589746 :         IF( GT_16( abs_s( eleDeg ), 180 ) )
    4912             :         {
    4913             :             // cos(180 + x) = -cos(x)
    4914           0 :             cos_val = -ptr_cos[sub( abs_s( eleDeg ), 180 )]; // Q31
    4915             :         }
    4916             :         ELSE
    4917             :         {
    4918     1589746 :             cos_val = ptr_cos[abs_s( eleDeg )]; // Q31
    4919             :         }
    4920     1589746 :         move32();
    4921             : 
    4922     1589746 :         IF( GT_16( aziDeg, 180 ) )
    4923             :         {
    4924             :             // sin(180 + x) = -sin(x)
    4925           0 :             sin_val = -ptr_sin[sub( aziDeg, 180 )]; // Q31
    4926             :         }
    4927     1589746 :         ELSE IF( LT_16( aziDeg, -180 ) )
    4928             :         {
    4929             :             // sin(-(180 + x)) = sin(180 + x) = sinx
    4930           0 :             sin_val = ptr_sin[sub( abs_s( aziDeg ), 180 )]; // Q31
    4931             :         }
    4932             :         ELSE
    4933             :         {
    4934     1589746 :             sin_val = ptr_sin[aziDeg]; // Q31
    4935             :         }
    4936     1589746 :         move32();
    4937             : 
    4938     1589746 :         y = Mpy_32_32( sin_val, cos_val ); // Q31
    4939     1589746 :         e_mappedX = 0;
    4940     1589746 :         move16();
    4941     1589746 :         mappedX = Sqrt32( L_max( 0, L_sub( ONE_IN_Q31, Mpy_32_32( y, y ) ) ), &e_mappedX );
    4942             : 
    4943     1589746 :         aziRadMapped = BASOP_util_atan2( y, mappedX, negate( e_mappedX ) ); // Q13
    4944             : 
    4945             :         /* Determine the real valued amplitude panning gains */
    4946     1589746 :         *lImagp = 0;
    4947     1589746 :         *rImagp = 0;
    4948     1589746 :         move32();
    4949     1589746 :         move32();
    4950     1589746 :         IF( GE_16( aziRadMapped, shr( LsAngleRad, 2 ) ) )
    4951             :         { /* Left side */
    4952      361666 :             *lRealp = ONE_IN_Q31;
    4953      361666 :             *rRealp = 0;
    4954      361666 :             move32();
    4955      361666 :             move32();
    4956             :         }
    4957     1228080 :         ELSE IF( LE_16( aziRadMapped, negate( shr( LsAngleRad, 2 ) ) ) )
    4958             :         { /* Right side */
    4959      569969 :             *lRealp = 0;
    4960      569969 :             *rRealp = ONE_IN_Q31;
    4961      569969 :             move32();
    4962      569969 :             move32();
    4963             :         }
    4964             :         ELSE /* Tangent panning law */
    4965             :         {
    4966             :             Word16 e_div, div, e_a, e_a3, temp_16_1, temp_16_2, e_num, e_den;
    4967      658111 :             div = BASOP_Util_Divide3232_Scale( y, mappedX, &e_div );
    4968      658111 :             e_div = sub( e_div, e_mappedX );
    4969             : 
    4970      658111 :             A = mult( div, INV_TAN30_FX );
    4971      658111 :             e_a = add( e_div, 1 );
    4972             : 
    4973      658111 :             e_num = BASOP_Util_Add_MantExp( A, e_a, -32767, 0, &temp_16_1 );
    4974      658111 :             e_den = BASOP_Util_Add_MantExp( A, e_a, 32767, 0, &temp_16_2 );
    4975      658111 :             IF( temp_16_2 <= 0 )
    4976             :             {
    4977           0 :                 temp_16_2 = 32;
    4978           0 :                 e_den = 0;
    4979           0 :                 move16();
    4980           0 :                 move16();
    4981             :             }
    4982      658111 :             A2 = BASOP_Util_Divide1616_Scale( temp_16_1, temp_16_2, &e_div );
    4983      658111 :             e_div = add( e_div, sub( e_num, e_den ) );
    4984             : 
    4985      658111 :             e_den = BASOP_Util_Add_MantExp( mult( A2, A2 ), add( e_div, e_div ), 32767, 0, &temp_16_2 );
    4986      658111 :             A3 = BASOP_Util_Divide1616_Scale( 32767, temp_16_2, &e_a3 );
    4987      658111 :             e_a3 = sub( e_a3, e_den );
    4988             :             // A3 = 1.0f / ( A2 * A2 + 1.0f );   // Q15
    4989      658111 :             Word32 temp_32 = L_shr( L_deposit_h( A3 ), sub( 0, e_a3 ) );
    4990      658111 :             Word16 temp_e = 0;
    4991      658111 :             e_a3 = 0;
    4992      658111 :             move16();
    4993      658111 :             move16();
    4994      658111 :             *lRealp = Sqrt32( temp_32, &e_a3 );
    4995      658111 :             *rRealp = Sqrt32( L_sub( ONE_IN_Q31, temp_32 ), &temp_e );
    4996      658111 :             *lRealp = L_shr( *lRealp, sub( 0, e_a3 ) );   // Q31
    4997      658111 :             *rRealp = L_shr( *rRealp, sub( 0, temp_e ) ); // Q31
    4998      658111 :             move32();
    4999      658111 :             move32();
    5000      658111 :             move32();
    5001      658111 :             move32();
    5002             :         }
    5003             : 
    5004             :         /* Scaling to have the same expected gain as for the HRTF rendering */
    5005     1589746 :         *lRealp = Mpy_32_32( *lRealp, SQRT2_FIXED ); // Q30
    5006     1589746 :         *rRealp = Mpy_32_32( *rRealp, SQRT2_FIXED ); // Q30
    5007             : 
    5008     1589746 :         *lRealp = L_shr( *lRealp, 2 ); // Q28
    5009     1589746 :         *rRealp = L_shr( *rRealp, 2 ); // Q28
    5010     1589746 :         move32();
    5011     1589746 :         move32();
    5012     1589746 :         move32();
    5013     1589746 :         move32();
    5014             :     }
    5015             :     ELSE /* In regular binaural rendering mode */
    5016             :     {
    5017    19215743 :         test();
    5018    19215743 :         IF( EQ_16( aziDeg, gainCache->azi ) && EQ_16( eleDeg, gainCache->ele ) )
    5019             :         {
    5020             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    5021    11830041 :             hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE, hHrtfParambin );
    5022             : #else
    5023             :             hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE );
    5024             : #endif
    5025             :         }
    5026             :         ELSE
    5027             :         {
    5028     7385702 :             gainCache->azi = aziDeg;
    5029     7385702 :             gainCache->ele = eleDeg;
    5030     7385702 :             move16();
    5031     7385702 :             move16();
    5032     7385702 :             IF( isHeadtracked )
    5033             :             {
    5034             :                 // Word32 aziDeg_32, eleDeg_32;
    5035     3309804 :                 rotateAziEle_fx( aziDeg, eleDeg, &aziDeg, &eleDeg, Rmat, 0 ); // need to be chnaged
    5036             :                                                                               // eleDeg = L_shr(eleDeg_32, 22);
    5037             :                                                                               // aziDeg = L_shr(aziDeg_32, 22);
    5038             :             }
    5039             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    5040     7385702 :             hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE, hHrtfParambin );
    5041             : #else
    5042             :             hrtfShGetHrtf_fx( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE );
    5043             : #endif
    5044             :         }
    5045             :     }
    5046             : 
    5047    20805489 :     return;
    5048             : }
    5049             : 
    5050    19215743 : static void hrtfShGetHrtf_fx(
    5051             :     const Word16 bin,
    5052             :     const Word16 aziDeg,
    5053             :     const Word16 eleDeg,
    5054             :     Word32 *lRealp,
    5055             :     Word32 *lImagp,
    5056             :     Word32 *rRealp,
    5057             :     Word32 *rImagp,
    5058             :     PARAMBIN_HRTF_GAIN_CACHE *gainCache,
    5059             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    5060             :     const Word16 useCachedValue,
    5061             :     HRTFS_PARAMBIN_HANDLE hHrtfParambin
    5062             : #else
    5063             :     const Word16 useCachedValue
    5064             : #endif
    5065             : )
    5066             : {
    5067             :     Word16 k;
    5068             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    5069             :     Word16( *hrtfShCoeffsReInt_fx )[16][60];
    5070             :     Word16( *hrtfShCoeffsImInt_fx )[16][60];
    5071    19215743 :     hrtfShCoeffsReInt_fx = hHrtfParambin->hrtfShCoeffsRe_fx;
    5072    19215743 :     hrtfShCoeffsImInt_fx = hHrtfParambin->hrtfShCoeffsIm_fx;
    5073             : #endif
    5074             : 
    5075    19215743 :     *lRealp = 0;
    5076    19215743 :     *lImagp = 0;
    5077    19215743 :     *rRealp = 0;
    5078    19215743 :     *rImagp = 0;
    5079    19215743 :     move32();
    5080    19215743 :     move32();
    5081    19215743 :     move32();
    5082    19215743 :     move32();
    5083             : 
    5084    19215743 :     IF( useCachedValue )
    5085             :     {
    5086             :         Word32 *shVec;
    5087    11830041 :         shVec = gainCache->shVec_fx;
    5088             : 
    5089   201110697 :         FOR( k = 0; k < HRTF_SH_CHANNELS; k++ )
    5090             :         {
    5091             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    5092   189280656 :             *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsReInt_fx[0][k][bin] ); // Q28
    5093   189280656 :             *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsImInt_fx[0][k][bin] ); // Q28
    5094   189280656 :             *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsReInt_fx[1][k][bin] ); // Q28
    5095   189280656 :             *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsImInt_fx[1][k][bin] ); // Q28
    5096             : #else
    5097             :             *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsRe_fx[0][k][bin] ); // Q28
    5098             :             *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsIm_fx[0][k][bin] ); // Q28
    5099             :             *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsRe_fx[1][k][bin] ); // Q28
    5100             :             *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsIm_fx[1][k][bin] ); // Q28
    5101             : #endif
    5102   189280656 :             move32();
    5103   189280656 :             move32();
    5104   189280656 :             move32();
    5105   189280656 :             move32();
    5106             :         }
    5107             :     }
    5108             :     ELSE
    5109             :     {
    5110             :         Word32 shVec[HRTF_SH_CHANNELS];
    5111             : 
    5112     7385702 :         ivas_dirac_dec_get_response_fx( aziDeg,
    5113             :                                         eleDeg,
    5114             :                                         shVec,
    5115             :                                         HRTF_SH_ORDER,
    5116             :                                         Q29 );
    5117             : 
    5118   125556934 :         FOR( k = 0; k < HRTF_SH_CHANNELS; k++ )
    5119             :         {
    5120             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    5121   118171232 :             *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsReInt_fx[0][k][bin] ); // Q28
    5122   118171232 :             *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsImInt_fx[0][k][bin] ); // Q28
    5123   118171232 :             *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsReInt_fx[1][k][bin] ); // Q28
    5124   118171232 :             *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsImInt_fx[1][k][bin] ); // Q28
    5125             : #else
    5126             :             *lRealp = Madd_32_16( *lRealp, shVec[k], hrtfShCoeffsRe_fx[0][k][bin] ); // Q28
    5127             :             *lImagp = Madd_32_16( *lImagp, shVec[k], hrtfShCoeffsIm_fx[0][k][bin] ); // Q28
    5128             :             *rRealp = Madd_32_16( *rRealp, shVec[k], hrtfShCoeffsRe_fx[1][k][bin] ); // Q28
    5129             :             *rImagp = Madd_32_16( *rImagp, shVec[k], hrtfShCoeffsIm_fx[1][k][bin] ); // Q28
    5130             : #endif
    5131   118171232 :             gainCache->shVec_fx[k] = shVec[k]; // Q29
    5132   118171232 :             move32();
    5133   118171232 :             move32();
    5134   118171232 :             move32();
    5135   118171232 :             move32();
    5136   118171232 :             move32();
    5137             :         }
    5138             :     }
    5139             : 
    5140    19215743 :     return;
    5141             : }
    5142             : 
    5143             : /*-------------------------------------------------------------------------
    5144             :  * configure_reqularization_factor()
    5145             :  *
    5146             :  * Configure regularization factor for the mixing matrix generation of the
    5147             :  * parametric binauralizer using IVAS codec format and current bitrate.
    5148             :  *------------------------------------------------------------------------*/
    5149             : 
    5150             : /*! r: Configured reqularization factor value */
    5151             : 
    5152        3541 : Word16 configure_reqularization_factor_fx(
    5153             :     const IVAS_FORMAT ivas_format, /* i  : IVAS format          */
    5154             :     const Word32 ivas_total_brate  /* i  : IVAS total bitrate  */
    5155             : )
    5156             : {
    5157             :     Word16 reqularizationFactor;
    5158        3541 :     reqularizationFactor = 16384; /* Default value */ /*Q14*/
    5159        3541 :     move16();
    5160             : 
    5161        3541 :     IF( EQ_32( ivas_format, MASA_FORMAT ) )
    5162             :     {
    5163        1708 :         IF( GE_32( ivas_total_brate, IVAS_160k ) )
    5164             :         {
    5165         144 :             reqularizationFactor = 6553; /*Q14*/
    5166         144 :             move16();
    5167             :         }
    5168        1564 :         ELSE IF( EQ_32( ivas_total_brate, IVAS_128k ) )
    5169             :         {
    5170          88 :             reqularizationFactor = 8192; /*Q14*/
    5171          88 :             move16();
    5172             :         }
    5173        1476 :         ELSE IF( EQ_32( ivas_total_brate, IVAS_96k ) )
    5174             :         {
    5175          96 :             reqularizationFactor = 9830; /*Q14*/
    5176          96 :             move16();
    5177             :         }
    5178        1380 :         ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) )
    5179             :         {
    5180         202 :             reqularizationFactor = 13107; /*Q14*/
    5181         202 :             move16();
    5182             :         }
    5183             :         ELSE
    5184             :         {
    5185        1178 :             reqularizationFactor = 16384; /*Q14*/
    5186        1178 :             move16();
    5187             :         }
    5188             :     }
    5189             : 
    5190        3541 :     IF( EQ_32( ivas_format, MC_FORMAT ) ) /* This is always McMASA for parametric binauralizer. */
    5191             :     {
    5192         268 :         IF( GE_32( ivas_total_brate, IVAS_96k ) )
    5193             :         {
    5194           0 :             reqularizationFactor = 6553; /*Q14*/
    5195           0 :             move16();
    5196             :         }
    5197         268 :         ELSE IF( GE_32( ivas_total_brate, IVAS_80k ) )
    5198             :         {
    5199           2 :             reqularizationFactor = 8192; /*Q14*/
    5200           2 :             move16();
    5201             :         }
    5202         266 :         ELSE IF( GE_32( ivas_total_brate, IVAS_64k ) )
    5203             :         {
    5204           8 :             reqularizationFactor = 11468; /*Q14*/
    5205           8 :             move16();
    5206             :         }
    5207         258 :         ELSE IF( GE_32( ivas_total_brate, IVAS_48k ) )
    5208             :         {
    5209          13 :             reqularizationFactor = 13107; /*Q14*/
    5210          13 :             move16();
    5211             :         }
    5212             :         ELSE
    5213             :         {
    5214         245 :             reqularizationFactor = 16384; /*Q14*/
    5215         245 :             move16();
    5216             :         }
    5217             :     }
    5218             : 
    5219             :     /* For SBA and parametric ISM, currently in default value of 1.0f. */
    5220             : 
    5221        3541 :     return reqularizationFactor;
    5222             : }
    5223             : 
    5224             : /*-------------------------------------------------------------------*
    5225             :  * ivas_omasa_preProcessStereoTransportsForMovedObjects_fx()
    5226             :  *
    5227             :  *
    5228             :  *-------------------------------------------------------------------*/
    5229             : 
    5230        5053 : void ivas_omasa_preProcessStereoTransportsForMovedObjects_fx(
    5231             :     Decoder_Struct *st_ivas,
    5232             :     Word32 inRe_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/
    5233             :     Word32 inIm_fx[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /*cldfb_buf_q*/
    5234             :     Word16 *cldfb_buf_q,
    5235             :     const Word16 nBins,
    5236             :     const Word16 subframe )
    5237             : {
    5238             :     Word16 bin, ch, inCh, outCh, ismDirIndex, slot;
    5239             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    5240             :     MASA_ISM_DATA_HANDLE hMasaIsmData;
    5241             :     UWord8 enableCentering;
    5242             :     Word16 dirac_read_idx;
    5243             :     Word16 nSlots;
    5244             : 
    5245        5053 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
    5246        5053 :     hMasaIsmData = st_ivas->hMasaIsmData;
    5247             : 
    5248        5053 :     test();
    5249        5053 :     test();
    5250        5053 :     IF( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_HOA3 ) )
    5251             :     {
    5252        1216 :         enableCentering = 0;
    5253        1216 :         move16();
    5254             :     }
    5255             :     ELSE
    5256             :     {
    5257        3837 :         enableCentering = 1;
    5258        3837 :         move16();
    5259             :     }
    5260             : 
    5261             :     /* Bypass processing until first object is moved */
    5262        5053 :     IF( hMasaIsmData->objectsMoved == 0 )
    5263             :     {
    5264       21203 :         FOR( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ )
    5265             :         {
    5266       16150 :             if ( hMasaIsmData->ism_is_edited[ismDirIndex] )
    5267             :             {
    5268           0 :                 hMasaIsmData->objectsMoved = 1;
    5269           0 :                 move16();
    5270             :             }
    5271             :         }
    5272        5053 :         IF( hMasaIsmData->objectsMoved == 0 )
    5273             :         {
    5274             :             /* No objects have moved so far */
    5275        5053 :             return;
    5276             :         }
    5277             :     }
    5278             : 
    5279             :     /* Perform object-movement based processing */
    5280           0 :     nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
    5281           0 :     move16();
    5282           0 :     dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
    5283           0 :     move16();
    5284             : 
    5285           0 :     FOR( bin = 0; bin < nBins; bin++ )
    5286             :     {
    5287             :         Word16 ismPreprocMtxNew_fx[2][2];
    5288             :         Word16 ismPreprocMtxIncrement_fx[2][2];
    5289             :         Word16 eneMove_fx[2];
    5290             :         Word16 enePreserve_fx[2];
    5291             :         Word16 ismRatioAcc_fx;
    5292             :         Word32 subframeEne_fx;
    5293             :         Word32 Enes_fx[2];
    5294             :         Word16 normEnes_fx[2];
    5295             :         Word16 remainderNormEne_fx;
    5296           0 :         Word16 normEnes_q_fx[2], temp_q = 0;
    5297             :         Word16 eneMove_q_fx[2], enePreserve_q_fx[2], temp1;
    5298             :         Word32 temp;
    5299             : 
    5300           0 :         set16_fx( ismPreprocMtxNew_fx[0], 0, 2 );
    5301           0 :         set16_fx( ismPreprocMtxNew_fx[1], 0, 2 );
    5302           0 :         set16_fx( ismPreprocMtxIncrement_fx[0], 0, 2 );
    5303           0 :         set16_fx( ismPreprocMtxIncrement_fx[1], 0, 2 );
    5304           0 :         set16_fx( eneMove_fx, 0, 2 );
    5305           0 :         set16_fx( enePreserve_fx, 0, 2 );
    5306           0 :         ismRatioAcc_fx = 0;
    5307           0 :         move16();
    5308           0 :         subframeEne_fx = 0;
    5309           0 :         move32();
    5310           0 :         set16_fx( normEnes_fx, 0, 2 );
    5311           0 :         set32_fx( Enes_fx, 0, 2 );
    5312           0 :         set16_fx( normEnes_q_fx, Q31, 2 );
    5313           0 :         set16_fx( eneMove_q_fx, Q31, 2 );
    5314           0 :         set16_fx( enePreserve_q_fx, Q31, 2 );
    5315             : 
    5316             :         /* Determine transport normalized energies and subframe energy */
    5317           0 :         FOR( slot = 0; slot < nSlots; slot++ )
    5318             :         {
    5319           0 :             FOR( ch = 0; ch < 2; ch++ )
    5320             :             {
    5321           0 :                 Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
    5322           0 :                 move32();
    5323           0 :                 Enes_fx[ch] = L_add( Enes_fx[ch], Mpy_32_32( inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
    5324           0 :                 move32();
    5325             :             }
    5326             : 
    5327           0 :             subframeEne_fx = L_add( Enes_fx[0], Enes_fx[1] ); // Q = *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
    5328             : 
    5329           0 :             IF( subframeEne_fx != 0 )
    5330             :             {
    5331           0 :                 normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], subframeEne_fx, &temp_q );
    5332           0 :                 move32();
    5333           0 :                 normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12
    5334           0 :                 move32();
    5335           0 :                 normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], subframeEne_fx, &temp_q );
    5336           0 :                 move32();
    5337           0 :                 normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12
    5338           0 :                 move32();
    5339             :             }
    5340             :             ELSE
    5341             :             {
    5342           0 :                 normEnes_fx[0] = BASOP_Util_Divide3232_Scale( Enes_fx[0], EPSILON_FX, &temp_q );
    5343           0 :                 move32();
    5344           0 :                 normEnes_fx[0] = shr( normEnes_fx[0], sub( sub( 15, temp_q ), Q12 ) ); // Q12
    5345           0 :                 move32();
    5346           0 :                 normEnes_fx[1] = BASOP_Util_Divide3232_Scale( Enes_fx[1], EPSILON_FX, &temp_q );
    5347           0 :                 move32();
    5348           0 :                 normEnes_fx[1] = shr( normEnes_fx[1], sub( sub( 15, temp_q ), Q12 ) ); // Q12
    5349           0 :                 move32();
    5350             :             }
    5351             : 
    5352             : 
    5353             :             /* For each ismDir, formulate a mix-matrix that moves object audio signals between
    5354             :              * left and right channels when needed. Make a combined matrix by a ratio-weighted sum */
    5355           0 :             FOR( ismDirIndex = 0; ismDirIndex < hSpatParamRendCom->numIsmDirections; ismDirIndex++ )
    5356             :             {
    5357             :                 Word16 panGainsOut_fx[2];
    5358             :                 Word16 panGainsIn_fx[2];
    5359             :                 Word16 ratio;
    5360             :                 Word16 panEnesOut_fx[2];
    5361             :                 Word16 panEnesIn_fx[2];
    5362             :                 Word16 centeringFactor_fx;
    5363             : 
    5364           0 :                 ratio = extract_l( hMasaIsmData->energy_ratio_ism_fx[ismDirIndex][dirac_read_idx][bin] ); // Q14
    5365           0 :                 ismRatioAcc_fx = add( ismRatioAcc_fx, ratio );
    5366             : 
    5367             :                 /* Get input and output panning gains */
    5368           0 :                 ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx],
    5369           0 :                                                   hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx],
    5370             :                                                   panGainsIn_fx );
    5371             : 
    5372           0 :                 IF( hMasaIsmData->ism_is_edited[ismDirIndex] )
    5373             :                 {
    5374           0 :                     ivas_get_stereo_panning_gains_fx( hMasaIsmData->azimuth_ism_edited[ismDirIndex],
    5375           0 :                                                       hMasaIsmData->elevation_ism_edited[ismDirIndex],
    5376             :                                                       panGainsOut_fx );
    5377             :                 }
    5378             :                 ELSE
    5379             :                 {
    5380             :                     /* When not edited, input and output pan gains are the same */
    5381           0 :                     FOR( ch = 0; ch < 2; ch++ )
    5382             :                     {
    5383           0 :                         panGainsOut_fx[ch] = panGainsIn_fx[ch];
    5384           0 :                         move16();
    5385             :                     }
    5386             :                 }
    5387             : 
    5388             :                 /* Determine pan enes */
    5389           0 :                 FOR( ch = 0; ch < 2; ch++ )
    5390             :                 {
    5391           0 :                     panEnesOut_fx[ch] = mult( panGainsOut_fx[ch], panGainsOut_fx[ch] ); // Q15
    5392           0 :                     move16();
    5393           0 :                     panEnesIn_fx[ch] = mult( panGainsIn_fx[ch], panGainsIn_fx[ch] ); // Q15
    5394           0 :                     move16();
    5395             :                 }
    5396             : 
    5397           0 :                 IF( enableCentering )
    5398             :                 {
    5399           0 :                     centeringFactor_fx = s_max( 0, sub( mult( shl( 2, 13 ), abs_s( sub( panEnesIn_fx[0], panEnesOut_fx[0] ) ) ), ONE_IN_Q13 ) ); // Q13
    5400           0 :                     FOR( ch = 0; ch < 2; ch++ )
    5401             :                     {
    5402           0 :                         panEnesOut_fx[ch] = mult( panEnesOut_fx[ch], sub( ONE_IN_Q13, centeringFactor_fx ) ); // Q13
    5403           0 :                         move16();
    5404           0 :                         panEnesOut_fx[ch] = add( panEnesOut_fx[ch], shr( centeringFactor_fx, 1 ) ); // Q13
    5405           0 :                         move16();
    5406             :                     }
    5407             :                 }
    5408             : 
    5409           0 :                 FOR( ch = 0; ch < 2; ch++ )
    5410             :                 {
    5411             :                     Word16 eneMoveThis_fx;
    5412             :                     Word16 enePreserveThis_fx;
    5413             : 
    5414           0 :                     eneMoveThis_fx = s_max( 0, sub( shr( panEnesIn_fx[ch], 2 ), panEnesOut_fx[ch] ) ); // Q13
    5415           0 :                     enePreserveThis_fx = sub( shr( panEnesIn_fx[ch], 2 ), eneMoveThis_fx );            // Q13
    5416             : 
    5417           0 :                     eneMove_fx[ch] = mult( ratio, eneMoveThis_fx ); // Q = 14 + 13 - 15 = 12
    5418           0 :                     move16();
    5419           0 :                     enePreserve_fx[ch] = mult( ratio, enePreserveThis_fx ); // Q = 14 + 13 - 15 = 12
    5420           0 :                     move16();
    5421             : 
    5422             :                     /* Subtract object parts from normEnes */
    5423           0 :                     normEnes_fx[ch] = sub( normEnes_fx[ch], shr( mult( panEnesIn_fx[ch], ratio ), 2 ) ); // Q12
    5424           0 :                     move16();
    5425             :                 }
    5426             :             }
    5427             : 
    5428             :             /* Any remaining (non-object) energy is set to be preserved at both channels */
    5429           0 :             remainderNormEne_fx = s_max( 0, sub( sub( shr( sub( ONE_IN_Q14, ismRatioAcc_fx ), Q14 - Q12 ), normEnes_fx[0] ), normEnes_fx[1] ) ); // Q12
    5430             : 
    5431           0 :             FOR( ch = 0; ch < 2; ch++ )
    5432             :             {
    5433           0 :                 enePreserve_fx[ch] = add( enePreserve_fx[ch], s_max( 0, add( enePreserve_fx[ch], shr( remainderNormEne_fx, 1 ) ) ) ); // Q12
    5434           0 :                 move16();
    5435             :             }
    5436             : 
    5437             :             /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix */
    5438           0 :             FOR( ch = 0; ch < 2; ch++ )
    5439             :             {
    5440             :                 Word32 normVal_fx;
    5441           0 :                 hMasaIsmData->eneMoveIIR_fx[ch][bin] = Mpy_32_16_1( hMasaIsmData->eneMoveIIR_fx[ch][bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
    5442           0 :                 move32();
    5443           0 :                 temp = Mpy_32_16_1( subframeEne_fx, eneMove_fx[ch] );
    5444           0 :                 hMasaIsmData->eneMoveIIR_fx[ch][bin] = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], temp ); // Q = *cldfb_buf_q + *cldfb_buf_q - 34 = Q-22
    5445           0 :                 move32();
    5446             : 
    5447           0 :                 hMasaIsmData->enePreserveIIR_fx[ch][bin] = Mpy_32_16_1( hMasaIsmData->enePreserveIIR_fx[ch][bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
    5448           0 :                 move32();
    5449           0 :                 temp = Mpy_32_16_1( subframeEne_fx, enePreserve_fx[ch] );
    5450           0 :                 hMasaIsmData->enePreserveIIR_fx[ch][bin] = L_add( hMasaIsmData->enePreserveIIR_fx[ch][bin], temp ); // Q = *cldfb_buf_q + *cldfb_buf_q - 34 = Q-22
    5451           0 :                 move32();
    5452             : 
    5453           0 :                 normVal_fx = L_add( hMasaIsmData->eneMoveIIR_fx[ch][bin], hMasaIsmData->enePreserveIIR_fx[ch][bin] );
    5454           0 :                 IF( normVal_fx != 0 )
    5455             :                 {
    5456             : 
    5457           0 :                     temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->enePreserveIIR_fx[ch][bin], normVal_fx, &temp_q );
    5458           0 :                     ismPreprocMtxNew_fx[ch][ch] = Sqrt16( temp1, &temp_q );
    5459           0 :                     move16();
    5460           0 :                     ismPreprocMtxNew_fx[ch][ch] = shl( ismPreprocMtxNew_fx[ch][ch], temp_q ); // Q15
    5461           0 :                     move16();
    5462           0 :                     temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->eneMoveIIR_fx[ch][bin], normVal_fx, &temp_q );
    5463           0 :                     ismPreprocMtxNew_fx[sub( 1, ch )][ch] = Sqrt16( temp1, &temp_q );
    5464           0 :                     move16();
    5465           0 :                     ismPreprocMtxNew_fx[sub( 1, ch )][ch] = shl( ismPreprocMtxNew_fx[sub( 1, ch )][ch], temp_q ); // Q15
    5466           0 :                     move16();
    5467             :                 }
    5468             :                 ELSE
    5469             :                 {
    5470           0 :                     ismPreprocMtxNew_fx[ch][ch] = 0;
    5471           0 :                     move16();
    5472           0 :                     ismPreprocMtxNew_fx[sub( 1, ch )][ch] = 0;
    5473           0 :                     move16();
    5474             :                 }
    5475             :             }
    5476             : 
    5477             :             /* Get increment value for temporal interpolation */
    5478           0 :             FOR( inCh = 0; inCh < 2; inCh++ )
    5479             :             {
    5480           0 :                 FOR( outCh = 0; outCh < 2; outCh++ )
    5481           0 :                 ismPreprocMtxIncrement_fx[outCh][inCh] = BASOP_Util_Divide1616_Scale( sub( ismPreprocMtxNew_fx[outCh][inCh], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ), nSlots, &temp_q );
    5482           0 :                 move16();
    5483           0 :                 ismPreprocMtxIncrement_fx[outCh][inCh] = shl( ismPreprocMtxIncrement_fx[outCh][inCh], temp_q ); // Q15
    5484           0 :                 move16();
    5485             :             }
    5486             :         }
    5487             : 
    5488             :         /* Mix signals */
    5489           0 :         FOR( slot = 0; slot < nSlots; slot++ )
    5490             :         {
    5491           0 :             Word16 eqVal_fx = 0;
    5492           0 :             Word16 eqVal_q_fx = 0;
    5493           0 :             move16();
    5494           0 :             move16();
    5495             :             Word32 outSlotRe_fx[2];
    5496             :             Word32 outSlotIm_fx[2];
    5497             : 
    5498           0 :             set_zero_fx( outSlotRe_fx, 2 );
    5499           0 :             set_zero_fx( outSlotIm_fx, 2 );
    5500             : 
    5501           0 :             FOR( outCh = 0; outCh < 2; outCh++ )
    5502             :             {
    5503           0 :                 FOR( inCh = 0; inCh < 2; inCh++ )
    5504             :                 {
    5505           0 :                     hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] = add( hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin], ismPreprocMtxIncrement_fx[outCh][inCh] ); // Q = 15
    5506           0 :                     move16();
    5507           0 :                     outSlotRe_fx[outCh] = Mpy_32_16_1( inRe_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q;
    5508           0 :                     move32();
    5509           0 :                     outSlotIm_fx[outCh] = Mpy_32_16_1( inIm_fx[inCh][slot][bin], hMasaIsmData->ismPreprocMatrix_fx[outCh][inCh][bin] ); // Q = *cldfb_buf_q;
    5510           0 :                     move32();
    5511             :                 }
    5512             :             }
    5513             : 
    5514             :             /* IIR average the energy measures and determine and apply energy-preserving equalizer */
    5515           0 :             hMasaIsmData->preprocEneTarget_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneTarget_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
    5516           0 :             move32();
    5517           0 :             hMasaIsmData->preprocEneRealized_fx[bin] = Mpy_32_16_1( hMasaIsmData->preprocEneRealized_fx[bin], STEREO_PREPROCESS_IIR_FACTOR_Q15 );
    5518           0 :             move32();
    5519           0 :             FOR( ch = 0; ch < 2; ch++ )
    5520             :             {
    5521           0 :                 hMasaIsmData->preprocEneTarget_fx[bin] = L_add( hMasaIsmData->preprocEneTarget_fx[bin], Madd_32_32( Mpy_32_32( inRe_fx[ch][slot][bin], inRe_fx[ch][slot][bin] ), inIm_fx[ch][slot][bin], inIm_fx[ch][slot][bin] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
    5522           0 :                 move32();
    5523           0 :                 hMasaIsmData->preprocEneRealized_fx[bin] = L_add( hMasaIsmData->preprocEneRealized_fx[bin], Madd_32_32( Mpy_32_32( outSlotRe_fx[ch], outSlotRe_fx[ch] ), outSlotIm_fx[ch], outSlotIm_fx[ch] ) ); // Q= *cldfb_buf_q + *cldfb_buf_q - 31 = Q-19
    5524           0 :                 move32();
    5525             :             }
    5526           0 :             temp1 = BASOP_Util_Divide3232_Scale( hMasaIsmData->preprocEneTarget_fx[bin], L_max( EPSILON_FX, hMasaIsmData->preprocEneRealized_fx[bin] ), &eqVal_q_fx );
    5527           0 :             eqVal_fx = Sqrt16( temp1, &eqVal_q_fx );
    5528           0 :             temp1 = 4 << Q12; // Q12
    5529           0 :             move16();
    5530           0 :             IF( LT_16( eqVal_q_fx, Q12 ) )
    5531             :             {
    5532           0 :                 IF( GT_16( eqVal_fx, shr( temp1, sub( Q12, eqVal_q_fx ) ) ) )
    5533             :                 {
    5534           0 :                     eqVal_fx = temp1;
    5535           0 :                     move16();
    5536           0 :                     eqVal_q_fx = Q12;
    5537           0 :                     move16();
    5538             :                 }
    5539             :             }
    5540             :             ELSE
    5541             :             {
    5542           0 :                 if ( GT_16( shr( eqVal_fx, sub( eqVal_q_fx, Q12 ) ), temp1 ) )
    5543             :                 {
    5544           0 :                     eqVal_fx = temp1; // eqVal_q_fx
    5545           0 :                     move16();
    5546             :                 }
    5547             :             }
    5548             : 
    5549           0 :             FOR( ch = 0; ch < 2; ch++ )
    5550             :             {
    5551           0 :                 inRe_fx[ch][slot][bin] = Mpy_32_16_1( outSlotRe_fx[ch], eqVal_fx );
    5552           0 :                 move32();
    5553           0 :                 inIm_fx[ch][slot][bin] = Mpy_32_16_1( outSlotIm_fx[ch], eqVal_fx );
    5554           0 :                 move32();
    5555             :             }
    5556           0 :             *cldfb_buf_q = sub( add( *cldfb_buf_q, eqVal_q_fx ), 15 );
    5557           0 :             move16();
    5558             :         }
    5559             :     }
    5560             : 
    5561           0 :     return;
    5562             : }
    5563             : 
    5564             : 
    5565        7200 : static void ivas_masa_ext_rend_parambin_internal_fx(
    5566             :     MASA_EXT_REND_HANDLE hMasaExtRend,
    5567             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
    5568             :     Word32 *output_fx[], /* Q11*/
    5569             :     const Word16 subframe,
    5570             :     const SPLIT_REND_WRAPPER *hSplitRendWrapper,
    5571             :     Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
    5572             :     Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] )
    5573             : {
    5574             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
    5575             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    5576             :     PARAMBIN_REND_CONFIG config_data;
    5577             :     Word16 slot, ch, numInChannels;
    5578             :     Word16 max_band_decorr;
    5579             :     Word16 nBins;
    5580             :     Word16 i, j;
    5581             :     Word16 nchan_transport;
    5582             :     Word16 q_mat;
    5583             :     int16_t pos_idx;
    5584             :     const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
    5585             :     Word32 tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5586             :     Word32 tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5587             : 
    5588             :     /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */
    5589             :     Word32 reverbRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5590             :     Word32 reverbIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5591             :     Word32 decorrRe_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5592             :     Word32 decorrIm_fx[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5593             :     Word32 subFrameTotalEne_fx[CLDFB_NO_CHANNELS_MAX];
    5594             :     Word16 subFrameTotalEne_e[CLDFB_NO_CHANNELS_MAX];
    5595             :     Word32 IIReneLimiter_fx[CLDFB_NO_CHANNELS_MAX];
    5596             :     Word16 Q_inp_mix;
    5597             : 
    5598        7200 :     hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
    5599        7200 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
    5600             : 
    5601             :     Word32 Cldfb_RealBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5602             :     Word32 Cldfb_ImagBuffer_in_fx[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    5603             : 
    5604       50400 :     FOR( i = 0; i < 6; i++ )
    5605             :     {
    5606      216000 :         FOR( j = 0; j < CLDFB_SLOTS_PER_SUBFRAME; j++ )
    5607             :         {
    5608      172800 :             set32_fx( Cldfb_RealBuffer_in_fx[i][j], 0, CLDFB_NO_CHANNELS_MAX );
    5609      172800 :             set32_fx( Cldfb_ImagBuffer_in_fx[i][j], 0, CLDFB_NO_CHANNELS_MAX );
    5610             :         }
    5611             :     }
    5612             :     Word32 Rmat_fx[3][3];
    5613        7200 :     hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
    5614        7200 :     assert( hDiracDecBin );
    5615        7200 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
    5616        7200 :     nBins = hSpatParamRendCom->num_freq_bands;
    5617             : 
    5618             :     /* Setup internal config. MASA EXT renderer is quite strict. */
    5619        7200 :     config_data.separateCenterChannelRendering = 0;
    5620        7200 :     move16();
    5621        7200 :     config_data.ivas_format = MASA_FORMAT;
    5622        7200 :     move32();
    5623        7200 :     config_data.mc_mode = MC_MODE_NONE;
    5624        7200 :     move32();
    5625        7200 :     config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */
    5626        7200 :     move32();
    5627        7200 :     config_data.nchan_transport = hMasaExtRend->nchan_input;
    5628        7200 :     move16();
    5629        7200 :     config_data.qualityBasedSmFactor_fx = ONE_IN_Q31;
    5630        7200 :     move32();
    5631        7200 :     IF( EQ_16( hMasaExtRend->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
    5632             :     {
    5633           0 :         config_data.processReverb = 1;
    5634           0 :         move16();
    5635             :     }
    5636             :     ELSE
    5637             :     {
    5638        7200 :         config_data.processReverb = 0;
    5639        7200 :         move16();
    5640             :     }
    5641        7200 :     config_data.ism_mode = ISM_MODE_NONE;
    5642        7200 :     move32();
    5643             : 
    5644             :     /* Set nchan_transport to number of transport channels in MASA input */
    5645        7200 :     nchan_transport = hMasaExtRend->nchan_input;
    5646        7200 :     move16();
    5647             : 
    5648             :     /* The input channel number at this processing function (not nchan_transport) */
    5649        7200 :     numInChannels = BINAURAL_CHANNELS;
    5650        7200 :     move16();
    5651             : 
    5652        7200 :     Rmat_fx[0][0] = ONE_IN_Q30;
    5653        7200 :     Rmat_fx[0][1] = 0;
    5654        7200 :     Rmat_fx[0][2] = 0;
    5655        7200 :     move32();
    5656        7200 :     move32();
    5657        7200 :     move32();
    5658             : 
    5659        7200 :     Rmat_fx[1][0] = 0;
    5660        7200 :     Rmat_fx[1][1] = ONE_IN_Q30;
    5661        7200 :     Rmat_fx[1][2] = 0;
    5662        7200 :     move32();
    5663        7200 :     move32();
    5664        7200 :     move32();
    5665             : 
    5666        7200 :     Rmat_fx[2][0] = 0;
    5667        7200 :     Rmat_fx[2][1] = 0;
    5668        7200 :     Rmat_fx[2][2] = ONE_IN_Q30;
    5669        7200 :     move32();
    5670        7200 :     move32();
    5671        7200 :     move32();
    5672             : 
    5673             :     /* CLDFB Analysis of input */
    5674             : 
    5675       36000 :     FOR( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    5676             :     {
    5677       86400 :         FOR( ch = 0; ch < numInChannels; ch++ )
    5678             :         {
    5679       57600 :             test();
    5680       57600 :             IF( ch == 0 || EQ_16( nchan_transport, 2 ) )
    5681       43200 :             {
    5682       43200 :                 Word16 q_cldfb = Q11;
    5683       43200 :                 move16();
    5684       43200 :                 cldfbAnalysis_ts_fx_fixed_q(
    5685       43200 :                     &( output_fx[ch][nBins * slot] ),
    5686       43200 :                     Cldfb_RealBuffer_in_fx[ch][slot],
    5687       43200 :                     Cldfb_ImagBuffer_in_fx[ch][slot],
    5688             :                     nBins, hMasaExtRend->cldfbAnaRend[ch], &q_cldfb );
    5689             :             }
    5690             :             ELSE /* when nchan_transport == 1 and ch == 1 */
    5691             :             {
    5692             :                 /* At mono input duplicate the channel to dual-mono, and apply gain
    5693             :                 correction to ensure same overall level as in stereo mode  */
    5694       14400 :                 v_multc_fixed( Cldfb_RealBuffer_in_fx[0][slot], 1518500224 /* INV_SQRT_2 in Q31 */, Cldfb_RealBuffer_in_fx[0][slot], nBins );
    5695       14400 :                 v_multc_fixed( Cldfb_ImagBuffer_in_fx[0][slot], 1518500224 /* INV_SQRT_2 in Q31 */, Cldfb_ImagBuffer_in_fx[0][slot], nBins );
    5696             : 
    5697       14400 :                 Copy32( Cldfb_RealBuffer_in_fx[0][slot], Cldfb_RealBuffer_in_fx[1][slot], nBins );
    5698       14400 :                 Copy32( Cldfb_ImagBuffer_in_fx[0][slot], Cldfb_ImagBuffer_in_fx[1][slot], nBins );
    5699             :             }
    5700             :         }
    5701             :     }
    5702        7200 :     Word16 q_inp = Q6;
    5703        7200 :     move16();
    5704        7200 :     IF( hCombinedOrientationData )
    5705             :     {
    5706        9600 :         FOR( i = 0; i < 3; i++ )
    5707             :         {
    5708       28800 :             FOR( j = 0; j < 3; j++ )
    5709             :             {
    5710       21600 :                 Rmat_fx[i][j] = hCombinedOrientationData->Rmat_fx[hCombinedOrientationData->subframe_idx][i][j]; // Q30//
    5711       21600 :                 move32();
    5712             :             }
    5713             :         }
    5714             : 
    5715        2400 :         IF( EQ_16( nchan_transport, 2 ) )
    5716             :         {
    5717             :             /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
    5718        1200 :             adaptTransportSignalsHeadtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
    5719        1200 :             ivas_dirac_dec_binaural_check_and_switch_transports_headtracked_fx( hCombinedOrientationData, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat_fx );
    5720             :         }
    5721             :     }
    5722             : 
    5723        7200 :     test();
    5724             :     /* Always using CLDFB decorrelation in MASA EXT renderer */
    5725        7200 :     max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
    5726             : 
    5727        7200 :     ivas_dirac_dec_binaural_formulate_input_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, subframe,
    5728             :                                                                     subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, q_inp );
    5729        7200 :     ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_fx, subframe,
    5730        7200 :                                                                      hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
    5731             :                                                                      subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL );
    5732             : 
    5733        7200 :     ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_fx, subframe,
    5734        7200 :                                                               hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
    5735             :                                                               0, NULL );
    5736             : 
    5737             :     Word16 q_out;
    5738        7200 :     q_inp = Q6;
    5739        7200 :     move16();
    5740             : 
    5741       21600 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5742             :     {
    5743       14400 :         hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11;
    5744       14400 :         move16();
    5745             :     }
    5746             : 
    5747        7200 :     q_mat = hDiracDecBin->q_processMtx;
    5748        7200 :     move16();
    5749        7200 :     q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
    5750        7200 :     q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
    5751        7200 :     q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
    5752             : 
    5753       21600 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5754             :     {
    5755       43200 :         FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
    5756             :         {
    5757       28800 :             Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    5758       28800 :             Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    5759       28800 :             Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    5760       28800 :             Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    5761             :         }
    5762             :     }
    5763       21600 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5764             :     {
    5765       43200 :         FOR( slot = 0; slot < numInChannels; slot++ )
    5766             :         {
    5767       28800 :             Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    5768       28800 :             Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    5769       28800 :             Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    5770       28800 :             Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    5771             :         }
    5772             :     }
    5773        7200 :     hDiracDecBin->q_processMtx = q_mat;
    5774        7200 :     hDiracDecBin->q_processMtxPrev = q_mat;
    5775        7200 :     hDiracDecBin->q_processMtxDec = q_mat;
    5776        7200 :     hDiracDecBin->q_processMtxDecPrev = q_mat;
    5777        7200 :     move16();
    5778        7200 :     move16();
    5779        7200 :     move16();
    5780        7200 :     move16();
    5781             : 
    5782        7200 :     pMultiBinPoseData = NULL;
    5783        7200 :     if ( hSplitRendWrapper != NULL )
    5784             :     {
    5785           0 :         pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData );
    5786             : 
    5787           0 :         ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
    5788             :                                                    reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
    5789             : 
    5790           0 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5791             :         {
    5792           0 :             for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
    5793             :             {
    5794           0 :                 Copy32( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    5795           0 :                 Copy32( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    5796             :             }
    5797             :         }
    5798             :     }
    5799             :     else
    5800             :     {
    5801        7200 :         ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, NULL, NULL,
    5802             :                                                    reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 1 );
    5803             :     }
    5804             : 
    5805        7200 :     hDiracDecBin->hDiffuseDist = NULL;
    5806             : 
    5807        7200 :     if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
    5808             :     {
    5809             :         /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
    5810             :         IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
    5811             :         Word32 Rmat_local[3][3];
    5812             : 
    5813             : 
    5814           0 :         if ( hCombinedOrientationData )
    5815             :         {
    5816           0 :             Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
    5817           0 :             Copy_Quat_fx( Quaternions_ref, &Quaternions_abs );
    5818           0 :             modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, Q22 );
    5819           0 :             Quaternions_rot.w_fx = L_negate( 12582912 );                                                                 /* signal to use Euler */
    5820           0 :             Quat2EulerDegree_fx( Quaternions_abs, &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx ); /*order in Quat2Euler seems to be reversed ?*/
    5821           0 :             Quaternions_abs.w_fx = L_negate( 12582912 );                                                                 /* signal to use Euler */
    5822             : 
    5823           0 :             FOR( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
    5824             :             {
    5825           0 :                 Quaternions_rot.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
    5826           0 :                 Quaternions_rot.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
    5827           0 :                 Quaternions_rot.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
    5828           0 :                 move32();
    5829           0 :                 move32();
    5830           0 :                 move32();
    5831           0 :                 Euler2Quat_fx( deg2rad_fx( Quaternions_rot.x_fx ), deg2rad_fx( Quaternions_rot.y_fx ), deg2rad_fx( Quaternions_rot.z_fx ), &Quaternions_rot );
    5832           0 :                 modify_Quat_q_fx( &Quaternions_rot, &Quaternions_rot, Quaternions_ref->q_fact );
    5833           0 :                 QuatToRotMat_fx( Quaternions_rot, Rmat_local );
    5834           0 :                 modify_Rmat_q_fx( Rmat_local, Rmat_local, sub( shl( Quaternions_ref->q_fact, 1 ), 32 ), Q30 );
    5835             : 
    5836           0 :                 hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx];
    5837           0 :                 assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
    5838             : 
    5839             :                 /* re-use input covariance for the side renderings */
    5840           0 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5841             :                 {
    5842           0 :                     Copy32( hMasaExtRend->hDiracDecBin[0]->ChEne_fx[ch], hDiracDecBin->ChEne_fx[ch], hSpatParamRendCom->num_freq_bands );
    5843           0 :                     Copy( hMasaExtRend->hDiracDecBin[0]->ChEne_e[ch], hDiracDecBin->ChEne_e[ch], hSpatParamRendCom->num_freq_bands );
    5844             :                 }
    5845           0 :                 Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_fx, hDiracDecBin->ChCrossRe_fx, hSpatParamRendCom->num_freq_bands );
    5846           0 :                 Copy32( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_fx, hDiracDecBin->ChCrossIm_fx, hSpatParamRendCom->num_freq_bands );
    5847           0 :                 Copy( hMasaExtRend->hDiracDecBin[0]->ChCrossRe_e, hDiracDecBin->ChCrossRe_e, hSpatParamRendCom->num_freq_bands );
    5848           0 :                 Copy( hMasaExtRend->hDiracDecBin[0]->ChCrossIm_e, hDiracDecBin->ChCrossIm_e, hSpatParamRendCom->num_freq_bands );
    5849             : 
    5850           0 :                 ivas_dirac_dec_binaural_formulate_target_covariance_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
    5851           0 :                                                                                  hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    5852             :                                                                                  subFrameTotalEne_fx, subFrameTotalEne_e, IIReneLimiter_fx, NULL );
    5853             : 
    5854           0 :                 ivas_dirac_dec_binaural_determine_processing_matrices_fx( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
    5855           0 :                                                                           hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    5856             :                                                                           0, NULL );
    5857             : 
    5858             : 
    5859           0 :                 q_mat = hDiracDecBin->q_processMtx;
    5860           0 :                 move16();
    5861           0 :                 q_mat = s_min( q_mat, hDiracDecBin->q_processMtxPrev );
    5862           0 :                 q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDec );
    5863           0 :                 q_mat = s_min( q_mat, hDiracDecBin->q_processMtxDecPrev );
    5864             : 
    5865           0 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5866             :                 {
    5867           0 :                     FOR( slot = 0; slot < BINAURAL_CHANNELS; slot++ )
    5868             :                     {
    5869           0 :                         Scale_sig( hDiracDecBin->processMtxDecRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    5870           0 :                         Scale_sig( hDiracDecBin->processMtxDecIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDec ) );         // scaling to q_mat
    5871           0 :                         Scale_sig( hDiracDecBin->processMtxDecRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    5872           0 :                         Scale_sig( hDiracDecBin->processMtxDecImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxDecPrev ) ); // scaling to q_mat
    5873             :                     }
    5874             :                 }
    5875           0 :                 FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5876             :                 {
    5877           0 :                     FOR( slot = 0; slot < numInChannels; slot++ )
    5878             :                     {
    5879           0 :                         Scale_sig( hDiracDecBin->processMtxRe_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    5880           0 :                         Scale_sig( hDiracDecBin->processMtxIm_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtx ) );         // scaling to q_mat
    5881           0 :                         Scale_sig( hDiracDecBin->processMtxRePrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    5882           0 :                         Scale_sig( hDiracDecBin->processMtxImPrev_fx[ch][slot], nBins, sub( q_mat, hDiracDecBin->q_processMtxPrev ) ); // scaling to q_mat
    5883             :                     }
    5884             :                 }
    5885           0 :                 hDiracDecBin->q_processMtx = q_mat;
    5886           0 :                 hDiracDecBin->q_processMtxPrev = q_mat;
    5887           0 :                 hDiracDecBin->q_processMtxDec = q_mat;
    5888           0 :                 hDiracDecBin->q_processMtxDecPrev = q_mat;
    5889           0 :                 move16();
    5890           0 :                 move16();
    5891           0 :                 move16();
    5892           0 :                 move16();
    5893             :                 /* re-use reverb and decorr from main direction for the sides */
    5894           0 :                 ivas_dirac_dec_binaural_process_output_fx( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_fx, &q_out, Cldfb_RealBuffer_in_fx, Cldfb_ImagBuffer_in_fx, q_inp, max_band_decorr, numInChannels, config_data.processReverb, subframe, q_mat, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
    5895             :                                                            reverbRe_fx, reverbIm_fx, decorrRe_fx, decorrIm_fx, &Q_inp_mix, 0 );
    5896             : 
    5897             :                 /* copy from temporary buffer to the main split rendering buffer */
    5898           0 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5899             :                 {
    5900           0 :                     for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
    5901             :                     {
    5902           0 :                         Copy32( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    5903           0 :                         Copy32( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    5904             :                     }
    5905             :                 }
    5906             : 
    5907           0 :                 hDiracDecBin->hDiffuseDist = NULL;
    5908             :             }
    5909             :         }
    5910             :     }
    5911             : 
    5912             :     /* update this counter only after the last rendering of split directions */
    5913             : 
    5914        7200 :     hSpatParamRendCom->slots_rendered = add( hSpatParamRendCom->slots_rendered, hSpatParamRendCom->subframe_nbslots[subframe] );
    5915        7200 :     hSpatParamRendCom->subframes_rendered = add( hSpatParamRendCom->subframes_rendered, 1 );
    5916        7200 :     move16();
    5917        7200 :     move16();
    5918             : 
    5919       21600 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5920             :     {
    5921       14400 :         scale_sig32( output_fx[ch], nBins * hSpatParamRendCom->subframe_nbslots[subframe], sub( Q11, q_out ) );                                                               // Q11
    5922       14400 :         scale_sig32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); // Q11
    5923       14400 :         hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11;
    5924             :     }
    5925             : 
    5926        7200 :     return;
    5927             : }
    5928             : 
    5929        4500 : void ivas_masa_ext_rend_parambin_render_fx(
    5930             :     MASA_EXT_REND_HANDLE hMasaExtRend,                                /* i/o: MASA ext rend structure                                   */
    5931             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,             /* i  : combined orientation handle                               */
    5932             :     Word32 *output_f[],                                               /* i/o: synthesized core-coder transport channels/DirAC output Q11*/
    5933             :     const Word16 num_subframes,                                       /* i  : number of subframes to render                            */
    5934             :     const SPLIT_REND_WRAPPER *hSplitRendWrapper,                      /* i  : split rendering orientation data                         */
    5935             :     Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o  : rendered orientations for split rend. real part of cldfb */
    5936             :     Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]  /* o  : rendered orientations for split rend. imag part of cldfb */
    5937             : )
    5938             : {
    5939             :     Word16 subframe;
    5940             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    5941             :     Word32 *p_output[BINAURAL_CHANNELS];
    5942             :     Word16 ch;
    5943             : 
    5944        4500 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
    5945             : 
    5946       13500 :     FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5947             :     {
    5948        9000 :         p_output[ch] = output_f[ch];
    5949             :     }
    5950             : 
    5951        4500 :     hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx;
    5952        4500 :     move16();
    5953       11700 :     FOR( subframe = 0; subframe < num_subframes; subframe++ )
    5954             :     {
    5955        7200 :         Word16 n_samples_sf = i_mult( hSpatParamRendCom->slot_size, CLDFB_SLOTS_PER_SUBFRAME );
    5956        7200 :         hSpatParamRendCom->slots_rendered = 0;
    5957        7200 :         move16();
    5958             : 
    5959        7200 :         ivas_masa_ext_rend_parambin_internal_fx( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag );
    5960       21600 :         FOR( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    5961             :         {
    5962       14400 :             p_output[ch] += n_samples_sf;
    5963             :         }
    5964             : 
    5965        7200 :         ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_sf );
    5966             : 
    5967        7200 :         hSpatParamRendCom->dirac_read_idx = ( add( hSpatParamRendCom->dirac_read_idx, 1 ) ) % hSpatParamRendCom->dirac_md_buffer_length;
    5968        7200 :         move16();
    5969             :     }
    5970             : 
    5971        4500 :     return;
    5972             : }

Generated by: LCOV version 1.14