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

Generated by: LCOV version 1.14