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 enc/dec/rend @ 3b2f07138c61dcf997bbf4165d0882f794b2995f Lines: 2521 2770 91.0 %
Date: 2025-05-03 01:55:50 Functions: 25 25 100.0 %

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

Generated by: LCOV version 1.14