LCOV - code coverage report
Current view: top level - lib_rend - ivas_dirac_dec_binaural_functions.c (source / functions) Hit Total Coverage
Test: Coverage on main -- merged total coverage @ a21f94bc6bac334fe001a5bad2f7b32b79038097 Lines: 1289 1356 95.1 %
Date: 2025-11-01 08:50:45 Functions: 26 26 100.0 %

          Line data    Source code
       1             : /******************************************************************************************************
       2             : 
       3             :    (C) 2022-2025 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
       4             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
       5             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
       6             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
       7             :    contributors to this repository. All Rights Reserved.
       8             : 
       9             :    This software is protected by copyright law and by international treaties.
      10             :    The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
      11             :    Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
      12             :    Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
      13             :    Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
      14             :    contributors to this repository retain full ownership rights in their respective contributions in
      15             :    the software. This notice grants no license of any kind, including but not limited to patent
      16             :    license, nor is any license granted by implication, estoppel or otherwise.
      17             : 
      18             :    Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
      19             :    contributions.
      20             : 
      21             :    This software is provided "AS IS", without any express or implied warranties. The software is in the
      22             :    development stage. It is intended exclusively for experts who have experience with such software and
      23             :    solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
      24             :    and fitness for a particular purpose are hereby disclaimed and excluded.
      25             : 
      26             :    Any dispute, controversy or claim arising under or in relation to providing this software shall be
      27             :    submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
      28             :    accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
      29             :    the United Nations Convention on Contracts on the International Sales of Goods.
      30             : 
      31             : *******************************************************************************************************/
      32             : 
      33             : #include <stdint.h>
      34             : #include "options.h"
      35             : #include <assert.h>
      36             : #include <math.h>
      37             : #include "prot.h"
      38             : #include "ivas_prot.h"
      39             : #include "ivas_prot_rend.h"
      40             : #include "ivas_cnst.h"
      41             : #include "ivas_rom_binauralRenderer.h"
      42             : #include "ivas_rom_rend.h"
      43             : #include "ivas_rom_com.h"
      44             : 
      45             : #ifdef DEBUGGING
      46             : #include "debug.h"
      47             : #endif
      48             : #include "wmc_auto.h"
      49             : 
      50             : 
      51             : /*-------------------------------------------------------------------------
      52             :  * Local constants
      53             :  *------------------------------------------------------------------------*/
      54             : 
      55             : #define CLDFB_HALF_BIN_FREQUENCY_OFFSET         0.5f
      56             : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN        ( 2.0f )
      57             : #define IVAS_TDET_DUCK_MULT_FAC_PARA_BIN_LOW_BR ( 3.0f )
      58             : #define SBA_CARDI_TARGET_ENERGY_GAIN            0.5f
      59             : 
      60             : #define STEREO_PREPROCESS_IIR_FACTOR ( 0.9f )
      61             : 
      62             : /* powf(0.95f, 4.0f) for sub-frame smoothing instead of CLDFB slot */
      63             : #define ADAPT_HTPROTO_IIR_FAC 0.81450625f
      64             : 
      65             : #define ADAPT_HTPROTO_ILD_LIM_DB0 1.0f
      66             : #define ADAPT_HTPROTO_ILD_LIM_DB1 4.0f
      67             : #define ADAPT_HTPROTO_ROT_LIM_0   0.4f
      68             : #define ADAPT_HTPROTO_ROT_LIM_1   0.8f
      69             : 
      70             : #define MAX_GAIN_CACHE_SIZE ( ( MASA_MAXIMUM_DIRECTIONS * 3 ) + MAX_NUM_OBJECTS ) /* == different calls to get gains */
      71             : 
      72             : typedef struct hrtfGainCache
      73             : {
      74             :     int16_t azi;
      75             :     int16_t ele;
      76             : 
      77             :     float shVec[HRTF_SH_CHANNELS];
      78             : } PARAMBIN_HRTF_GAIN_CACHE;
      79             : 
      80             : typedef struct parambin_rend_config_data
      81             : {
      82             :     int16_t separateCenterChannelRendering;
      83             :     IVAS_FORMAT ivas_format;
      84             :     MC_MODE mc_mode;
      85             :     int32_t ivas_total_brate;
      86             :     int16_t nchan_transport;
      87             :     float qualityBasedSmFactor;
      88             :     int16_t processReverb;
      89             :     ISM_MODE ism_mode;
      90             : } PARAMBIN_REND_CONFIG, *PARAMBIN_REND_CONFIG_HANDLE;
      91             : 
      92             : 
      93             : /*-------------------------------------------------------------------------
      94             :  * Local function prototypes
      95             :  *------------------------------------------------------------------------*/
      96             : 
      97             : static void ivas_dirac_dec_binaural_internal( Decoder_Struct *st_ivas, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t nchan_transport, const int16_t subframe );
      98             : 
      99             : static void ivas_dirac_dec_decorrelate_slot( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const int16_t num_freq_bands, const int16_t slot, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decRe[][CLDFB_NO_CHANNELS_MAX], float decIm[][CLDFB_NO_CHANNELS_MAX] );
     100             : 
     101             : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t subframe, float *subFrameTotalEne, float *IIReneLimiter );
     102             : 
     103             : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, const PARAMBIN_REND_CONFIG_HANDLE hConfig, float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const float *subFrameTotalEne, const float *IIReneLimiter, const MASA_ISM_DATA_HANDLE hMasaIsmData );
     104             : 
     105             : static void ivas_dirac_dec_binaural_determine_processing_matrices( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, PARAMBIN_REND_CONFIG_HANDLE hConfig, const int16_t max_band_decorr, float Rmat[3][3], const int16_t subframe, const int16_t isHeadtracked, const int16_t nchanSeparateChannels, const MASA_ISM_DATA_HANDLE hMasaIsmData );
     106             : 
     107             : static void ivas_dirac_dec_binaural_process_output( DIRAC_DEC_BIN_HANDLE hDiracDecBin, SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom, HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS], float *output_f[], float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t max_band_decorr, const int16_t numInChannels, const int16_t processReverb, const int16_t subframe, float outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const uint8_t recompute );
     108             : 
     109             : static void adaptTransportSignalsHeadtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] );
     110             : 
     111             : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( COMBINED_ORIENTATION_HANDLE hHeadTrackData, float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX], const int16_t nBins, const int16_t nSlots, float Rmat[3][3] );
     112             : 
     113             : static void formulate2x2MixingMatrix( float Ein1, float Ein2, float CinRe, float CinIm, float Eout1, float Eout2, float CoutRe, float CoutIm, float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], const float regularizationFactor );
     114             : 
     115             : static void hrtfShGetHrtf( const int16_t bin, const int16_t aziDeg, const int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t useCachedValue, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
     116             : 
     117             : static void getDirectPartGains( const int16_t bin, int16_t aziDeg, int16_t eleDeg, float *lRealp, float *lImagp, float *rRealp, float *rImagp, const uint8_t stereoMode, float Rmat[3][3], PARAMBIN_HRTF_GAIN_CACHE *gainCache, const int16_t isHeadtracked, HRTFS_PARAMBIN_HANDLE hHrtfParambin );
     118             : 
     119             : static void matrixMul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] );
     120             : 
     121             : static void matrixTransp2Mul( float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] );
     122             : 
     123             : static void ivas_masa_ext_rend_parambin_internal( MASA_EXT_REND_HANDLE hMasaExtRend, COMBINED_ORIENTATION_HANDLE hCombinedOrientationData, float *output_f[], const int16_t subframe, const SPLIT_REND_WRAPPER *hSplitRendWrapper, float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] );
     124             : 
     125             : 
     126             : /*-------------------------------------------------------------------------
     127             :  * ivas_dirac_dec_init_binaural_data()
     128             :  *
     129             :  * Initialize parametric binaural renderer
     130             :  *------------------------------------------------------------------------*/
     131             : 
     132       33796 : ivas_error ivas_dirac_dec_init_binaural_data(
     133             :     Decoder_Struct *st_ivas,              /* i/o: IVAS decoder structure                  */
     134             :     HRTFS_PARAMBIN_HANDLE *phHrtfParambin /* i  : HRTF structure for rendering            */
     135             : )
     136             : {
     137             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
     138             :     int16_t nBins;
     139             :     int32_t output_Fs;
     140             :     RENDERER_TYPE renderer_type;
     141             :     int16_t j, k, bin;
     142             :     float binCenterFreq, tmpFloat;
     143             :     ivas_error error;
     144             :     float frequency_axis[CLDFB_NO_CHANNELS_MAX];
     145             :     int16_t num_poses, pos_idx;
     146             :     const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics;
     147             : 
     148       33796 :     num_poses = 1;
     149       33796 :     if ( st_ivas->hSplitBinRend != NULL )
     150             :     {
     151        1444 :         num_poses = st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses;
     152             :     }
     153             : 
     154       33796 :     output_Fs = st_ivas->hDecoderConfig->output_Fs;
     155       33796 :     nBins = st_ivas->hSpatParamRendCom->num_freq_bands;
     156       33796 :     renderer_type = st_ivas->renderer_type;
     157             : 
     158       72024 :     for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
     159             :     {
     160       38228 :         hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
     161             : 
     162       38228 :         if ( hDiracDecBin == NULL )
     163             :         {
     164       38228 :             if ( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL )
     165             :             {
     166           0 :                 return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " );
     167             :             }
     168             : 
     169       38228 :             hDiracDecBin->hTdDecorr = NULL;
     170       38228 :             hDiracDecBin->hReverb = NULL;
     171       38228 :             hDiracDecBin->h_freq_domain_decorr_ap_params = NULL;
     172       38228 :             hDiracDecBin->h_freq_domain_decorr_ap_state = NULL;
     173       38228 :             hDiracDecBin->phHrtfParambin = NULL;
     174             :         }
     175             : 
     176      114684 :         for ( j = 0; j < BINAURAL_CHANNELS; j++ )
     177             :         {
     178      535192 :             for ( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ )
     179             :             {
     180      458736 :                 set_zero( hDiracDecBin->processMtxRe[j][k], nBins );
     181      458736 :                 set_zero( hDiracDecBin->processMtxIm[j][k], nBins );
     182             :             }
     183             : 
     184      229368 :             for ( k = 0; k < BINAURAL_CHANNELS; k++ )
     185             :             {
     186      152912 :                 set_zero( hDiracDecBin->processMtxDecRe[j][k], nBins );
     187      152912 :                 set_zero( hDiracDecBin->processMtxDecIm[j][k], nBins );
     188             :             }
     189       76456 :             set_zero( hDiracDecBin->ChEnePrev[j], nBins );
     190       76456 :             set_zero( hDiracDecBin->ChEneOutPrev[j], nBins );
     191             :         }
     192       38228 :         set_zero( hDiracDecBin->ChCrossRePrev, nBins );
     193       38228 :         set_zero( hDiracDecBin->ChCrossImPrev, nBins );
     194       38228 :         set_zero( hDiracDecBin->ChCrossReOutPrev, nBins );
     195       38228 :         set_zero( hDiracDecBin->ChCrossImOutPrev, nBins );
     196       38228 :         hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0;
     197             : 
     198             : 
     199     1862448 :         for ( bin = 0; bin < nBins; bin++ )
     200             :         {
     201     1824220 :             binCenterFreq = ( (float) bin + CLDFB_HALF_BIN_FREQUENCY_OFFSET ) / (float) nBins * ( (float) output_Fs / 2.0f );
     202             :             /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */
     203     1824220 :             tmpFloat = max( 0.0f, 1.0f - binCenterFreq / 2700.0f );
     204     1824220 :             hDiracDecBin->diffuseFieldCoherence[bin] = tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );
     205             :         }
     206             : 
     207      382280 :         for ( bin = 0; bin < BINAURAL_COHERENCE_DIFFERENCE_BINS; bin++ )
     208             :         {
     209      344052 :             hDiracDecBin->diffuseFieldCoherenceX[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceX[bin];
     210      344052 :             hDiracDecBin->diffuseFieldCoherenceY[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceY[bin];
     211      344052 :             hDiracDecBin->diffuseFieldCoherenceZ[bin] = hDiracDecBin->diffuseFieldCoherence[bin] + diffuseFieldCoherenceDifferenceZ[bin];
     212             :         }
     213             : 
     214       38228 :         if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC ) /* Indication of binaural rendering without room effect */
     215             :         {
     216       19317 :             set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
     217       19317 :             hDiracDecBin->hReverb = NULL;
     218             :         }
     219       18911 :         else if ( renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) /* Indication of binaural rendering with room effect */
     220             :         {
     221       17858 :             if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR )
     222             :             {
     223       10134 :                 mvr2r( ( *phHrtfParambin )->parametricEarlyPartEneCorrection, hDiracDecBin->earlyPartEneCorrection, nBins );
     224       10134 :                 pRoomAcoustics = NULL;
     225             :             }
     226             :             else
     227             :             {
     228        7724 :                 set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
     229        7724 :                 pRoomAcoustics = &( st_ivas->hRenderConfig->roomAcoustics );
     230             :             }
     231             : 
     232             :             /* reconfiguration needed when Reverb. parameters are changed -> close and open the handle again */
     233       17858 :             if ( hDiracDecBin->hReverb != NULL && ( ( hDiracDecBin->hReverb->numBins != nBins ) ||
     234           0 :                                                     ( hDiracDecBin->hReverb->blockSize != CLDFB_SLOTS_PER_SUBFRAME ) ) )
     235             :             {
     236           0 :                 ivas_binaural_reverb_close( &( hDiracDecBin->hReverb ) );
     237             :             }
     238             : 
     239       17858 :             if ( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */
     240             :             {
     241       17858 :                 if ( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb,
     242             :                                                           st_ivas->hHrtfStatistics,
     243             :                                                           nBins,
     244             :                                                           CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES,
     245             :                                                           pRoomAcoustics,
     246             :                                                           output_Fs,
     247       17858 :                                                           ( *phHrtfParambin )->parametricReverberationTimes,
     248       17858 :                                                           ( *phHrtfParambin )->parametricReverberationEneCorrections,
     249       17858 :                                                           hDiracDecBin->earlyPartEneCorrection ) ) != IVAS_ERR_OK )
     250             :                 {
     251           0 :                     return error;
     252             :                 }
     253             :             }
     254             :         }
     255        1053 :         else if ( renderer_type == RENDERER_STEREO_PARAMETRIC )
     256             :         {
     257        1053 :             set_f( hDiracDecBin->earlyPartEneCorrection, 1.0f, CLDFB_NO_CHANNELS_MAX );
     258        1053 :             hDiracDecBin->hReverb = NULL;
     259        1053 :             hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1;
     260             :         }
     261             :         else /* Not valid renderer type for this renderer */
     262             :         {
     263           0 :             assert( false );
     264             :         }
     265             : 
     266       38228 :         hDiracDecBin->hDiffuseDist = NULL; /* Memory is allocated from stack during runtime when needed */
     267             : 
     268       38228 :         if ( hDiracDecBin->hTdDecorr == NULL )
     269             :         {
     270       38228 :             hDiracDecBin->useTdDecorr = 0;
     271             :         }
     272             : 
     273       38228 :         if ( hDiracDecBin->h_freq_domain_decorr_ap_params != NULL )
     274             :         {
     275           0 :             ivas_dirac_dec_decorr_close( &hDiracDecBin->h_freq_domain_decorr_ap_params, &hDiracDecBin->h_freq_domain_decorr_ap_state );
     276             :         }
     277             : 
     278       38228 :         if ( pos_idx == 0 ) /* open decorrelator only for the main direction */
     279             :         {
     280       33796 :             if ( ( 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 )
     281             :             {
     282           0 :                 return error;
     283             :             }
     284             : 
     285       33796 :             if ( !hDiracDecBin->useTdDecorr && !( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM ) )
     286             :             {
     287       12031 :                 ivas_dirac_dec_get_frequency_axis( frequency_axis, output_Fs, nBins );
     288             : 
     289       12031 :                 if ( ( error = ivas_dirac_dec_decorr_open( &( hDiracDecBin->h_freq_domain_decorr_ap_params ),
     290       12031 :                                                            &( hDiracDecBin->h_freq_domain_decorr_ap_state ),
     291             :                                                            nBins,
     292             :                                                            BINAURAL_CHANNELS,
     293             :                                                            BINAURAL_CHANNELS,
     294             :                                                            DIRAC_SYNTHESIS_PSD_LS,
     295             :                                                            frequency_axis,
     296             :                                                            BINAURAL_CHANNELS,
     297             :                                                            output_Fs ) ) != IVAS_ERR_OK )
     298             :                 {
     299           0 :                     return error;
     300             :                 }
     301             :             }
     302             :         }
     303             :         else
     304             :         {
     305        4432 :             hDiracDecBin->useTdDecorr = st_ivas->hDiracDecBin[0]->useTdDecorr; /* copy the flag, but the implementation re-uses the decorrelated signal */
     306             :         }
     307             : 
     308       38228 :         hDiracDecBin->reqularizationFactor = configure_reqularization_factor( st_ivas->ivas_format, st_ivas->hDecoderConfig->ivas_total_brate );
     309             : 
     310       38228 :         hDiracDecBin->phHrtfParambin = phHrtfParambin;
     311             : 
     312       38228 :         st_ivas->hDiracDecBin[pos_idx] = hDiracDecBin;
     313             :     }
     314             : 
     315             :     /* allocate transport channels */
     316       33796 :     if ( st_ivas->hTcBuffer == NULL )
     317             :     {
     318             :         int16_t nchan_to_allocate;
     319             :         int16_t n_samples_granularity;
     320             : 
     321        7824 :         nchan_to_allocate = BINAURAL_CHANNELS;
     322        7824 :         if ( st_ivas->hDiracDecBin[0] != NULL && st_ivas->hDiracDecBin[0]->useTdDecorr )
     323             :         {
     324        2200 :             nchan_to_allocate = 2 * BINAURAL_CHANNELS;
     325             :         }
     326        5624 :         else if ( st_ivas->hOutSetup.separateChannelEnabled )
     327             :         {
     328         135 :             nchan_to_allocate++;
     329             :         }
     330        7824 :         if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
     331             :         {
     332        3458 :             nchan_to_allocate = BINAURAL_CHANNELS + st_ivas->nchan_ism;
     333             :         }
     334             : 
     335        7824 :         n_samples_granularity = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, ivas_renderer_secondary_select( st_ivas ), output_Fs );
     336             : 
     337        7824 :         if ( ( error = ivas_jbm_dec_tc_buffer_open( st_ivas, TC_BUFFER_MODE_RENDERER, ivas_jbm_dec_get_num_tc_channels( st_ivas ), nchan_to_allocate, nchan_to_allocate, n_samples_granularity ) ) != IVAS_ERR_OK )
     338             :         {
     339           0 :             return error;
     340             :         }
     341             :     }
     342       33796 :     return IVAS_ERR_OK;
     343             : }
     344             : 
     345             : 
     346             : /*-------------------------------------------------------------------------
     347             :  * ivas_dirac_dec_close_binaural_data()
     348             :  *
     349             :  * Close parametric binaural renderer
     350             :  *------------------------------------------------------------------------*/
     351             : 
     352      298361 : void ivas_dirac_dec_close_binaural_data(
     353             :     DIRAC_DEC_BIN_HANDLE *hBinaural /* i/o: decoder DirAC binaural data handle  */
     354             : )
     355             : {
     356             :     int16_t pos_idx;
     357             : 
     358      298361 :     if ( hBinaural == NULL || *hBinaural == NULL )
     359             :     {
     360      263157 :         return;
     361             :     }
     362             : 
     363      316836 :     for ( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
     364             :     {
     365      281632 :         if ( hBinaural[pos_idx] != NULL )
     366             :         {
     367       40052 :             if ( hBinaural[pos_idx]->hReverb != NULL )
     368             :             {
     369       18578 :                 ivas_binaural_reverb_close( &( hBinaural[pos_idx]->hReverb ) );
     370             :             }
     371             : 
     372       40052 :             ivas_td_decorr_dec_close( &( hBinaural[pos_idx]->hTdDecorr ) );
     373             : 
     374       40052 :             if ( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params != NULL )
     375             :             {
     376       13814 :                 ivas_dirac_dec_decorr_close( &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_params ), &( hBinaural[pos_idx]->h_freq_domain_decorr_ap_state ) );
     377             :             }
     378             : 
     379       40052 :             free( hBinaural[pos_idx] );
     380       40052 :             hBinaural[pos_idx] = NULL;
     381             :         }
     382             :     }
     383             : 
     384       35204 :     return;
     385             : }
     386             : 
     387             : /*-------------------------------------------------------------------------
     388             :  * ivas_dirac_dec_binaural_copy_hrtfs()
     389             :  *
     390             :  * Temporary function for copying HRTF data from rom tables if no binary
     391             :  * file was given.
     392             :  *------------------------------------------------------------------------*/
     393             : 
     394      151689 : ivas_error ivas_dirac_dec_binaural_copy_hrtfs(
     395             :     HRTFS_PARAMBIN_HANDLE *hHrtfParambin /* i/o: HRTF structure for rendering */
     396             : )
     397             : {
     398             :     int16_t i, j;
     399             : 
     400      151689 :     if ( hHrtfParambin != NULL && *hHrtfParambin != NULL )
     401             :     {
     402             :         /* Tables already loaded from file */
     403      139658 :         return IVAS_ERR_OK;
     404             :     }
     405             :     else
     406             :     {
     407             :         /* Initialise tables from ROM */
     408             :         HRTFS_PARAMBIN *hrtfParambin;
     409             : 
     410       12031 :         if ( ( hrtfParambin = (HRTFS_PARAMBIN *) malloc( sizeof( HRTFS_PARAMBIN ) ) ) == NULL )
     411             :         {
     412           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Could not allocate memory for parametric binauralizer HRTF tables" );
     413             :         }
     414             : 
     415       36093 :         for ( i = 0; i < BINAURAL_CHANNELS; i++ )
     416             :         {
     417      409054 :             for ( j = 0; j < HRTF_SH_CHANNELS; j++ )
     418             :             {
     419      384992 :                 mvr2r( hrtfShCoeffsRe[i][j], hrtfParambin->hrtfShCoeffsRe[i][j], HRTF_NUM_BINS );
     420      384992 :                 mvr2r( hrtfShCoeffsIm[i][j], hrtfParambin->hrtfShCoeffsIm[i][j], HRTF_NUM_BINS );
     421             :             }
     422             :         }
     423             : 
     424       12031 :         mvr2r( parametricReverberationTimes, hrtfParambin->parametricReverberationTimes, CLDFB_NO_CHANNELS_MAX );
     425       12031 :         mvr2r( parametricReverberationEneCorrections, hrtfParambin->parametricReverberationEneCorrections, CLDFB_NO_CHANNELS_MAX );
     426       12031 :         mvr2r( parametricEarlyPartEneCorrection, hrtfParambin->parametricEarlyPartEneCorrection, CLDFB_NO_CHANNELS_MAX );
     427             : 
     428       12031 :         *hHrtfParambin = hrtfParambin;
     429             : 
     430       12031 :         return IVAS_ERR_OK;
     431             :     }
     432             : }
     433             : 
     434             : 
     435             : /*-------------------------------------------------------------------------
     436             :  * void ivas_dirac_dec_binaural_render()
     437             :  *
     438             :  *
     439             :  *------------------------------------------------------------------------*/
     440             : 
     441     7689165 : void ivas_dirac_dec_binaural_render(
     442             :     Decoder_Struct *st_ivas,       /* i/o: IVAS decoder handle                      */
     443             :     const uint16_t nSamplesAsked,  /* i  : number of CLDFB slots requested          */
     444             :     uint16_t *nSamplesRendered,    /* o  : number of CLDFB slots rendered           */
     445             :     uint16_t *nSamplesAvailable,   /* o  : number of CLDFB slots still to render    */
     446             :     const int16_t nchan_transport, /* i  : number of transport channels             */
     447             :     float *output_f[]              /* o  : rendered time signal                     */
     448             : )
     449             : {
     450             :     int16_t slots_to_render, first_sf, last_sf, subframe_idx;
     451             :     uint16_t slot_size, ch;
     452             :     uint16_t nchan_out;
     453             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
     454             :     float *output_f_local[MAX_OUTPUT_CHANNELS];
     455             : 
     456     7689165 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
     457     7689165 :     nchan_out = BINAURAL_CHANNELS;
     458             : #ifdef DEBUGGING
     459             :     assert( hSpatParamRendCom );
     460             : #endif
     461    23067495 :     for ( ch = 0; ch < nchan_out; ch++ )
     462             :     {
     463    15378330 :         output_f_local[ch] = output_f[ch];
     464             :     }
     465     7689165 :     slot_size = NS2SA( st_ivas->hDecoderConfig->output_Fs, CLDFB_SLOT_NS );
     466             : 
     467             :     /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */
     468     7689165 :     slots_to_render = min( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered, nSamplesAsked / slot_size );
     469     7689165 :     *nSamplesRendered = slots_to_render * slot_size;
     470     7689165 :     first_sf = hSpatParamRendCom->subframes_rendered;
     471     7689165 :     last_sf = first_sf;
     472             : 
     473    22797643 :     while ( slots_to_render > 0 )
     474             :     {
     475    15108478 :         slots_to_render -= hSpatParamRendCom->subframe_nbslots[last_sf];
     476    15108478 :         last_sf++;
     477             :     }
     478             : 
     479             : #ifdef DEBUGGING
     480             :     assert( slots_to_render == 0 );
     481             : #endif
     482    22797643 :     for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ )
     483             :     {
     484    15108478 :         int16_t n_samples_sf = slot_size * hSpatParamRendCom->subframe_nbslots[subframe_idx];
     485    15108478 :         ivas_dirac_dec_binaural_internal( st_ivas, st_ivas->hCombinedOrientationData, output_f_local, nchan_transport, subframe_idx );
     486             : 
     487    45325434 :         for ( ch = 0; ch < nchan_out; ch++ )
     488             :         {
     489    30216956 :             output_f_local[ch] += n_samples_sf;
     490             :         }
     491             : 
     492             :         /* update combined orientation access index */
     493    15108478 :         ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, n_samples_sf );
     494             :     }
     495             : 
     496     7689165 :     if ( hSpatParamRendCom->slots_rendered == hSpatParamRendCom->num_slots )
     497             :     {
     498     3740468 :         hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + DEFAULT_JBM_SUBFRAMES_5MS ) % hSpatParamRendCom->dirac_md_buffer_length;
     499             :     }
     500             : 
     501     7689165 :     *nSamplesAvailable = ( hSpatParamRendCom->num_slots - hSpatParamRendCom->slots_rendered ) * slot_size;
     502             : 
     503     7689165 :     return;
     504             : }
     505             : 
     506             : 
     507             : /*-------------------------------------------------------------------------
     508             :  * ivas_dirac_dec_binaural_sba_gain()
     509             :  *
     510             :  * loudness correction for parametric binaural renderer
     511             :  *------------------------------------------------------------------------*/
     512             : 
     513     1880991 : void ivas_dirac_dec_binaural_sba_gain(
     514             :     float *output[],              /* i/o: synthesized core-coder transport channels/DirAC output    */
     515             :     const int16_t nchan_remapped, /* i  : num channels after remapping of TCs                       */
     516             :     const int16_t output_frame    /* i  : output frame length                                       */
     517             : )
     518             : {
     519             :     int16_t n;
     520             :     float gain;
     521             : 
     522     1880991 :     if ( nchan_remapped == 1 )
     523             :     {
     524      728207 :         gain = 1.4454f;
     525             :     }
     526             :     else
     527             :     {
     528     1152784 :         gain = 1.3657f;
     529             :     }
     530             : 
     531     4914766 :     for ( n = 0; n < nchan_remapped; n++ )
     532             :     {
     533     3033775 :         v_multc( output[n], gain, output[n], output_frame );
     534             :     }
     535             : 
     536     1880991 :     return;
     537             : }
     538             : 
     539             : 
     540             : /*-------------------------------------------------------------------------
     541             :  * Local functions
     542             :  *------------------------------------------------------------------------*/
     543             : 
     544    15108478 : static void ivas_dirac_dec_binaural_internal(
     545             :     Decoder_Struct *st_ivas,
     546             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
     547             :     float *output_f[],
     548             :     const int16_t nchan_transport,
     549             :     const int16_t subframe )
     550             : {
     551             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
     552             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
     553             :     PARAMBIN_REND_CONFIG config_data;
     554             :     int16_t slot, ch, numInChannels;
     555             :     float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     556             :     float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     557             :     int16_t nchanSeparateChannels;
     558             :     float Rmat[3][3];
     559             :     int16_t max_band_decorr;
     560             :     DIFFUSE_DISTRIBUTION_DATA diffuseDistData;
     561             :     int16_t nBins, offsetSamples;
     562             :     int16_t i, j;
     563             :     int16_t pos_idx;
     564             :     MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
     565             :     float tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     566             :     float tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     567             :     /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */
     568             :     float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     569             :     float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     570             :     float decorrRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     571             :     float decorrIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
     572             :     float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX];
     573             :     float IIReneLimiter[CLDFB_NO_CHANNELS_MAX];
     574             : 
     575    15108478 :     hDiracDecBin = st_ivas->hDiracDecBin[0];
     576    15108478 :     assert( hDiracDecBin );
     577    15108478 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
     578    15108478 :     nBins = hSpatParamRendCom->num_freq_bands;
     579    15108478 :     offsetSamples = hSpatParamRendCom->slots_rendered * nBins;
     580             : 
     581             :     /* Setup internal config */
     582    15108478 :     config_data.separateCenterChannelRendering = st_ivas->hOutSetup.separateChannelEnabled;
     583    15108478 :     config_data.ivas_format = st_ivas->ivas_format;
     584    15108478 :     config_data.mc_mode = st_ivas->mc_mode;
     585    15108478 :     config_data.ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate;
     586    15108478 :     config_data.nchan_transport = st_ivas->nchan_transport;
     587    15108478 :     config_data.qualityBasedSmFactor = st_ivas->hMasa != NULL ? st_ivas->hMasa->data.dir_decode_quality : 1.0f;
     588    15108478 :     config_data.processReverb = st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0;
     589    15108478 :     if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
     590             :     {
     591     2075869 :         config_data.ism_mode = st_ivas->ism_mode;
     592             :     }
     593             :     else
     594             :     {
     595    13032609 :         config_data.ism_mode = ISM_MODE_NONE;
     596             :     }
     597             : 
     598             :     /* The input channel number at this processing function (not nchan_transport) */
     599    15108478 :     numInChannels = BINAURAL_CHANNELS;
     600    15108478 :     if ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) )
     601             :     {
     602     1099437 :         numInChannels++;
     603             :     }
     604    14009041 :     else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
     605             :     {
     606      574125 :         numInChannels += (uint8_t) st_ivas->nchan_ism;
     607             :     }
     608             : 
     609    15108478 :     Rmat[0][0] = 1.0f;
     610    15108478 :     Rmat[0][1] = 0.0f;
     611    15108478 :     Rmat[0][2] = 0.0f;
     612             : 
     613    15108478 :     Rmat[1][0] = 0.0f;
     614    15108478 :     Rmat[1][1] = 1.0f;
     615    15108478 :     Rmat[1][2] = 0.0f;
     616             : 
     617    15108478 :     Rmat[2][0] = 0.0f;
     618    15108478 :     Rmat[2][1] = 0.0f;
     619    15108478 :     Rmat[2][2] = 1.0f;
     620             : 
     621             :     /* CLDFB Analysis of input */
     622    74947523 :     for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
     623             :     {
     624   189322097 :         for ( ch = 0; ch < numInChannels; ch++ )
     625             :         {
     626   129483052 :             if ( ch == 0 || nchan_transport == 2 )
     627             :             {
     628   105108477 :                 cldfbAnalysis_ts(
     629   105108477 :                     &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ),
     630   105108477 :                     Cldfb_RealBuffer_in[ch][slot],
     631   105108477 :                     Cldfb_ImagBuffer_in[ch][slot],
     632             :                     nBins, st_ivas->cldfbAnaDec[ch] );
     633             :             }
     634    24374575 :             else if ( config_data.nchan_transport == 2 ) /* Stereo signal transmitted as mono with DFT stereo */
     635             :             {
     636             :                 /* At mono input duplicate the channel to dual-mono  */
     637     2099683 :                 mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
     638     2099683 :                 mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
     639             :             }
     640             :             else /* when nchan_transport == 1 and ch == 1 */
     641             :             {
     642             :                 /* CNA and HB FD-CNG*/
     643    22274892 :                 if ( st_ivas->hSCE[0]->hCoreCoder[0] != NULL && st_ivas->hSCE[0]->hCoreCoder[0]->cng_sba_flag )
     644    13895144 :                 {
     645             :                     int16_t numCoreBands, b;
     646             : 
     647    13895144 :                     numCoreBands = st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom->numCoreBands;
     648             : 
     649    27790288 :                     generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
     650             :                                                   st_ivas->cldfbAnaDec[1],
     651    13895144 :                                                   &st_ivas->hTcBuffer->tc[nchan_transport][hSpatParamRendCom->num_freq_bands * hSpatParamRendCom->slots_rendered],
     652    13895144 :                                                   Cldfb_RealBuffer_in[2][slot], Cldfb_ImagBuffer_in[2][slot],
     653             :                                                   slot,
     654    13895144 :                                                   st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
     655    13895144 :                                                   ( 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 );
     656             : 
     657    27790288 :                     generate_masking_noise_dirac( st_ivas->hSCE[0]->hCoreCoder[0]->hFdCngDec->hFdCngCom,
     658             :                                                   st_ivas->cldfbAnaDec[1], /*nothing will be analyzed, just get cnst*/
     659             :                                                   NULL,
     660    13895144 :                                                   Cldfb_RealBuffer_in[1][slot], Cldfb_ImagBuffer_in[1][slot],
     661             :                                                   slot,
     662    13895144 :                                                   st_ivas->hSCE[0]->hCoreCoder[0]->cna_dirac_flag && st_ivas->hSCE[0]->hCoreCoder[0]->flag_cna,
     663    13895144 :                                                   ( 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 );
     664             : 
     665             :                     /* LB: Copy first channel + LB-CNG to first and second channels with same scaling (dual-mono)*/
     666   281398484 :                     for ( b = 0; b < numCoreBands; b++ )
     667             :                     {
     668   267503340 :                         Cldfb_RealBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_RealBuffer_in[0][slot][b] + Cldfb_RealBuffer_in[2][slot][b] );
     669   267503340 :                         Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b];
     670   267503340 :                         Cldfb_ImagBuffer_in[0][slot][b] = INV_SQRT2 * ( Cldfb_ImagBuffer_in[0][slot][b] + Cldfb_ImagBuffer_in[2][slot][b] );
     671   267503340 :                         Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b];
     672             :                     }
     673             : 
     674             :                     /* HB: Copy first channel to second channel and add HB-CNGs with different scalings*/
     675   475210084 :                     for ( ; b < nBins; b++ )
     676             :                     {
     677   461314940 :                         Cldfb_RealBuffer_in[0][slot][b] *= INV_SQRT2;
     678   461314940 :                         Cldfb_RealBuffer_in[1][slot][b] = Cldfb_RealBuffer_in[0][slot][b] + 0.5f * Cldfb_RealBuffer_in[1][slot][b] + Cldfb_RealBuffer_in[0][slot][b];
     679   461314940 :                         Cldfb_RealBuffer_in[0][slot][b] += 0.5f * Cldfb_RealBuffer_in[2][slot][b];
     680             : 
     681   461314940 :                         Cldfb_ImagBuffer_in[0][slot][b] *= INV_SQRT2;
     682   461314940 :                         Cldfb_ImagBuffer_in[1][slot][b] = Cldfb_ImagBuffer_in[0][slot][b] + 0.5f * Cldfb_ImagBuffer_in[1][slot][b];
     683   461314940 :                         Cldfb_ImagBuffer_in[0][slot][b] += 0.5f * Cldfb_ImagBuffer_in[2][slot][b];
     684             :                     }
     685             :                 }
     686             :                 else
     687             :                 {
     688             :                     /* At mono input duplicate the channel to dual-mono, and apply gain
     689             :                     correction to ensure same overall level as in stereo mode  */
     690     8379748 :                     v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins );
     691     8379748 :                     v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins );
     692             : 
     693     8379748 :                     mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
     694     8379748 :                     mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
     695             :                 }
     696             :             }
     697             :         }
     698             : 
     699    59839045 :         if ( hDiracDecBin->useTdDecorr )
     700             :         {
     701    60110847 :             for ( ch = BINAURAL_CHANNELS; ch < ( 2 * BINAURAL_CHANNELS ); ch++ )
     702             :             {
     703    40073898 :                 cldfbAnalysis_ts(
     704    40073898 :                     &( st_ivas->hTcBuffer->tc[ch][nBins * slot + offsetSamples] ),
     705    40073898 :                     Cldfb_RealBuffer_in[ch][slot],
     706    40073898 :                     Cldfb_ImagBuffer_in[ch][slot],
     707             :                     nBins, st_ivas->cldfbAnaDec[ch] );
     708    40073898 :                 if ( config_data.nchan_transport == 1 &&
     709    35874532 :                      ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT ) )
     710             :                 {
     711    23302312 :                     v_multc( Cldfb_RealBuffer_in[ch][slot], INV_SQRT_2, Cldfb_RealBuffer_in[ch][slot], nBins );
     712    23302312 :                     v_multc( Cldfb_ImagBuffer_in[ch][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[ch][slot], nBins );
     713             :                 }
     714             :             }
     715             :         }
     716             :     }
     717             : 
     718    15108478 :     if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
     719             :     {
     720     6475076 :         hDiracDecBin->hDiffuseDist = &diffuseDistData;
     721             : 
     722     6475076 :         ivas_spar_param_to_masa_param_mapping( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
     723     6475076 :         ivas_sba_prototype_renderer( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe );
     724             :     }
     725             : 
     726    15108478 :     if ( ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ || ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) ) ) || st_ivas->ivas_format == ISM_FORMAT )
     727             :     {
     728     2165549 :         ivas_omasa_preProcessStereoTransportsForEditedObjects( st_ivas, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, subframe );
     729             :     }
     730             : 
     731    15108478 :     if ( hCombinedOrientationData )
     732             :     {
     733    19578688 :         for ( i = 0; i < 3; i++ )
     734             :         {
     735    58736064 :             for ( j = 0; j < 3; j++ )
     736             :             {
     737    44052048 :                 Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j];
     738             :             }
     739             :         }
     740             : 
     741     4894672 :         if ( nchan_transport == 2 )
     742             :         {
     743             :             /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
     744     3252740 :             adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
     745             : 
     746     3252740 :             ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
     747             :         }
     748             :     }
     749             : 
     750    15108478 :     if ( config_data.ivas_format == ISM_FORMAT )
     751             :     {
     752     1095685 :         max_band_decorr = 0;
     753             :     }
     754    14012793 :     else if ( hDiracDecBin->useTdDecorr )
     755             :     {
     756     5059955 :         max_band_decorr = CLDFB_NO_CHANNELS_MAX;
     757             :     }
     758             :     else
     759             :     {
     760     8952838 :         max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
     761             :     }
     762             : 
     763    15108478 :     ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe,
     764             :                                                                  subFrameTotalEne, IIReneLimiter );
     765             : 
     766    15108478 :     ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe,
     767    15108478 :                                                                   hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData );
     768             : 
     769    15108478 :     nchanSeparateChannels = 0;
     770    15108478 :     if ( config_data.separateCenterChannelRendering || ( st_ivas->ivas_format == MASA_ISM_FORMAT && ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) ) )
     771             :     {
     772     1099437 :         nchanSeparateChannels = 1;
     773             :     }
     774    14009041 :     else if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->ism_mode == ISM_MASA_MODE_DISC && ( st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) )
     775             :     {
     776      574125 :         nchanSeparateChannels = (uint8_t) st_ivas->nchan_ism;
     777             :     }
     778             : 
     779    15108478 :     ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe,
     780    15108478 :                                                            hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0, nchanSeparateChannels, st_ivas->hMasaIsmData );
     781             : 
     782    15108478 :     pMultiBinPoseData = NULL;
     783    15108478 :     if ( st_ivas->hSplitBinRend != NULL )
     784             :     {
     785      765930 :         pMultiBinPoseData = &st_ivas->hSplitBinRend->splitrend.multiBinPoseData;
     786             :     }
     787             : 
     788    15108478 :     if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM )
     789             :     {
     790      765930 :         ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
     791      765930 :                                                 max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
     792             :                                                 reverbRe, reverbIm, decorrRe, decorrIm, 1 );
     793             : 
     794     2297790 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     795             :         {
     796     7577754 :             for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
     797             :             {
     798             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     799     6045894 :                 ivas_CLDFB_RINGBUF_Push( st_ivas->hSplitBinRend->hMultiBinCldfbData[ch], tmp_Cldfb_out_re[ch][i], tmp_Cldfb_out_im[ch][i], CLDFB_NO_CHANNELS_MAX );
     800             : #else
     801             :                 mvr2r( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
     802             :                 mvr2r( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
     803             : #endif
     804             :             }
     805             :         }
     806             :     }
     807             :     else
     808             :     {
     809    14342548 :         ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
     810    14342548 :                                                 max_band_decorr, numInChannels, config_data.processReverb, subframe, NULL, NULL,
     811             :                                                 reverbRe, reverbIm, decorrRe, decorrIm, 1 );
     812             :     }
     813             : 
     814    15108478 :     hDiracDecBin->hDiffuseDist = NULL;
     815             : 
     816    15108478 :     if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
     817             :     {
     818             :         /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
     819             :         IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
     820             :         float Rmat_local[3][3];
     821             : 
     822      543095 :         if ( hCombinedOrientationData )
     823             :         {
     824      543095 :             Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
     825      543095 :             Quaternions_rot.w = -3.0f;                                                                        /* signal to use Euler */
     826      543095 :             Quaternions_abs.w = -3.0f;                                                                        /* signal to use Euler */
     827      543095 :             Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/
     828             : 
     829     2893743 :             for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
     830             :             {
     831     2350648 :                 Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
     832     2350648 :                 Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
     833     2350648 :                 Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
     834             : 
     835     2350648 :                 QuatToRotMat( Quaternions_rot, Rmat_local );
     836             : 
     837     2350648 :                 hDiracDecBin = st_ivas->hDiracDecBin[pos_idx];
     838     2350648 :                 assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
     839     2350648 :                 if ( config_data.ivas_format == SBA_FORMAT || config_data.ivas_format == SBA_ISM_FORMAT )
     840             :                 {
     841      471640 :                     hDiracDecBin->hDiffuseDist = &diffuseDistData;
     842             :                 }
     843             : 
     844             :                 /* re-use input covariance for the side renderings */
     845     7051944 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     846             :                 {
     847     4701296 :                     mvr2r( st_ivas->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands );
     848             :                 }
     849     2350648 :                 mvr2r( st_ivas->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands );
     850     2350648 :                 mvr2r( st_ivas->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands );
     851             : 
     852     2350648 :                 ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
     853             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     854     2350648 :                                                                               hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
     855             : #else
     856             :                                                                               hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
     857             : #endif
     858             :                                                                               subFrameTotalEne, IIReneLimiter, st_ivas->hMasaIsmData );
     859             : 
     860     2350648 :                 ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
     861             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     862     2350648 :                                                                        hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
     863             : #else
     864             :                                                                        hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
     865             : #endif
     866             :                                                                        nchanSeparateChannels, st_ivas->hMasaIsmData );
     867             : 
     868             :                 /* re-use reverb and decorr from main direction for the sides */
     869     2350648 :                 ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, st_ivas->cldfbSynDec, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
     870     2350648 :                                                         max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
     871             :                                                         reverbRe, reverbIm, decorrRe, decorrIm, 0 );
     872             : 
     873             :                 /* copy from temporary buffer to the main split rendering buffer */
     874     7051944 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     875             :                 {
     876    23256680 :                     for ( i = 0; i < hSpatParamRendCom->subframe_nbslots[subframe]; i++ )
     877             :                     {
     878             : #ifdef FIX_1119_SPLIT_RENDERING_VOIP
     879    18555384 :                         ivas_CLDFB_RINGBUF_Push( st_ivas->hSplitBinRend->hMultiBinCldfbData[pos_idx * BINAURAL_CHANNELS + ch], tmp_Cldfb_out_re[ch][i], tmp_Cldfb_out_im[ch][i], CLDFB_NO_CHANNELS_MAX );
     880             : #else
     881             :                         mvr2r( tmp_Cldfb_out_re[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
     882             :                         mvr2r( tmp_Cldfb_out_im[ch][i], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[pos_idx * BINAURAL_CHANNELS + ch][hSpatParamRendCom->slots_rendered + i], CLDFB_NO_CHANNELS_MAX );
     883             : #endif
     884             :                     }
     885             :                 }
     886             : 
     887     2350648 :                 hDiracDecBin->hDiffuseDist = NULL;
     888             :             }
     889             :         }
     890             :     }
     891             : 
     892             :     /* update this counter only after the last rendering of split directions */
     893    15108478 :     hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe];
     894    15108478 :     hSpatParamRendCom->subframes_rendered++;
     895             : 
     896    15108478 :     return;
     897             : }
     898             : 
     899             : 
     900    79563650 : static void ivas_dirac_dec_decorrelate_slot(
     901             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
     902             :     const int16_t num_freq_bands,
     903             :     const int16_t slot,
     904             :     float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
     905             :     float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
     906             :     float decRe[][CLDFB_NO_CHANNELS_MAX],
     907             :     float decIm[][CLDFB_NO_CHANNELS_MAX] )
     908             : {
     909             :     int16_t offset, ch, bin;
     910             :     float onset_filter[BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX];                     /* 2 ch, 60 bins */
     911             :     float decorrelatedFrameInterleaved[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX]; /* 2 ch, real + imag, 60 bins */
     912             :     float protoFrameF[2 * BINAURAL_CHANNELS * CLDFB_NO_CHANNELS_MAX];                  /* 2 ch, real + imag, 60 bins */
     913    79563650 :     const int16_t protoIndexDir[BINAURAL_CHANNELS] = { 0, 1 };
     914             : 
     915             :     /* Decorrelation needs interleaved data. Copy left and right signals to proto_frame_f */
     916   238690950 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     917             :     {
     918   159127300 :         offset = num_freq_bands * BINAURAL_CHANNELS * ch;
     919  7180935460 :         for ( bin = 0; bin < num_freq_bands; bin++ )
     920             :         {
     921  7021808160 :             protoFrameF[( bin * BINAURAL_CHANNELS ) + offset] = inRe[ch][slot][bin];
     922  7021808160 :             protoFrameF[( bin * BINAURAL_CHANNELS ) + offset + 1] = inIm[ch][slot][bin];
     923             :         }
     924             :     }
     925             : 
     926             :     /* Decorrelate proto signal to decorrelatedFrameInterleaved */
     927    79563650 :     ivas_dirac_dec_decorr_process( num_freq_bands,
     928             :                                    BINAURAL_CHANNELS,
     929             :                                    BINAURAL_CHANNELS,
     930             :                                    DIRAC_SYNTHESIS_PSD_LS,
     931             :                                    BINAURAL_CHANNELS,
     932             :                                    protoFrameF,
     933             :                                    BINAURAL_CHANNELS,
     934             :                                    protoIndexDir,
     935             :                                    decorrelatedFrameInterleaved,
     936             :                                    onset_filter,
     937             :                                    hDiracDecBin->h_freq_domain_decorr_ap_params,
     938             :                                    hDiracDecBin->h_freq_domain_decorr_ap_state );
     939             : 
     940             :     /* De-interleave decorrelated signals*/
     941   238690950 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     942             :     {
     943   159127300 :         offset = num_freq_bands * BINAURAL_CHANNELS * ch;
     944  7180935460 :         for ( bin = 0; bin < num_freq_bands; bin++ )
     945             :         {
     946  7021808160 :             decRe[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset];
     947  7021808160 :             decIm[ch][bin] = decorrelatedFrameInterleaved[( bin * BINAURAL_CHANNELS ) + offset + 1];
     948             :         }
     949             :     }
     950             : 
     951    79563650 :     return;
     952             : }
     953             : 
     954             : 
     955    26119202 : static void ivas_dirac_dec_binaural_formulate_input_covariance_matrices(
     956             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
     957             :     const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
     958             :     const PARAMBIN_REND_CONFIG_HANDLE hConfig,
     959             :     float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
     960             :     float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
     961             :     const int16_t subframe,
     962             :     float *subFrameTotalEne,
     963             :     float *IIReneLimiter )
     964             : {
     965             :     int16_t ch, slot, bin;
     966             :     int16_t nBins;
     967             :     float IIReneLimiterFactor;
     968             :     float qualityBasedSmFactor;
     969             :     float lowBitRateEQ[CLDFB_NO_CHANNELS_MAX];
     970             :     uint8_t applyLowBitRateEQ;
     971             :     IVAS_FORMAT ivas_format;
     972             :     int32_t ivas_total_brate;
     973             :     int16_t nchan_transport;
     974             : 
     975    26119202 :     ivas_format = hConfig->ivas_format;
     976    26119202 :     ivas_total_brate = hConfig->ivas_total_brate;
     977    26119202 :     nchan_transport = hConfig->nchan_transport;
     978    26119202 :     qualityBasedSmFactor = hConfig->qualityBasedSmFactor;
     979    26119202 :     qualityBasedSmFactor *= qualityBasedSmFactor;
     980    26119202 :     nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
     981             : 
     982    26119202 :     set_zero( hDiracDecBin->ChCrossRe, nBins );
     983    26119202 :     set_zero( hDiracDecBin->ChCrossIm, nBins );
     984    78357606 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
     985             :     {
     986    52238404 :         set_zero( hDiracDecBin->ChEne[ch], nBins );
     987             :     }
     988             : 
     989             :     /* Determine EQ for low bit rates (13.2 and 16.4 kbps) */
     990    26119202 :     applyLowBitRateEQ = 0;
     991    26119202 :     if ( ( ivas_format == MASA_FORMAT || ivas_format == MC_FORMAT ) && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
     992             :     {
     993      846503 :         applyLowBitRateEQ = 1;
     994      846503 :         if ( ivas_total_brate == IVAS_16k4 )
     995             :         {
     996     7099128 :             for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
     997             :             {
     998     6704732 :                 lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin] * 0.5f + 0.5f;
     999             :             }
    1000             :         }
    1001             :         else
    1002             :         {
    1003     8137926 :             for ( bin = 0; bin < LOW_BIT_RATE_BINAURAL_EQ_BINS; bin++ )
    1004             :             {
    1005     7685819 :                 lowBitRateEQ[bin + LOW_BIT_RATE_BINAURAL_EQ_OFFSET] = lowBitRateBinauralEQ[bin];
    1006             :             }
    1007             :         }
    1008             :     }
    1009             : 
    1010             :     /* Formulate input and target covariance matrices for this subframe */
    1011    26119202 :     set_zero( subFrameTotalEne, CLDFB_NO_CHANNELS_MAX );
    1012             : 
    1013             :     /* Calculate input covariance matrix */
    1014   130001143 :     for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    1015             :     {
    1016  4804547601 :         for ( bin = 0; bin < nBins; bin++ )
    1017             :         {
    1018 14101996980 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1019             :             {
    1020             :                 float instEne;
    1021             : 
    1022  9401331320 :                 instEne = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] );
    1023  9401331320 :                 instEne += ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
    1024  9401331320 :                 hDiracDecBin->ChEne[ch][bin] += instEne;
    1025  9401331320 :                 subFrameTotalEne[bin] += instEne;
    1026             :             }
    1027  4700665660 :             hDiracDecBin->ChCrossRe[bin] += inRe[0][slot][bin] * inRe[1][slot][bin];
    1028  4700665660 :             hDiracDecBin->ChCrossRe[bin] += inIm[0][slot][bin] * inIm[1][slot][bin];
    1029  4700665660 :             hDiracDecBin->ChCrossIm[bin] += inRe[0][slot][bin] * inIm[1][slot][bin];
    1030  4700665660 :             hDiracDecBin->ChCrossIm[bin] -= inIm[0][slot][bin] * inRe[1][slot][bin];
    1031             :         }
    1032             :     }
    1033             : 
    1034             :     /* Apply EQ at low bit rates */
    1035    26119202 :     if ( applyLowBitRateEQ )
    1036             :     {
    1037      846503 :         int16_t lastEqBin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET + LOW_BIT_RATE_BINAURAL_EQ_BINS - 1;
    1038             : 
    1039    14390551 :         for ( bin = LOW_BIT_RATE_BINAURAL_EQ_OFFSET; bin < lastEqBin; bin++ )
    1040             :         {
    1041    13544048 :             subFrameTotalEne[bin] *= lowBitRateEQ[bin];
    1042             :         }
    1043    19358393 :         for ( ; bin < nBins; bin++ )
    1044             :         {
    1045    18511890 :             subFrameTotalEne[bin] *= lowBitRateEQ[lastEqBin];
    1046             :         }
    1047             :     }
    1048             : 
    1049    26119202 :     if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 2 )
    1050             :     {
    1051             :         float tempRe, tempIm;
    1052             :         float subFrameSumEne[CLDFB_NO_CHANNELS_MAX];
    1053             : 
    1054     3545961 :         v_multc( subFrameTotalEne, SBA_CARDI_TARGET_ENERGY_GAIN, subFrameTotalEne, nBins );
    1055             : 
    1056     3545961 :         set_zero( subFrameSumEne, CLDFB_NO_CHANNELS_MAX );
    1057    17710791 :         for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    1058             :         {
    1059   636304230 :             for ( bin = 0; bin < nBins; bin++ )
    1060             :             {
    1061   622139400 :                 tempRe = inRe[0][slot][bin] + inRe[1][slot][bin];
    1062   622139400 :                 tempIm = inIm[0][slot][bin] + inIm[1][slot][bin];
    1063   622139400 :                 subFrameSumEne[bin] += tempRe * tempRe + tempIm * tempIm;
    1064             :             }
    1065             :         }
    1066             : 
    1067   159366021 :         for ( bin = 0; bin < nBins; bin++ )
    1068             :         {
    1069   155820060 :             subFrameTotalEne[bin] = max( subFrameTotalEne[bin], subFrameSumEne[bin] );
    1070             :         }
    1071             :     }
    1072             : 
    1073             :     /* Temporal IIR-type smoothing of covariance matrices. Also apply encoding quality based smoothing factor. */
    1074    26119202 :     if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
    1075             :     {
    1076      725483 :         IIReneLimiterFactor = 16.0f + ( 1.0f - qualityBasedSmFactor );
    1077             :     }
    1078             :     else
    1079             :     {
    1080    25393719 :         IIReneLimiterFactor = 8.0f + ( 1.0f - qualityBasedSmFactor );
    1081             :     }
    1082  1208328262 :     for ( bin = 0; bin < nBins; bin++ )
    1083             :     {
    1084             :         float eneRatio;
    1085             : 
    1086             :         /* Temporally smooth cov mtx estimates for resulting mixing matrix stability. The design principle is that
    1087             :          * the energy history (IIR) must not be more than double of the current frame energy. This provides more
    1088             :          * robust performance at energy offsets when compared to typical IIR averaging. */
    1089  1182209060 :         eneRatio = ( hDiracDecBin->ChEne[0][bin] + hDiracDecBin->ChEne[1][bin] ) / fmaxf( 1e-12f, ( hDiracDecBin->ChEnePrev[0][bin] + hDiracDecBin->ChEnePrev[1][bin] ) );
    1090  1182209060 :         IIReneLimiter[bin] = fminf( 1.0f, eneRatio * IIReneLimiterFactor );
    1091             : 
    1092  1182209060 :         hDiracDecBin->ChCrossRe[bin] *= qualityBasedSmFactor;
    1093  1182209060 :         hDiracDecBin->ChCrossIm[bin] *= qualityBasedSmFactor;
    1094  3546627180 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1095             :         {
    1096  2364418120 :             hDiracDecBin->ChEne[ch][bin] *= qualityBasedSmFactor;
    1097             :         }
    1098             : 
    1099  1182209060 :         hDiracDecBin->ChCrossRe[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossRePrev[bin];
    1100  1182209060 :         hDiracDecBin->ChCrossIm[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossImPrev[bin];
    1101             : 
    1102  3546627180 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1103             :         {
    1104  2364418120 :             hDiracDecBin->ChEne[ch][bin] += IIReneLimiter[bin] * hDiracDecBin->ChEnePrev[ch][bin];
    1105             :         }
    1106             : 
    1107             :         /* Store energy values and coefficients for next round */
    1108  1182209060 :         hDiracDecBin->ChCrossRePrev[bin] = hDiracDecBin->ChCrossRe[bin];
    1109  1182209060 :         hDiracDecBin->ChCrossImPrev[bin] = hDiracDecBin->ChCrossIm[bin];
    1110  3546627180 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1111             :         {
    1112  2364418120 :             hDiracDecBin->ChEnePrev[ch][bin] = hDiracDecBin->ChEne[ch][bin];
    1113             :         }
    1114             :     }
    1115             : 
    1116    26119202 :     return;
    1117             : }
    1118             : 
    1119             : 
    1120    28646234 : static void ivas_dirac_dec_binaural_formulate_target_covariance_matrices(
    1121             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    1122             :     const SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    1123             :     const PARAMBIN_REND_CONFIG_HANDLE hConfig,
    1124             :     float Rmat[3][3],
    1125             :     const int16_t subframe,
    1126             :     const int16_t isHeadtracked,
    1127             :     const float *subFrameTotalEne,
    1128             :     const float *IIReneLimiter,
    1129             :     const MASA_ISM_DATA_HANDLE hMasaIsmData )
    1130             : {
    1131             :     int16_t ch, bin;
    1132             :     int16_t separateCenterChannelRendering;
    1133             :     int16_t nBins, idx;
    1134             :     float frameMeanDiffusenessEneWeight[CLDFB_NO_CHANNELS_MAX];
    1135             :     float qualityBasedSmFactor;
    1136             :     int16_t dirac_read_idx;
    1137             :     PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_GAIN_CACHE_SIZE];
    1138             :     IVAS_FORMAT ivas_format;
    1139             :     MC_MODE mc_mode;
    1140             :     int16_t gainCacheBaseIndex;
    1141             : 
    1142    28646234 :     separateCenterChannelRendering = hConfig->separateCenterChannelRendering;
    1143    28646234 :     ivas_format = hConfig->ivas_format;
    1144    28646234 :     mc_mode = hConfig->mc_mode;
    1145    28646234 :     qualityBasedSmFactor = hConfig->qualityBasedSmFactor;
    1146    28646234 :     qualityBasedSmFactor *= qualityBasedSmFactor;
    1147    28646234 :     nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
    1148             : 
    1149    28646234 :     set_zero( hDiracDecBin->ChCrossReOut, nBins );
    1150    28646234 :     set_zero( hDiracDecBin->ChCrossImOut, nBins );
    1151    85938702 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1152             :     {
    1153    57292468 :         set_zero( hDiracDecBin->ChEneOut[ch], nBins );
    1154             :     }
    1155    28646234 :     set_zero( hDiracDecBin->frameMeanDiffuseness, nBins );
    1156             : 
    1157    28646234 :     set_zero( frameMeanDiffusenessEneWeight, CLDFB_NO_CHANNELS_MAX );
    1158             : 
    1159   315108574 :     for ( idx = 0; idx < MAX_GAIN_CACHE_SIZE; idx++ )
    1160             :     {
    1161   286462340 :         gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
    1162             :     }
    1163             : 
    1164    28646234 :     dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
    1165             : 
    1166             :     /* Determine target covariance matrix containing target binaural properties */
    1167  1362477214 :     for ( bin = 0; bin < nBins; bin++ )
    1168             :     {
    1169  1333830980 :         float diffuseness = 1.0f; /* ratio1 and ratio2 are subtracted from diffuseness further below */
    1170  1333830980 :         float diffusenessValForDecorrelationReduction = 1.0f;
    1171             :         float diffEneValForDecorrelationReduction;
    1172  1333830980 :         float surCoh = 0.0f, spreadCoh = 0.0f; /* Default values if spreadSurroundCoherenceApplied == false */
    1173             :         float diffEne, dirEne, meanEnePerCh;
    1174             :         int16_t dirIndex;
    1175             : 
    1176             :         /* When BINAURAL_ROOM is not indicated, hBinaural->earlyPartEneCorrection[bin] values are all 1.0f.
    1177             :          * When BINAURAL_ROOM is indicated, the binaural audio output is based on combined use of the
    1178             :          * HRTF data set and a BRIR-based data set. The HRTF data set is spectrally corrected to match
    1179             :          * the early spectrum of the BRIR data, using the spectral correction data in
    1180             :          * hBinaural->earlyPartEneCorrection[bin], based on the BRIR set. */
    1181  1333830980 :         meanEnePerCh = hDiracDecBin->earlyPartEneCorrection[bin] * subFrameTotalEne[bin] / 2.0f;
    1182             : 
    1183             :         /* Determine direct part target covariance matrix (for 1 or 2 directions) */
    1184  3160061560 :         for ( dirIndex = 0; dirIndex < hSpatParamRendCom->numSimultaneousDirections; dirIndex++ )
    1185             :         {
    1186             :             int16_t aziDeg, eleDeg;
    1187             :             float lRealp, lImagp, rRealp, rImagp;
    1188             :             float lRealpTmp, lImagpTmp, rRealpTmp, rImagpTmp;
    1189             :             float hrtfEne[BINAURAL_CHANNELS], hrtfCrossRe, hrtfCrossIm, ratio;
    1190  1826230580 :             uint8_t isIsmDirection = 0;
    1191             : 
    1192  1826230580 :             if ( dirIndex == 0 ) /* For first of the two simultaneous directions */
    1193             :             {
    1194  1333830980 :                 aziDeg = hSpatParamRendCom->azimuth[dirac_read_idx][bin];
    1195  1333830980 :                 eleDeg = hSpatParamRendCom->elevation[dirac_read_idx][bin];
    1196  1333830980 :                 ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin];
    1197  1333830980 :                 spreadCoh = hSpatParamRendCom->spreadCoherence[dirac_read_idx][bin];
    1198  1333830980 :                 gainCacheBaseIndex = 0;
    1199             :             }
    1200   492399600 :             else if ( ivas_format != MASA_ISM_FORMAT || ( ivas_format == MASA_ISM_FORMAT && dirIndex < hSpatParamRendCom->numParametricDirections ) ) /* For second of the two simultaneous directions */
    1201             :             {
    1202   373633560 :                 if ( ( ratio = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] ) < 0.001 )
    1203             :                 {
    1204             :                     /* This touches only MASA path where second direction always has smaller ratio and
    1205             :                      * for non-2dir it is zero. As the whole direction contribution is multiplied with
    1206             :                      * the ratio, a very small ratio does not contribute any energy to output. Thus,
    1207             :                      * it is better to save complexity. */
    1208   108116636 :                     continue;
    1209             :                 }
    1210   265516924 :                 aziDeg = hSpatParamRendCom->azimuth2[dirac_read_idx][bin];
    1211   265516924 :                 eleDeg = hSpatParamRendCom->elevation2[dirac_read_idx][bin];
    1212   265516924 :                 spreadCoh = hSpatParamRendCom->spreadCoherence2[dirac_read_idx][bin];
    1213   265516924 :                 gainCacheBaseIndex = 3;
    1214             :             }
    1215             :             else /* For object directions of MASA_ISM_FORMAT */
    1216             :             {
    1217   118766040 :                 isIsmDirection = 1;
    1218             :                 uint16_t ismDirIndex;
    1219   118766040 :                 ismDirIndex = dirIndex - hSpatParamRendCom->numParametricDirections;
    1220   118766040 :                 assert( hMasaIsmData != NULL && "hMasaIsmData should not be NULL if we use it" );
    1221             : 
    1222   118766040 :                 if ( hMasaIsmData->ism_dir_is_edited[ismDirIndex] )
    1223             :                 {
    1224    19975200 :                     aziDeg = hMasaIsmData->azimuth_ism_edited[ismDirIndex];
    1225    19975200 :                     eleDeg = hMasaIsmData->elevation_ism_edited[ismDirIndex];
    1226             :                 }
    1227             :                 else
    1228             :                 {
    1229    98790840 :                     aziDeg = hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx];
    1230    98790840 :                     eleDeg = hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx];
    1231             :                 }
    1232   118766040 :                 ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin];
    1233   118766040 :                 spreadCoh = 0.0f;
    1234   118766040 :                 gainCacheBaseIndex = 6 + ismDirIndex;
    1235             :             }
    1236             : 
    1237  1718113944 :             diffuseness -= ratio; /* diffuseness = 1 - ratio1 - ratio2 */
    1238             : 
    1239  1718113944 :             if ( diffuseness < 0.0f )
    1240             :             {
    1241     4168815 :                 diffuseness = 0.0f;
    1242             :             }
    1243  1718113944 :             if ( isIsmDirection )
    1244             :             {
    1245             :                 /* Objects cause lesser decorrelation reduction, to avoid removing all decorrelation when only objects are present */
    1246   118766040 :                 diffusenessValForDecorrelationReduction -= ratio * 0.5f;
    1247             :             }
    1248             :             else
    1249             :             {
    1250  1599347904 :                 diffusenessValForDecorrelationReduction -= ratio;
    1251             :             }
    1252             : 
    1253  1718113944 :             if ( separateCenterChannelRendering )
    1254             :             {
    1255             :                 /* In masa + mono rendering mode, the center directions originate from phantom sources, so the
    1256             :                  * spread coherence is increased */
    1257             :                 float aziRad, eleRad, doaVectorX, spatialAngleDeg, altSpreadCoh;
    1258             : 
    1259     4119540 :                 aziRad = (float) aziDeg * PI_OVER_180;
    1260     4119540 :                 eleRad = (float) eleDeg * PI_OVER_180;
    1261     4119540 :                 doaVectorX = cosf( aziRad ) * cosf( eleRad );
    1262     4119540 :                 spatialAngleDeg = acosf( doaVectorX ) * _180_OVER_PI;
    1263     4119540 :                 altSpreadCoh = 1.0f - ( spatialAngleDeg / 30.0f );
    1264     4119540 :                 spreadCoh = max( spreadCoh, altSpreadCoh );
    1265             :             }
    1266             : 
    1267  1718113944 :             getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1268             : 
    1269  1718113944 :             if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
    1270             :             {
    1271             :                 /* Synthesizing spread coherence is not needed for stereo loudspeaker output,
    1272             :                  * as directional sound is reproduced with two loudspeakers in any case */
    1273   161143464 :                 spreadCoh = 0.0f;
    1274             :             }
    1275             : 
    1276  1718113944 :             if ( spreadCoh > 0.0f )
    1277             :             {
    1278             :                 float centerMul, sidesMul;
    1279             :                 float hrtfEneCenter, hrtfEneSides, hrtfEneRealized, eneCorrectionFactor;
    1280             :                 float w1, w2, w3, eq;
    1281             : 
    1282   574132297 :                 hrtfEneCenter = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp );
    1283             : 
    1284             :                 /* Spread coherence is synthesized as coherent sources at 30 degree horizontal spacing.
    1285             :                  * The following formulas determine the gains for these sources.
    1286             :                  * spreadCoh = 0: Only panning
    1287             :                  * spreadCoh = 0.5: Three sources coherent panning (e.g. 30 0 -30 deg azi)
    1288             :                  * spreadCoh = 1.0: Two sources coherent panning with gap (as above, but center is silent) */
    1289   574132297 :                 if ( spreadCoh < 0.5f )
    1290             :                 {
    1291             :                     /* 0.0f < spreadCoh < 0.5f */
    1292   505984214 :                     sidesMul = 0.5774f * spreadCoh * 2.0f; /* sqrt(1/3) = 0.5774f */
    1293   505984214 :                     centerMul = 1.0f - ( spreadCoh * 2.0f ) + sidesMul;
    1294             :                 }
    1295             :                 else
    1296             :                 {
    1297             :                     /* 0.5f <= spreadCoh < 1.0f */
    1298    68148083 :                     centerMul = 2.0f - ( 2.0f * spreadCoh );
    1299    68148083 :                     sidesMul = inv_sqrt( centerMul + 2.0f );
    1300    68148083 :                     centerMul *= sidesMul;
    1301             :                 }
    1302             : 
    1303             :                 /* Apply the gain for the center source of the three coherent sources */
    1304   574132297 :                 lRealp *= centerMul;
    1305   574132297 :                 lImagp *= centerMul;
    1306   574132297 :                 rRealp *= centerMul;
    1307   574132297 :                 rImagp *= centerMul;
    1308             : 
    1309             :                 /* Apply the gain for the left source of the three coherent sources */
    1310   574132297 :                 getDirectPartGains( bin, aziDeg + 30, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 1], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1311             : 
    1312   574132297 :                 hrtfEneSides = ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
    1313   574132297 :                 lRealp += sidesMul * lRealpTmp;
    1314   574132297 :                 lImagp += sidesMul * lImagpTmp;
    1315   574132297 :                 rRealp += sidesMul * rRealpTmp;
    1316   574132297 :                 rImagp += sidesMul * rImagpTmp;
    1317             : 
    1318             :                 /* Apply the gain for the right source of the three coherent sources.
    1319             :                  * -30 degrees to 330 wrapping due to internal functions. */
    1320   574132297 :                 getDirectPartGains( bin, aziDeg + 330, eleDeg, &lRealpTmp, &lImagpTmp, &rRealpTmp, &rImagpTmp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[gainCacheBaseIndex + 2], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1321   574132297 :                 hrtfEneSides += ( lRealpTmp * lRealpTmp ) + ( lImagpTmp * lImagpTmp ) + ( rRealpTmp * rRealpTmp ) + ( rImagpTmp * rImagpTmp );
    1322   574132297 :                 lRealp += sidesMul * lRealpTmp;
    1323   574132297 :                 lImagp += sidesMul * lImagpTmp;
    1324   574132297 :                 rRealp += sidesMul * rRealpTmp;
    1325   574132297 :                 rImagp += sidesMul * rImagpTmp;
    1326             : 
    1327             :                 /* Formulate an eneCorrectionFactor that compensates for the coherent summation of the HRTFs */
    1328   574132297 :                 hrtfEneRealized = ( lRealp * lRealp ) + ( lImagp * lImagp ) + ( rRealp * rRealp ) + ( rImagp * rImagp );
    1329  1148264594 :                 eneCorrectionFactor = ( ( hrtfEneSides * sidesMul * sidesMul ) +
    1330   574132297 :                                         ( hrtfEneCenter * centerMul * centerMul ) ) /
    1331   574132297 :                                       max( 1e-12f, hrtfEneRealized );
    1332             : 
    1333             :                 /* Weighting factors to determine appropriate target spectrum for spread coherent sound */
    1334   574132297 :                 if ( spreadCoh < 0.5 )
    1335             :                 {
    1336   505984214 :                     w1 = 1.0f - 2.0f * spreadCoh;
    1337   505984214 :                     w2 = 2.0f * spreadCoh;
    1338   505984214 :                     w3 = 0.0f;
    1339             :                 }
    1340             :                 else
    1341             :                 {
    1342    68148083 :                     w1 = 0.0f;
    1343    68148083 :                     w2 = 2.0f - 2.0f * spreadCoh;
    1344    68148083 :                     w3 = 2.0f * spreadCoh - 1.0f;
    1345             :                 }
    1346             : 
    1347   574132297 :                 if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) )
    1348             :                 {
    1349    36704483 :                     idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
    1350             : 
    1351             :                     /* Apply the target spectrum to the eneCorrectionFactor */
    1352    36704483 :                     if ( separateCenterChannelRendering ) /* spreadCoh mostly originates from phantom sources in separate channel rendering mode */
    1353             :                     {
    1354     2265371 :                         eneCorrectionFactor *= w1 * 1.0f + ( w2 + w3 ) * spreadCohEne1[idx];
    1355             :                     }
    1356             :                     else
    1357             :                     {
    1358    34439112 :                         eneCorrectionFactor *= w1 * 1.0f + w2 * spreadCohEne05[idx] + w3 * spreadCohEne1[idx];
    1359             :                     }
    1360             :                 }
    1361             : 
    1362             :                 /* Equalize the spread coherent combined HRTFs */
    1363   574132297 :                 eq = min( 4.0f, sqrtf( eneCorrectionFactor ) );
    1364   574132297 :                 lRealp *= eq;
    1365   574132297 :                 lImagp *= eq;
    1366   574132297 :                 rRealp *= eq;
    1367   574132297 :                 rImagp *= eq;
    1368             :             }
    1369             : 
    1370  1718113944 :             hrtfEne[0] = ( lRealp * lRealp ) + ( lImagp * lImagp );
    1371  1718113944 :             hrtfEne[1] = ( rRealp * rRealp ) + ( rImagp * rImagp );
    1372  1718113944 :             hrtfCrossRe = ( lRealp * rRealp ) + ( lImagp * rImagp );
    1373  1718113944 :             hrtfCrossIm = ( -lImagp * rRealp ) + ( lRealp * rImagp );
    1374             : 
    1375             :             /* Add direct part (1 or 2) covariance matrix */
    1376  1718113944 :             dirEne = ratio * meanEnePerCh;
    1377  1718113944 :             hDiracDecBin->ChEneOut[0][bin] += dirEne * hrtfEne[0]; /* Dir ene part*/
    1378  1718113944 :             hDiracDecBin->ChEneOut[1][bin] += dirEne * hrtfEne[1];
    1379  1718113944 :             hDiracDecBin->ChCrossReOut[bin] += dirEne * hrtfCrossRe; /* Dir cross re */
    1380  1718113944 :             hDiracDecBin->ChCrossImOut[bin] += dirEne * hrtfCrossIm; /* Dir cross im */
    1381             :         }
    1382             : 
    1383             :         /* Add diffuse / ambient part covariance matrix */
    1384  1333830980 :         diffuseness = max( 0.0f, diffuseness );
    1385  1333830980 :         diffEne = diffuseness * meanEnePerCh;
    1386  1333830980 :         surCoh = hSpatParamRendCom->surroundingCoherence[dirac_read_idx][bin];
    1387             : 
    1388  1333830980 :         diffusenessValForDecorrelationReduction = max( 0.0f, diffusenessValForDecorrelationReduction );
    1389  1333830980 :         diffEneValForDecorrelationReduction = diffusenessValForDecorrelationReduction * meanEnePerCh;
    1390             : 
    1391  1333830980 :         if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) )
    1392             :         {
    1393    66020420 :             if ( !hDiracDecBin->renderStereoOutputInsteadOfBinaural )
    1394             :             {
    1395             :                 float spectrumModVal;
    1396             : 
    1397    66020420 :                 idx = min( bin, MASA_NUM_DEFINED_SUR_SPR_COH_ENE_BINS - 1 );
    1398             :                 /* Apply target spectrum that emphasizes low frequencies when the sound is surround coherent */
    1399    66020420 :                 spectrumModVal = ( 1.0f - surCoh ) + surCoh * surCohEne[idx];
    1400    66020420 :                 diffEne *= spectrumModVal;
    1401             : 
    1402             :                 /* Modify also the value for decorrelation reduction */
    1403    66020420 :                 diffEneValForDecorrelationReduction *= spectrumModVal;
    1404             :             }
    1405             :         }
    1406  1333830980 :         hDiracDecBin->ChEneOut[0][bin] += diffEne; /* Diff ene part*/
    1407  1333830980 :         hDiracDecBin->ChEneOut[1][bin] += diffEne;
    1408             : 
    1409  1333830980 :         if ( hDiracDecBin->renderStereoOutputInsteadOfBinaural )
    1410             :         {
    1411             :             /* When rendering stereo, ambience (except for surround coherent sound) has zero ICC. */
    1412   115754120 :             hDiracDecBin->ChCrossReOut[bin] += surCoh * diffEne;
    1413             :         }
    1414             :         else /* When rendering binaural, ambience has frequency dependent ICC. */
    1415             :         {
    1416  1218076860 :             if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && bin < BINAURAL_COHERENCE_DIFFERENCE_BINS )
    1417    62520444 :             {
    1418             :                 float diffuseFieldCoherence;
    1419    62520444 :                 diffuseFieldCoherence = hDiracDecBin->hDiffuseDist->diffuseRatioX[bin] * hDiracDecBin->diffuseFieldCoherenceX[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioY[bin] * hDiracDecBin->diffuseFieldCoherenceY[bin] + hDiracDecBin->hDiffuseDist->diffuseRatioZ[bin] * hDiracDecBin->diffuseFieldCoherenceZ[bin];
    1420    62520444 :                 hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * diffuseFieldCoherence + surCoh ) * diffEne;
    1421             :             }
    1422             :             else
    1423             :             {
    1424  1155556416 :                 hDiracDecBin->ChCrossReOut[bin] += ( ( 1.0f - surCoh ) * hDiracDecBin->diffuseFieldCoherence[bin] + surCoh ) * diffEne;
    1425             :             }
    1426             :         }
    1427             : 
    1428             :         /* Store parameters for formulating average diffuseness over frame */
    1429  1333830980 :         hDiracDecBin->frameMeanDiffuseness[bin] += diffEneValForDecorrelationReduction;
    1430  1333830980 :         frameMeanDiffusenessEneWeight[bin] += meanEnePerCh;
    1431             :     }
    1432             : 
    1433             :     /* Formulate average diffuseness over frame */
    1434  1362477214 :     for ( bin = 0; bin < nBins; bin++ )
    1435             :     {
    1436  1333830980 :         hDiracDecBin->frameMeanDiffuseness[bin] /= fmaxf( 1e-12f, frameMeanDiffusenessEneWeight[bin] );
    1437             :     }
    1438             : 
    1439  1362477214 :     for ( bin = 0; bin < nBins; bin++ )
    1440             :     {
    1441  1333830980 :         hDiracDecBin->ChCrossReOut[bin] *= qualityBasedSmFactor;
    1442  1333830980 :         hDiracDecBin->ChCrossImOut[bin] *= qualityBasedSmFactor;
    1443             : 
    1444  4001492940 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1445             :         {
    1446  2667661960 :             hDiracDecBin->ChEneOut[ch][bin] *= qualityBasedSmFactor;
    1447             :         }
    1448             : 
    1449  1333830980 :         hDiracDecBin->ChCrossReOut[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossReOutPrev[bin];
    1450  1333830980 :         hDiracDecBin->ChCrossImOut[bin] += IIReneLimiter[bin] * hDiracDecBin->ChCrossImOutPrev[bin];
    1451             : 
    1452  4001492940 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1453             :         {
    1454  2667661960 :             hDiracDecBin->ChEneOut[ch][bin] += IIReneLimiter[bin] * hDiracDecBin->ChEneOutPrev[ch][bin];
    1455             :         }
    1456             : 
    1457             :         /* Store energy values and coefficients for next round */
    1458  1333830980 :         hDiracDecBin->ChCrossReOutPrev[bin] = hDiracDecBin->ChCrossReOut[bin];
    1459  1333830980 :         hDiracDecBin->ChCrossImOutPrev[bin] = hDiracDecBin->ChCrossImOut[bin];
    1460             : 
    1461  4001492940 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    1462             :         {
    1463  2667661960 :             hDiracDecBin->ChEneOutPrev[ch][bin] = hDiracDecBin->ChEneOut[ch][bin];
    1464             :         }
    1465             :     }
    1466             : 
    1467    28646234 :     return;
    1468             : }
    1469             : 
    1470    28646234 : static void ivas_dirac_dec_binaural_determine_processing_matrices(
    1471             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    1472             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    1473             :     PARAMBIN_REND_CONFIG_HANDLE hConfig,
    1474             :     const int16_t max_band_decorr,
    1475             :     float Rmat[3][3],
    1476             :     const int16_t subframe,
    1477             :     const int16_t isHeadtracked,
    1478             :     const int16_t nchanSeparateChannels,
    1479             :     const MASA_ISM_DATA_HANDLE hMasaIsmData )
    1480             : {
    1481             :     int16_t chA, chB, bin;
    1482             :     int16_t separateCenterChannelRendering;
    1483             :     int16_t nBins;
    1484             :     int16_t dirac_read_idx;
    1485             :     PARAMBIN_HRTF_GAIN_CACHE gainCache[MAX_NUM_OBJECTS];
    1486             :     int16_t idx;
    1487             :     ISM_MODE ism_mode;
    1488             :     IVAS_FORMAT ivas_format;
    1489             :     MC_MODE mc_mode;
    1490             :     int32_t ivas_total_brate;
    1491             :     int16_t nchan_transport;
    1492             : 
    1493    28646234 :     ivas_format = hConfig->ivas_format;
    1494    28646234 :     separateCenterChannelRendering = nchanSeparateChannels > 0;
    1495    28646234 :     mc_mode = hConfig->mc_mode;
    1496    28646234 :     ivas_total_brate = hConfig->ivas_total_brate;
    1497    28646234 :     nchan_transport = hConfig->nchan_transport;
    1498    28646234 :     nBins = hSpatParamRendCom->num_freq_bands; /* Actually bins */
    1499             : 
    1500    28646234 :     ism_mode = hConfig->ism_mode;
    1501             : 
    1502    28646234 :     dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
    1503             : 
    1504   143231170 :     for ( idx = 0; idx < MAX_NUM_OBJECTS; idx++ )
    1505             :     {
    1506   114584936 :         gainCache[idx].azi = -1000; /* Use -1000 as value for uninitialized cache. */
    1507             :     }
    1508             : 
    1509  1362477214 :     for ( bin = 0; bin < nBins; bin++ )
    1510             :     {
    1511             :         float tmpMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], resultMtxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS], gain;
    1512             :         float CxRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], CxIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* Input covariance matrix */
    1513             :         float realizedOutputEne, targetOutputEne, missingOutputEne;
    1514             :         float CrEneL, CrEneR; /* Cr = residual decorrelated sound covariance matrix */
    1515             :         float CrCrossRe, CrCrossIm;
    1516             :         float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], MdecIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; /* M = mixing matrix; Mdec = residual decorrelated signal mixing matrix */
    1517  1333830980 :         float prototypeMtx[BINAURAL_CHANNELS][BINAURAL_CHANNELS] = { { 1.0f, 0.05f }, { 0.05f, 1.0f } };                                                                                        /* Prototype matrix determines a reference signal in mixing matrix determination */
    1518             : 
    1519  1333830980 :         CrEneL = 0.0f;
    1520  1333830980 :         CrEneR = 0.0f;
    1521             : 
    1522             :         /* Formulate main processing matrix M */
    1523  1333830980 :         formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin],
    1524             :                                   hDiracDecBin->ChCrossRe[bin], hDiracDecBin->ChCrossIm[bin],
    1525             :                                   hDiracDecBin->ChEneOut[0][bin], hDiracDecBin->ChEneOut[1][bin],
    1526             :                                   hDiracDecBin->ChCrossReOut[bin], hDiracDecBin->ChCrossImOut[bin],
    1527             :                                   prototypeMtx, Mre, Mim, hDiracDecBin->reqularizationFactor );
    1528             : 
    1529             :         /* Load estimated covariance matrix to the [2][2] matrix form */
    1530  1333830980 :         CxRe[0][0] = hDiracDecBin->ChEne[0][bin];
    1531  1333830980 :         CxRe[1][1] = hDiracDecBin->ChEne[1][bin];
    1532  1333830980 :         CxRe[1][0] = hDiracDecBin->ChCrossRe[bin];
    1533  1333830980 :         CxRe[0][1] = hDiracDecBin->ChCrossRe[bin];
    1534  1333830980 :         CxIm[0][0] = 0.0f;
    1535  1333830980 :         CxIm[1][1] = 0.0f;
    1536  1333830980 :         CxIm[1][0] = hDiracDecBin->ChCrossIm[bin];
    1537  1333830980 :         CxIm[0][1] = -hDiracDecBin->ChCrossIm[bin];
    1538             : 
    1539             :         /* Make matrix multiplication M*Cx*M' to determine resulting covariance matrix of processing input with M */
    1540  1333830980 :         matrixMul( Mre, Mim, CxRe, CxIm, tmpMtxRe, tmpMtxIm );
    1541  1333830980 :         matrixTransp2Mul( tmpMtxRe, tmpMtxIm, Mre, Mim, resultMtxRe, resultMtxIm );
    1542             : 
    1543             :         /* When below the frequency limit where decorrelation is applied, we inject the decorrelated
    1544             :          * residual (or missing) signal component. The procedure is active when there are not enough independent
    1545             :          * signal energy to synthesize a signal with the target covariance matrix from the non-decorrelated signals */
    1546  1333830980 :         if ( bin < max_band_decorr )
    1547             :         {
    1548             :             float decorrelationReductionFactor;
    1549             : 
    1550             :             /* Subtract the resulting covariance matrix from the target covariance matrix to determine
    1551             :              * what signal component is missing. The result is the target covariance matrix for the residual signal, i.e.,
    1552             :              * a residual covariance matrix. */
    1553   597411270 :             CrEneL = max( 0.0f, hDiracDecBin->ChEneOut[0][bin] - resultMtxRe[0][0] );
    1554   597411270 :             CrEneR = max( 0.0f, hDiracDecBin->ChEneOut[1][bin] - resultMtxRe[1][1] );
    1555   597411270 :             CrCrossRe = hDiracDecBin->ChCrossReOut[bin] - resultMtxRe[1][0];
    1556   597411270 :             CrCrossIm = hDiracDecBin->ChCrossImOut[bin] - resultMtxIm[1][0];
    1557             : 
    1558             :             /* The amount of the decorrelated sound is further controlled based on the spatial metadata,
    1559             :              * by determining an energy-suppressed residual covariance matrix that is a control parameter
    1560             :              * that guides the processing of the decorrelated sound to a residual signal.
    1561             :              * The procedure improves quality in e.g. double-talk 2-direction rendering situations.*/
    1562   597411270 :             if ( ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE )
    1563             :             {
    1564    56299480 :                 decorrelationReductionFactor = 1.0f;
    1565             :             }
    1566   541111790 :             else if ( ( ivas_format == MC_FORMAT && mc_mode == MC_MODE_MCMASA ) || ( ivas_format == MASA_FORMAT && nchan_transport == 1 ) )
    1567             :             {
    1568   189883955 :                 decorrelationReductionFactor = sqrtf( fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] ) );
    1569             :             }
    1570   351227835 :             else if ( ( ivas_format == SBA_FORMAT || ivas_format == SBA_ISM_FORMAT ) && nchan_transport == 1 )
    1571             :             {
    1572   123147540 :                 decorrelationReductionFactor = 1.0f;
    1573             :             }
    1574             :             else
    1575             :             {
    1576   228080295 :                 decorrelationReductionFactor = fmaxf( 0.0f, hDiracDecBin->frameMeanDiffuseness[bin] );
    1577             :             }
    1578   597411270 :             CrEneL *= decorrelationReductionFactor;
    1579   597411270 :             CrEneR *= decorrelationReductionFactor;
    1580   597411270 :             CrCrossRe *= decorrelationReductionFactor;
    1581   597411270 :             CrCrossIm *= decorrelationReductionFactor;
    1582             : 
    1583             :             /* Determine a residual mixing matrix Mdec for processing the decorrelated signal to obtain
    1584             :              * the residual signal (that has the residual covariance matrix) */
    1585   597411270 :             formulate2x2MixingMatrix( hDiracDecBin->ChEne[0][bin], hDiracDecBin->ChEne[1][bin],
    1586             :                                       0.0f, 0.0f, /* Decorrelated signal has ideally no cross-terms */
    1587             :                                       CrEneL, CrEneR,
    1588             :                                       CrCrossRe, CrCrossIm,
    1589             :                                       prototypeMtx, MdecRe, MdecIm, 0.2f );
    1590             :         }
    1591             :         else
    1592             :         {
    1593  2209259130 :             for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1594             :             {
    1595  1472839420 :                 set_zero( MdecRe[chA], BINAURAL_CHANNELS );
    1596  1472839420 :                 set_zero( MdecIm[chA], BINAURAL_CHANNELS );
    1597             :             }
    1598             :         }
    1599             : 
    1600             :         /* The regularizations at determining mixing matrices cause signal energy to be lost to some degree, which is compensated for here */
    1601  1333830980 :         realizedOutputEne = CrEneL + CrEneR + resultMtxRe[0][0] + resultMtxRe[1][1];
    1602  1333830980 :         targetOutputEne = hDiracDecBin->ChEneOut[0][bin] + hDiracDecBin->ChEneOut[1][bin];
    1603  1333830980 :         missingOutputEne = fmaxf( 0.0f, targetOutputEne - realizedOutputEne );
    1604             : 
    1605  1333830980 :         gain = sqrtf( ( resultMtxRe[0][0] + resultMtxRe[1][1] + missingOutputEne ) /
    1606  1333830980 :                       fmaxf( 1e-12f, resultMtxRe[0][0] + resultMtxRe[1][1] ) );
    1607  1333830980 :         gain = fminf( 4.0f, gain );
    1608             : 
    1609  4001492940 :         for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1610             :         {
    1611  8002985880 :             for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    1612             :             {
    1613  5335323920 :                 Mre[chA][chB] *= gain;
    1614  5335323920 :                 Mim[chA][chB] *= gain;
    1615             :             }
    1616             :         }
    1617             : 
    1618             :         /* Store processing matrices */
    1619  4001492940 :         for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1620             :         {
    1621  8002985880 :             for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    1622             :             {
    1623  5335323920 :                 hDiracDecBin->processMtxRePrev[chA][chB][bin] = hDiracDecBin->processMtxRe[chA][chB][bin];
    1624  5335323920 :                 hDiracDecBin->processMtxImPrev[chA][chB][bin] = hDiracDecBin->processMtxIm[chA][chB][bin];
    1625  5335323920 :                 hDiracDecBin->processMtxDecRePrev[chA][chB][bin] = hDiracDecBin->processMtxDecRe[chA][chB][bin];
    1626  5335323920 :                 hDiracDecBin->processMtxDecImPrev[chA][chB][bin] = hDiracDecBin->processMtxDecIm[chA][chB][bin];
    1627             : 
    1628  5335323920 :                 hDiracDecBin->processMtxRe[chA][chB][bin] = Mre[chA][chB];
    1629  5335323920 :                 hDiracDecBin->processMtxIm[chA][chB][bin] = Mim[chA][chB];
    1630  5335323920 :                 hDiracDecBin->processMtxDecRe[chA][chB][bin] = MdecRe[chA][chB];
    1631  5335323920 :                 hDiracDecBin->processMtxDecIm[chA][chB][bin] = MdecIm[chA][chB];
    1632             :             }
    1633             :         }
    1634             : 
    1635  1333830980 :         if ( separateCenterChannelRendering )
    1636             :         {
    1637             :             /* The rendering of the separate center channel in masa + mono mode.
    1638             :              * The center channel is processed with a gain factor 0.8414f to match the loudness of different processing paths */
    1639             :             float lRealp, lImagp, rRealp, rImagp;
    1640             :             float gainFactor;
    1641    99852780 :             int16_t aziDeg = 0;
    1642    99852780 :             int16_t eleDeg = 0;
    1643    99852780 :             uint8_t instantChange = 0;
    1644             : 
    1645    99852780 :             if ( ivas_format == MASA_ISM_FORMAT )
    1646             :             {
    1647    95733240 :                 gainFactor = OMASA_TDREND_MATCHING_GAIN * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] );
    1648             :             }
    1649             :             else
    1650             :             {
    1651     4119540 :                 gainFactor = 0.8414f * sqrtf( hDiracDecBin->earlyPartEneCorrection[bin] );
    1652             :             }
    1653             : 
    1654   237925560 :             for ( chB = 0; chB < nchanSeparateChannels; chB++ )
    1655             :             {
    1656   138072780 :                 if ( ivas_format == MASA_ISM_FORMAT )
    1657             :                 {
    1658   133953240 :                     if ( ism_mode == ISM_MASA_MODE_DISC )
    1659             :                     {
    1660    63937380 :                         if ( hMasaIsmData->ism_dir_is_edited[chB] )
    1661             :                         {
    1662           0 :                             aziDeg = hMasaIsmData->azimuth_ism_edited[chB];
    1663           0 :                             eleDeg = hMasaIsmData->elevation_ism_edited[chB];
    1664             :                         }
    1665             :                         else
    1666             :                         {
    1667    63937380 :                             aziDeg = hMasaIsmData->azimuth_ism[chB][dirac_read_idx];
    1668    63937380 :                             eleDeg = hMasaIsmData->elevation_ism[chB][dirac_read_idx];
    1669             :                         }
    1670             :                     }
    1671             :                     else
    1672             :                     {
    1673    70015860 :                         if ( ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ && hMasaIsmData->ism_dir_is_edited[hMasaIsmData->idx_separated_ism] )
    1674             :                         {
    1675     5876160 :                             aziDeg = hMasaIsmData->azimuth_ism_edited[hMasaIsmData->idx_separated_ism];
    1676     5876160 :                             eleDeg = hMasaIsmData->elevation_ism_edited[hMasaIsmData->idx_separated_ism];
    1677             :                         }
    1678             :                         else
    1679             :                         {
    1680    64139700 :                             aziDeg = hMasaIsmData->azimuth_separated_ism[dirac_read_idx];
    1681    64139700 :                             eleDeg = hMasaIsmData->elevation_separated_ism[dirac_read_idx];
    1682             :                         }
    1683    70015860 :                         instantChange = 1;
    1684             :                     }
    1685             :                 }
    1686             : 
    1687   414218340 :                 for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1688             :                 {
    1689   276145560 :                     hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin];
    1690   276145560 :                     hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin];
    1691             :                 }
    1692             : 
    1693   138072780 :                 getDirectPartGains( bin, aziDeg, eleDeg, &lRealp, &lImagp, &rRealp, &rImagp, hDiracDecBin->renderStereoOutputInsteadOfBinaural, Rmat, &gainCache[chB], isHeadtracked, *hDiracDecBin->phHrtfParambin );
    1694             : 
    1695   138072780 :                 hDiracDecBin->processMtxRe[0][chB + 2][bin] = lRealp * gainFactor;
    1696   138072780 :                 hDiracDecBin->processMtxIm[0][chB + 2][bin] = lImagp * gainFactor;
    1697   138072780 :                 hDiracDecBin->processMtxRe[1][chB + 2][bin] = rRealp * gainFactor;
    1698   138072780 :                 hDiracDecBin->processMtxIm[1][chB + 2][bin] = rImagp * gainFactor;
    1699             : 
    1700   138072780 :                 if ( instantChange )
    1701             :                 {
    1702   210047580 :                     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1703             :                     {
    1704   140031720 :                         hDiracDecBin->processMtxRePrev[chA][chB + 2][bin] = hDiracDecBin->processMtxRe[chA][chB + 2][bin];
    1705   140031720 :                         hDiracDecBin->processMtxImPrev[chA][chB + 2][bin] = hDiracDecBin->processMtxIm[chA][chB + 2][bin];
    1706             :                     }
    1707             :                 }
    1708             :             }
    1709             :         }
    1710             :     }
    1711             : 
    1712    28646234 :     return;
    1713             : }
    1714             : 
    1715             : 
    1716    28646234 : static void ivas_dirac_dec_binaural_process_output(
    1717             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin,
    1718             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    1719             :     HANDLE_CLDFB_FILTER_BANK cldfbSynDec[MAX_OUTPUT_CHANNELS],
    1720             :     float *output_f[],
    1721             :     float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1722             :     float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1723             :     const int16_t max_band_decorr,
    1724             :     const int16_t numInChannels,
    1725             :     const int16_t processReverb,
    1726             :     const int16_t subframe,
    1727             :     float outRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1728             :     float outIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1729             :     float reverbRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1730             :     float reverbIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1731             :     float decorrRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1732             :     float decorrIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1733             :     const uint8_t recompute )
    1734             : {
    1735             :     int16_t slot, bin, chA, chB;
    1736             :     int16_t nBins;
    1737             :     float outSlotRe[CLDFB_NO_CHANNELS_MAX], outSlotIm[CLDFB_NO_CHANNELS_MAX];
    1738             :     float decSlotRe[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX], decSlotIm[BINAURAL_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    1739             :     float interpVal;
    1740             :     float *decSlotRePointer;
    1741             :     float *decSlotImPointer;
    1742             :     int16_t offsetSamples;
    1743             :     int16_t nSlots;
    1744             : 
    1745    28646234 :     nBins = hSpatParamRendCom->num_freq_bands;
    1746    28646234 :     offsetSamples = 0;
    1747    28646234 :     nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
    1748             : 
    1749    28646234 :     if ( processReverb )
    1750             :     {
    1751             :         /* Process second / room effect part of binaural output when needed */
    1752    12750574 :         if ( recompute == 1 )
    1753             :         {
    1754    12750574 :             ivas_binaural_reverb_processSubframe( hDiracDecBin->hReverb, numInChannels, nSlots, inRe, inIm, reverbRe, reverbIm );
    1755             :         }
    1756             :     }
    1757             : 
    1758    28646234 :     interpVal = 0.0f;
    1759   142511403 :     for ( slot = 0; slot < nSlots; slot++ )
    1760             :     {
    1761   113865169 :         interpVal += 1.0f / (float) nSlots;
    1762   113865169 :         if ( !hDiracDecBin->useTdDecorr && max_band_decorr > 0 )
    1763             :         {
    1764    87731246 :             if ( recompute == 1 )
    1765             :             {
    1766    79563650 :                 ivas_dirac_dec_decorrelate_slot( hDiracDecBin, nBins, slot, inRe, inIm, decSlotRe, decSlotIm );
    1767             : 
    1768   238690950 :                 for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1769             :                 {
    1770   159127300 :                     mvr2r( decSlotRe[chA], decorrRe[chA][slot], CLDFB_NO_CHANNELS_MAX );
    1771   159127300 :                     mvr2r( decSlotIm[chA], decorrIm[chA][slot], CLDFB_NO_CHANNELS_MAX );
    1772             :                 }
    1773             :             }
    1774             :             else
    1775             :             {
    1776    24502788 :                 for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1777             :                 {
    1778    16335192 :                     mvr2r( decorrRe[chA][slot], decSlotRe[chA], CLDFB_NO_CHANNELS_MAX );
    1779    16335192 :                     mvr2r( decorrIm[chA][slot], decSlotIm[chA], CLDFB_NO_CHANNELS_MAX );
    1780             :                 }
    1781             :             }
    1782             :         }
    1783             : 
    1784   341595507 :         for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    1785             :         {
    1786             :             float *outSlotRePr, *outSlotImPr; /* Pointers needed for function call compatibility */
    1787             : 
    1788   227730338 :             set_zero( outSlotRe, CLDFB_NO_CHANNELS_MAX );
    1789   227730338 :             set_zero( outSlotIm, CLDFB_NO_CHANNELS_MAX );
    1790             : 
    1791             :             /* Processing of the first / HRTF part of the binaural output. */
    1792   705225178 :             for ( chB = 0; chB < numInChannels; chB++ )
    1793             :             {
    1794   477494840 :                 if ( chB < BINAURAL_CHANNELS )
    1795             :                 {
    1796             :                     /* Decorrelator signal for TD decorrelation is stored in two input channels above the two normal inputs.
    1797             :                      * It should be noted that TD decorrelation is used only in cases where numInChannels is 2. If this
    1798             :                      * changes, additional adjustments are required. When using CLDFB decorrelator, we simply assign the
    1799             :                      * pointers to buffers. */
    1800   455460676 :                     if ( hDiracDecBin->useTdDecorr )
    1801             :                     {
    1802    87410324 :                         decSlotRePointer = inRe[chB + 2][slot];
    1803    87410324 :                         decSlotImPointer = inIm[chB + 2][slot];
    1804             :                     }
    1805             :                     else
    1806             :                     {
    1807   368050352 :                         decSlotRePointer = decSlotRe[chB];
    1808   368050352 :                         decSlotImPointer = decSlotIm[chB];
    1809             :                     }
    1810             :                 }
    1811             :                 else
    1812             :                 {
    1813    22034164 :                     decSlotRePointer = NULL; /* below these pointers are used only for chB < 2 */
    1814    22034164 :                     decSlotImPointer = NULL;
    1815             :                 }
    1816             : 
    1817             : 
    1818 22757811560 :                 for ( bin = 0; bin < nBins; bin++ )
    1819             :                 {
    1820             :                     float gain;
    1821             : 
    1822             :                     /* Mixing using the formulated processing matrix M */
    1823 22280316720 :                     gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxRePrev[chA][chB][bin] +
    1824 22280316720 :                            interpVal * hDiracDecBin->processMtxRe[chA][chB][bin];
    1825 22280316720 :                     outSlotRe[bin] += gain * inRe[chB][slot][bin];
    1826 22280316720 :                     outSlotIm[bin] += gain * inIm[chB][slot][bin];
    1827             : 
    1828 22280316720 :                     gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxImPrev[chA][chB][bin] +
    1829 22280316720 :                            interpVal * hDiracDecBin->processMtxIm[chA][chB][bin];
    1830 22280316720 :                     outSlotRe[bin] -= gain * inIm[chB][slot][bin];
    1831 22280316720 :                     outSlotIm[bin] += gain * inRe[chB][slot][bin];
    1832             : 
    1833             :                     /* Mixing decorrelated signals using the formulated residual processing matrix Mdec */
    1834 22280316720 :                     if ( bin < max_band_decorr && chB < 2 )
    1835             :                     {
    1836  9481692760 :                         gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecRePrev[chA][chB][bin] +
    1837  9481692760 :                                interpVal * hDiracDecBin->processMtxDecRe[chA][chB][bin];
    1838  9481692760 :                         outSlotRe[bin] += gain * decSlotRePointer[bin];
    1839  9481692760 :                         outSlotIm[bin] += gain * decSlotImPointer[bin];
    1840             : 
    1841  9481692760 :                         gain = ( 1.0f - interpVal ) * hDiracDecBin->processMtxDecImPrev[chA][chB][bin] +
    1842  9481692760 :                                interpVal * hDiracDecBin->processMtxDecIm[chA][chB][bin];
    1843  9481692760 :                         outSlotRe[bin] -= gain * decSlotImPointer[bin];
    1844  9481692760 :                         outSlotIm[bin] += gain * decSlotRePointer[bin];
    1845             :                     }
    1846             :                 }
    1847             :             }
    1848             : 
    1849   227730338 :             if ( processReverb )
    1850             :             {
    1851             :                 /* Combine second (reverb) part with the first (HRTF) part to obtain binaural output signal with room effect */
    1852   101705456 :                 v_add( outSlotRe, reverbRe[chA][slot], outSlotRe, CLDFB_NO_CHANNELS_MAX );
    1853   101705456 :                 v_add( outSlotIm, reverbIm[chA][slot], outSlotIm, CLDFB_NO_CHANNELS_MAX );
    1854             :             }
    1855             : 
    1856   227730338 :             outSlotRePr = &( outSlotRe[0] );
    1857   227730338 :             outSlotImPr = &( outSlotIm[0] );
    1858             : 
    1859   227730338 :             if ( outRe != NULL && outIm != NULL )
    1860             :             {
    1861             :                 /* provide the data outside in CLDFB domain => mainly for split rendering */
    1862    26473662 :                 mvr2r( outSlotRePr, outRe[chA][slot], CLDFB_NO_CHANNELS_MAX );
    1863    26473662 :                 mvr2r( outSlotImPr, outIm[chA][slot], CLDFB_NO_CHANNELS_MAX );
    1864             :             }
    1865   227730338 :             if ( recompute == 1 )
    1866             :             {
    1867             :                 /* Inverse filter bank */
    1868   207763882 :                 cldfbSynthesis( &outSlotRePr, &outSlotImPr, &( output_f[chA][nBins * slot + offsetSamples] ), nBins, cldfbSynDec[chA] );
    1869             :             }
    1870             :         }
    1871             :     }
    1872             : 
    1873    28646234 :     return;
    1874             : }
    1875             : 
    1876             : 
    1877     5732892 : static void adaptTransportSignalsHeadtracked(
    1878             :     COMBINED_ORIENTATION_HANDLE hHeadTrackData,
    1879             :     float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1880             :     float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1881             :     const int16_t nBins,
    1882             :     const int16_t nSlots,
    1883             :     float Rmat[3][3] )
    1884             : {
    1885             :     int16_t slot, ch, bin, louderCh;
    1886             :     float ILD, mono_factor_ILD, mono_factor_rotation, mono_factor, y_val, ene_proc, ene_target;
    1887             :     int16_t max_band;
    1888             :     float eqVal;
    1889             :     int16_t band_idx, bin_lo, bin_hi;
    1890             : 
    1891             :     /* Determine head-orientation-based mono factor.
    1892             :        Rmat[1][1] entry informs how close the ears are aligned according to transport signals. */
    1893     5732892 :     y_val = 1.0f - fabsf( Rmat[1][1] );
    1894     5732892 :     mono_factor_rotation = ( y_val - ADAPT_HTPROTO_ROT_LIM_0 ) / ( ADAPT_HTPROTO_ROT_LIM_1 - ADAPT_HTPROTO_ROT_LIM_0 );
    1895     5732892 :     mono_factor_rotation = fmaxf( 0.0f, fminf( 1.0f, mono_factor_rotation ) );
    1896             : 
    1897             :     /* Adapt transport signals in frequency bands */
    1898             :     /* 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 */
    1899             : 
    1900     5732892 :     max_band = 0;
    1901   137587095 :     while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
    1902             :     {
    1903   131854203 :         max_band++;
    1904             :     }
    1905             : 
    1906   137587095 :     for ( band_idx = 0; band_idx < max_band; band_idx++ )
    1907             :     {
    1908             :         float ch_nrg[2]; /* storage for input signal channel energies */
    1909   131854203 :         bin_lo = MASA_band_grouping_24[band_idx];
    1910   131854203 :         bin_hi = min( MASA_band_grouping_24[band_idx + 1], (int16_t) nBins );
    1911   395562609 :         for ( ch = 0; ch < 2; ch++ )
    1912             :         {
    1913   263708406 :             ch_nrg[ch] = 0.0f;
    1914  1315859742 :             for ( slot = 0; slot < nSlots; slot++ )
    1915             :             {
    1916  3140946576 :                 for ( bin = bin_lo; bin < bin_hi; bin++ )
    1917             :                 {
    1918  2088795240 :                     ch_nrg[ch] += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
    1919             :                 }
    1920             :             }
    1921   263708406 :             hHeadTrackData->chEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
    1922   263708406 :             hHeadTrackData->chEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch];
    1923             :         }
    1924             : 
    1925             :         /* Determine ILD */
    1926   131854203 :         ILD = fabsf( 10.0f * log10f( fmaxf( 1e-12f, hHeadTrackData->chEneIIR[0][band_idx] ) / fmaxf( 1e-12f, hHeadTrackData->chEneIIR[1][band_idx] ) ) );
    1927   131854203 :         if ( hHeadTrackData->chEneIIR[1][band_idx] > hHeadTrackData->chEneIIR[0][band_idx] )
    1928             :         {
    1929    68088174 :             louderCh = 1;
    1930             :         }
    1931             :         else
    1932             :         {
    1933    63766029 :             louderCh = 0;
    1934             :         }
    1935             : 
    1936             :         /* Determine ILD-based mono factor */
    1937   131854203 :         mono_factor_ILD = ( ILD - ADAPT_HTPROTO_ILD_LIM_DB0 ) / ( ADAPT_HTPROTO_ILD_LIM_DB1 - ADAPT_HTPROTO_ILD_LIM_DB0 );
    1938   131854203 :         mono_factor_ILD = fmaxf( 0.0f, fminf( 1.0f, mono_factor_ILD ) );
    1939             : 
    1940             :         /* Combine mono factors */
    1941   131854203 :         mono_factor = mono_factor_ILD * mono_factor_rotation;
    1942             : 
    1943             :         /* Mix original audio and sum signal according to determined mono factor */
    1944   395562609 :         for ( ch = 0; ch < 2; ch++ )
    1945             :         {
    1946   263708406 :             if ( ch != louderCh )
    1947             :             {
    1948   131854203 :                 float band_nrg = 0.0f;
    1949             : 
    1950   657929871 :                 for ( slot = 0; slot < nSlots; slot++ )
    1951             :                 {
    1952  1570473288 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    1953             :                     {
    1954             :                         /* mono sum signal with the computed weight + rest from the original channel */
    1955  1044397620 :                         inRe[ch][slot][bin] = mono_factor * ( inRe[0][slot][bin] + inRe[1][slot][bin] ) + ( 1.0f - mono_factor ) * inRe[ch][slot][bin];
    1956  1044397620 :                         inIm[ch][slot][bin] = mono_factor * ( inIm[0][slot][bin] + inIm[1][slot][bin] ) + ( 1.0f - mono_factor ) * inIm[ch][slot][bin];
    1957  1044397620 :                         band_nrg += ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
    1958             :                     }
    1959             :                 }
    1960   131854203 :                 hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
    1961   131854203 :                 hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * band_nrg;
    1962             :             }
    1963             :             else
    1964             :             {
    1965             :                 /* processed signal is input. use the original channel, so no need to compute new signals or signal energy */
    1966   131854203 :                 hHeadTrackData->procChEneIIR[ch][band_idx] *= ADAPT_HTPROTO_IIR_FAC;
    1967   131854203 :                 hHeadTrackData->procChEneIIR[ch][band_idx] += ( 1.0f - ADAPT_HTPROTO_IIR_FAC ) * ch_nrg[ch];
    1968             :             }
    1969             :         }
    1970             : 
    1971             :         /* Equalize */
    1972   131854203 :         ene_target = hHeadTrackData->chEneIIR[0][band_idx] + hHeadTrackData->chEneIIR[1][band_idx];
    1973   131854203 :         ene_proc = hHeadTrackData->procChEneIIR[0][band_idx] + hHeadTrackData->procChEneIIR[1][band_idx];
    1974   131854203 :         eqVal = fminf( 4.0f, sqrtf( ene_target / fmaxf( 1e-12f, ene_proc ) ) );
    1975             : 
    1976   657929871 :         for ( slot = 0; slot < nSlots; slot++ )
    1977             :         {
    1978  1578227004 :             for ( ch = 0; ch < 2; ch++ )
    1979             :             {
    1980  3140946576 :                 for ( bin = bin_lo; bin < bin_hi; bin++ )
    1981             :                 {
    1982  2088795240 :                     inRe[ch][slot][bin] *= eqVal;
    1983  2088795240 :                     inIm[ch][slot][bin] *= eqVal;
    1984             :                 }
    1985             :             }
    1986             :         }
    1987             :     }
    1988             : 
    1989     5732892 :     return;
    1990             : }
    1991             : 
    1992     5732892 : static void ivas_dirac_dec_binaural_check_and_switch_transports_headtracked(
    1993             :     COMBINED_ORIENTATION_HANDLE hHeadTrackData,
    1994             :     float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1995             :     float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    1996             :     const int16_t nBins,
    1997             :     const int16_t nSlots,
    1998             :     float Rmat[3][3] )
    1999             : {
    2000             :     int16_t slot, bin, ch;
    2001             :     float tmpVal;
    2002             : 
    2003             :     /* When not currently in prototype signal left-right switching procedure, check if such switching is needed */
    2004     5732892 :     if ( hHeadTrackData->lrSwitchedNext == hHeadTrackData->lrSwitchedCurrent )
    2005             :     {
    2006     5007979 :         float thresholdDotProduct = 0.17f; /* Corresponds to 10-degree switching threshold */
    2007     5007979 :         if ( ( hHeadTrackData->lrSwitchedCurrent == 0 ) && ( Rmat[1][1] < -thresholdDotProduct ) )
    2008             :         {
    2009        4046 :             hHeadTrackData->lrSwitchedNext = 1;
    2010             :         }
    2011     5007979 :         if ( ( hHeadTrackData->lrSwitchedCurrent == 1 ) && ( Rmat[1][1] > thresholdDotProduct ) )
    2012             :         {
    2013        3572 :             hHeadTrackData->lrSwitchedNext = 0;
    2014             :         }
    2015             :     }
    2016             : 
    2017             :     /* When currently in interpolation */
    2018     5732892 :     if ( hHeadTrackData->lrSwitchedNext != hHeadTrackData->lrSwitchedCurrent )
    2019             :     {
    2020     3646461 :         for ( slot = 0; slot < nSlots; slot++ )
    2021             :         {
    2022             :             float switchOrderFactor, origOrderFactor;
    2023             : 
    2024     2913930 :             hHeadTrackData->lrSwitchInterpVal += 0.0025f; /* Corresponds to 0.5 seconds interpolation time */
    2025             : 
    2026     2913930 :             if ( hHeadTrackData->lrSwitchInterpVal > 0.999f )
    2027             :             {
    2028             :                 /* Stop interpolation, reset values */
    2029        6948 :                 hHeadTrackData->lrSwitchInterpVal = 0.0f;
    2030        6948 :                 hHeadTrackData->lrSwitchedCurrent = hHeadTrackData->lrSwitchedNext;
    2031             :             }
    2032             : 
    2033             :             /* Gains for determining portion of switched channel order and original channel order */
    2034     2913930 :             tmpVal = (float) hHeadTrackData->lrSwitchedNext * hHeadTrackData->lrSwitchInterpVal;
    2035     2913930 :             tmpVal += (float) hHeadTrackData->lrSwitchedCurrent * ( 1.0f - hHeadTrackData->lrSwitchInterpVal );
    2036     2913930 :             switchOrderFactor = sqrtf( tmpVal );
    2037     2913930 :             origOrderFactor = sqrtf( 1.0f - tmpVal );
    2038             : 
    2039   152533730 :             for ( bin = 0; bin < nBins; bin++ )
    2040             :             {
    2041             :                 /* determine original order (1) signals and switched order (2) signals */
    2042             :                 float re1[BINAURAL_CHANNELS], re2[BINAURAL_CHANNELS], im1[BINAURAL_CHANNELS], im2[BINAURAL_CHANNELS];
    2043             : 
    2044   448859400 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2045             :                 {
    2046   299239600 :                     re1[ch] = inRe[ch][slot][bin] * origOrderFactor;
    2047   299239600 :                     re2[ch] = inRe[1 - ch][slot][bin] * switchOrderFactor;
    2048   299239600 :                     im1[ch] = inIm[ch][slot][bin] * origOrderFactor;
    2049   299239600 :                     im2[ch] = inIm[1 - ch][slot][bin] * switchOrderFactor;
    2050             :                 }
    2051             : 
    2052   448859400 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2053             :                 {
    2054             :                     float eneRef, ene, eq;
    2055             : 
    2056             :                     /* Interpolate / mix original and switched order signals */
    2057   299239600 :                     inRe[ch][slot][bin] = re1[ch] + re2[ch];
    2058   299239600 :                     inIm[ch][slot][bin] = im1[ch] + im2[ch];
    2059             : 
    2060             :                     /* Equalize interpolated signals to preserve energy per bin */
    2061   299239600 :                     eneRef = ( re1[ch] * re1[ch] ) + ( re2[ch] * re2[ch] ) + ( im1[ch] * im1[ch] ) + ( im2[ch] * im2[ch] );
    2062   299239600 :                     ene = ( inRe[ch][slot][bin] * inRe[ch][slot][bin] ) + ( inIm[ch][slot][bin] * inIm[ch][slot][bin] );
    2063   299239600 :                     eq = sqrtf( eneRef / fmaxf( 1e-12f, ene ) );
    2064   299239600 :                     eq = fminf( 4.0f, eq );
    2065   299239600 :                     inRe[ch][slot][bin] *= eq;
    2066   299239600 :                     inIm[ch][slot][bin] *= eq;
    2067             :                 }
    2068             :             }
    2069             :         }
    2070             :     }
    2071             :     else
    2072             :     {
    2073             :         /* If not in interpolation, but in switched prototype situation, then switch left and right channels */
    2074     5000361 :         if ( hHeadTrackData->lrSwitchedCurrent == 1 )
    2075             :         {
    2076     8287331 :             for ( slot = 0; slot < nSlots; slot++ )
    2077             :             {
    2078   294487497 :                 for ( bin = 0; bin < nBins; bin++ )
    2079             :                 {
    2080   287859020 :                     tmpVal = inRe[0][slot][bin];
    2081   287859020 :                     inRe[0][slot][bin] = inRe[1][slot][bin];
    2082   287859020 :                     inRe[1][slot][bin] = tmpVal;
    2083   287859020 :                     tmpVal = inIm[0][slot][bin];
    2084   287859020 :                     inIm[0][slot][bin] = inIm[1][slot][bin];
    2085   287859020 :                     inIm[1][slot][bin] = tmpVal;
    2086             :                 }
    2087             :             }
    2088             :         }
    2089             :     }
    2090             : 
    2091     5732892 :     return;
    2092             : }
    2093             : 
    2094             : 
    2095  3862484500 : static void eig2x2(
    2096             :     const float E1,
    2097             :     const float E2,
    2098             :     const float Cre,
    2099             :     const float Cim,
    2100             :     float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2101             :     float Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2102             :     float D[BINAURAL_CHANNELS] )
    2103             : {
    2104             :     int16_t chA, chB, ch;
    2105             :     float s, normVal, crossSquare, a, pm, add;
    2106             : 
    2107 11587453500 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2108             :     {
    2109 23174907000 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2110             :         {
    2111 15449938000 :             Ure[chA][chB] = 0.0f;
    2112 15449938000 :             Uim[chA][chB] = 0.0f;
    2113             :         }
    2114             :     }
    2115             : 
    2116  3862484500 :     crossSquare = ( Cre * Cre ) + ( Cim * Cim );
    2117  3862484500 :     a = ( E1 + E2 ) * ( E1 + E2 ) - 4.0f * ( ( E1 * E2 ) - crossSquare );
    2118  3862484500 :     pm = 0.5f * sqrtf( max( 0.0f, a ) );
    2119  3862484500 :     add = 0.5f * ( E1 + E2 );
    2120             : 
    2121  3862484500 :     D[0] = add + pm;
    2122  3862484500 :     D[1] = max( 0.0f, add - pm );
    2123             : 
    2124             :     /* Numeric case, when input is practically zeros */
    2125  3862484500 :     if ( D[0] < 1e-12f )
    2126             :     {
    2127   296909585 :         Ure[0][0] = 1.0f;
    2128   296909585 :         Ure[1][1] = 1.0f;
    2129             : 
    2130   296909585 :         return;
    2131             :     }
    2132             : 
    2133             :     /* Numeric case, when input is near an identity matrix with a gain */
    2134  3565574915 :     if ( pm < ( 1e-3f * add ) )
    2135             :     {
    2136   314081744 :         Ure[0][0] = 1.0f;
    2137   314081744 :         Ure[1][1] = 1.0f;
    2138             : 
    2139   314081744 :         return;
    2140             :     }
    2141             : 
    2142             :     /* Eigenvectors */
    2143  9754479513 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2144             :     {
    2145  6502986342 :         if ( fabsf( E2 - D[ch] ) > fabsf( E1 - D[ch] ) )
    2146             :         {
    2147  2792577804 :             s = D[ch] - E2;
    2148  2792577804 :             normVal = sqrtf( 1.0f / ( 1e-12f + crossSquare + s * s ) );
    2149             : 
    2150  2792577804 :             Ure[0][ch] = s * normVal;
    2151  2792577804 :             Ure[1][ch] = Cre * normVal;
    2152  2792577804 :             Uim[1][ch] = Cim * normVal;
    2153             :         }
    2154             :         else
    2155             :         {
    2156  3710408538 :             s = D[ch] - E1;
    2157  3710408538 :             normVal = sqrtf( 1.0f / ( 1e-12f + crossSquare + s * s ) );
    2158             : 
    2159  3710408538 :             Ure[1][ch] = s * normVal;
    2160  3710408538 :             Ure[0][ch] = Cre * normVal;
    2161  3710408538 :             Uim[0][ch] = -Cim * normVal;
    2162             :         }
    2163             :     }
    2164             : 
    2165  3251493171 :     return;
    2166             : }
    2167             : 
    2168             : 
    2169  1931242250 : static void matrixDiagMul(
    2170             :     float reIn[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2171             :     float imIn[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2172             :     const float D[BINAURAL_CHANNELS],
    2173             :     float reOut[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2174             :     float imOut[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
    2175             : {
    2176             :     int16_t chA, chB;
    2177             : 
    2178  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2179             :     {
    2180 11587453500 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2181             :         {
    2182  7724969000 :             reOut[chA][chB] = reIn[chA][chB] * D[chB];
    2183  7724969000 :             imOut[chA][chB] = imIn[chA][chB] * D[chB];
    2184             :         }
    2185             :     }
    2186             : 
    2187  1931242250 :     return;
    2188             : }
    2189             : 
    2190             : 
    2191  7127557730 : static void matrixMul(
    2192             :     float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2193             :     float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2194             :     float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2195             :     float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2196             :     float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2197             :     float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
    2198             : {
    2199             :     int16_t chA, chB;
    2200             : 
    2201 21382673190 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2202             :     {
    2203 42765346380 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2204             :         {
    2205 28510230920 :             outRe[chA][chB] = Are[chA][0] * Bre[0][chB] + Are[chA][1] * Bre[1][chB];
    2206 28510230920 :             outRe[chA][chB] -= Aim[chA][0] * Bim[0][chB] + Aim[chA][1] * Bim[1][chB];
    2207 28510230920 :             outIm[chA][chB] = Aim[chA][0] * Bre[0][chB] + Aim[chA][1] * Bre[1][chB];
    2208 28510230920 :             outIm[chA][chB] += Are[chA][0] * Bim[0][chB] + Are[chA][1] * Bim[1][chB];
    2209             :         }
    2210             :     }
    2211             : 
    2212  7127557730 :     return;
    2213             : }
    2214             : 
    2215             : 
    2216  1931242250 : static void matrixTransp1Mul(
    2217             :     float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2218             :     float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2219             :     float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2220             :     float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2221             :     float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2222             :     float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
    2223             : {
    2224             :     int16_t chA, chB;
    2225             : 
    2226  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2227             :     {
    2228 11587453500 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2229             :         {
    2230  7724969000 :             outRe[chA][chB] = Are[0][chA] * Bre[0][chB] + Are[1][chA] * Bre[1][chB];
    2231  7724969000 :             outRe[chA][chB] -= -Aim[0][chA] * Bim[0][chB] - Aim[1][chA] * Bim[1][chB];
    2232  7724969000 :             outIm[chA][chB] = -Aim[0][chA] * Bre[0][chB] - Aim[1][chA] * Bre[1][chB];
    2233  7724969000 :             outIm[chA][chB] += Are[0][chA] * Bim[0][chB] + Are[1][chA] * Bim[1][chB];
    2234             :         }
    2235             :     }
    2236             : 
    2237  1931242250 :     return;
    2238             : }
    2239             : 
    2240             : 
    2241  5196315480 : static void matrixTransp2Mul(
    2242             :     float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2243             :     float Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2244             :     float Bre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2245             :     float Bim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2246             :     float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2247             :     float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
    2248             : {
    2249             :     int16_t chA, chB;
    2250             : 
    2251 15588946440 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2252             :     {
    2253 31177892880 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2254             :         {
    2255 20785261920 :             outRe[chA][chB] = Are[chA][0] * Bre[chB][0] + Are[chA][1] * Bre[chB][1];
    2256 20785261920 :             outRe[chA][chB] -= Aim[chA][0] * ( -Bim[chB][0] ) + Aim[chA][1] * ( -Bim[chB][1] );
    2257 20785261920 :             outIm[chA][chB] = Aim[chA][0] * Bre[chB][0] + Aim[chA][1] * Bre[chB][1];
    2258 20785261920 :             outIm[chA][chB] += Are[chA][0] * ( -Bim[chB][0] ) + Are[chA][1] * ( -Bim[chB][1] );
    2259             :         }
    2260             :     }
    2261             : 
    2262  5196315480 :     return;
    2263             : }
    2264             : 
    2265             : 
    2266  1931242250 : static void chol2x2(
    2267             :     const float E1,
    2268             :     const float E2,
    2269             :     const float Cre,
    2270             :     const float Cim,
    2271             :     float outRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2272             :     float outIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS] )
    2273             : {
    2274             :     int16_t chA, chB;
    2275             :     float sqrtVal;
    2276             : 
    2277  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2278             :     {
    2279 11587453500 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2280             :         {
    2281  7724969000 :             outRe[chA][chB] = 0.0f;
    2282  7724969000 :             outIm[chA][chB] = 0.0f;
    2283             :         }
    2284             :     }
    2285             : 
    2286  1931242250 :     if ( E1 > E2 ) /* Perform Cholesky decomposition according to louder channel first */
    2287             :     {
    2288   896756103 :         outRe[0][0] = sqrtf( E1 );
    2289   896756103 :         outRe[1][0] = Cre / ( 1e-12f + outRe[0][0] );
    2290   896756103 :         outIm[1][0] = Cim / ( 1e-12f + outRe[0][0] );
    2291   896756103 :         sqrtVal = E2 - ( Cre * Cre + Cim * Cim ) / ( 1e-12f + E1 );
    2292   896756103 :         outRe[1][1] = sqrtf( max( 0.0f, sqrtVal ) );
    2293             :     }
    2294             :     else
    2295             :     {
    2296  1034486147 :         outRe[1][1] = sqrtf( E2 );
    2297  1034486147 :         outRe[0][1] = Cre / ( 1e-12f + outRe[1][1] );
    2298  1034486147 :         outIm[0][1] = -Cim / ( 1e-12f + outRe[1][1] );
    2299  1034486147 :         sqrtVal = E1 - ( Cre * Cre + Cim * Cim ) / ( 1e-12f + E2 );
    2300  1034486147 :         outRe[0][0] = sqrtf( max( 0.0f, sqrtVal ) );
    2301             :     }
    2302             : 
    2303  1931242250 :     return;
    2304             : }
    2305             : 
    2306             : 
    2307  1931242250 : static void formulate2x2MixingMatrix(
    2308             :     float Ein1,
    2309             :     float Ein2,
    2310             :     float CinRe,
    2311             :     float CinIm,
    2312             :     float Eout1,
    2313             :     float Eout2,
    2314             :     float CoutRe,
    2315             :     float CoutIm,
    2316             :     float Q[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2317             :     float Mre[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2318             :     float Mim[BINAURAL_CHANNELS][BINAURAL_CHANNELS],
    2319             :     const float regularizationFactor )
    2320             : {
    2321             :     /*
    2322             :      This function implements a 2x2 solution for an optimized spatial audio rendering algorithm
    2323             :      Vilkamo, J., Bäckström, T. and Kuntz, A., 2013.
    2324             :      "Optimized covariance domain framework for time–frequency processing of spatial audio."
    2325             :      Journal of the Audio Engineering Society, 61(6), pp.403-411.
    2326             : 
    2327             :      The result of the formulas below are the same as those in the publication, however, some
    2328             :      derivation details differ for as simple as possible 2x2 formulattion
    2329             :      */
    2330             :     int16_t chA, chB;
    2331             :     float maxEne, maxEneDiv;
    2332             :     float KyRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], KyIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2333             :     float Uxre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uxim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2334             :     float Sx[BINAURAL_CHANNELS], Kxre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Kxim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2335             :     float tmpRe[BINAURAL_CHANNELS][BINAURAL_CHANNELS], tmpIm[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2336             :     float Are[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Aim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2337             :     float Ure[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Uim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2338             :     float D[BINAURAL_CHANNELS];
    2339             :     float div[BINAURAL_CHANNELS];
    2340             :     float Ghat[BINAURAL_CHANNELS];
    2341             :     float GhatQ[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2342             :     float Pre[BINAURAL_CHANNELS][BINAURAL_CHANNELS], Pim[BINAURAL_CHANNELS][BINAURAL_CHANNELS];
    2343             : 
    2344             :     /* Normalize energy values */
    2345  1931242250 :     maxEne = Ein1;
    2346  1931242250 :     maxEne = max( maxEne, Ein2 );
    2347  1931242250 :     maxEne = max( maxEne, Eout1 );
    2348  1931242250 :     maxEne = max( maxEne, Eout2 );
    2349  1931242250 :     maxEneDiv = 1.0f / ( maxEne + 1e-12f );
    2350  1931242250 :     Ein1 *= maxEneDiv;
    2351  1931242250 :     Ein2 *= maxEneDiv;
    2352  1931242250 :     CinRe *= maxEneDiv;
    2353  1931242250 :     CinIm *= maxEneDiv;
    2354  1931242250 :     Eout1 *= maxEneDiv;
    2355  1931242250 :     Eout2 *= maxEneDiv;
    2356  1931242250 :     CoutRe *= maxEneDiv;
    2357  1931242250 :     CoutIm *= maxEneDiv;
    2358             : 
    2359             :     /* Cholesky decomposition of target / output covariance matrix */
    2360  1931242250 :     chol2x2( Eout1, Eout2, CoutRe, CoutIm, KyRe, KyIm );
    2361             : 
    2362             :     /* Eigendecomposition of input covariance matrix */
    2363  1931242250 :     eig2x2( Ein1, Ein2, CinRe, CinIm, Uxre, Uxim, Sx );
    2364             : 
    2365             :     /* Eigendecomposition to Kx -- Ux Sx Ux' -> Kx Kx'*/
    2366  1931242250 :     Sx[0] = sqrtf( Sx[0] );
    2367  1931242250 :     Sx[1] = sqrtf( Sx[1] );
    2368  1931242250 :     matrixDiagMul( Uxre, Uxim, Sx, Kxre, Kxim );
    2369             : 
    2370             :     /* Regularize the diagonal Sx for matrix inversion */
    2371  1931242250 :     Sx[0] = max( Sx[0], regularizationFactor * Sx[1] );
    2372  1931242250 :     Sx[1] = max( Sx[1], regularizationFactor * Sx[0] );
    2373             : 
    2374             :     /* This is equivalent to the prototype signal energy normalization in the publication */
    2375  1931242250 :     Ghat[0] = sqrtf( Eout1 / ( 1e-12f + max( Ein1, 0.001f * Ein2 ) ) );
    2376  1931242250 :     Ghat[1] = sqrtf( Eout2 / ( 1e-12f + max( Ein2, 0.001f * Ein1 ) ) );
    2377             : 
    2378             :     /* Matrix multiplication, tmp = Ky' * G_hat * Q */
    2379  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2380             :     {
    2381  3862484500 :         GhatQ[chA][0] = Q[chA][0] * Ghat[chA];
    2382  3862484500 :         GhatQ[chA][1] = Q[chA][1] * Ghat[chA];
    2383             :     }
    2384  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2385             :     {
    2386 11587453500 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2387             :         {
    2388  7724969000 :             tmpRe[chA][chB] = KyRe[0][chA] * GhatQ[0][chB] + KyRe[1][chA] * GhatQ[1][chB];
    2389  7724969000 :             tmpIm[chA][chB] = -KyIm[0][chA] * GhatQ[0][chB] - KyIm[1][chA] * GhatQ[1][chB];
    2390             :         }
    2391             :     }
    2392             : 
    2393             :     /* A = Ky' * G_hat * Q * Kx (see publication) */
    2394  1931242250 :     matrixMul( tmpRe, tmpIm, Kxre, Kxim, Are, Aim );
    2395             : 
    2396             :     /* Find nearest orthonormal matrix P to A = Ky' * G_hat * Q * Kx
    2397             :       For matrix A that is P = A(A'A)^0.5
    2398             :     */
    2399  1931242250 :     matrixTransp1Mul( Are, Aim, Are, Aim, tmpRe, tmpIm );
    2400             : 
    2401  1931242250 :     eig2x2( tmpRe[0][0], tmpRe[1][1], tmpRe[1][0], tmpIm[1][0], Ure, Uim, D );
    2402             : 
    2403  1931242250 :     div[0] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[0] ) ) );
    2404  1931242250 :     div[1] = min( 10000.0f, sqrtf( 1.0f / ( 1e-12f + D[1] ) ) );
    2405             : 
    2406  1931242250 :     matrixMul( Are, Aim, Ure, Uim, tmpRe, tmpIm );
    2407             : 
    2408  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2409             :     {
    2410 11587453500 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2411             :         {
    2412  7724969000 :             tmpRe[chA][chB] *= div[chB];
    2413  7724969000 :             tmpIm[chA][chB] *= div[chB];
    2414             :         }
    2415             :     }
    2416             : 
    2417  1931242250 :     matrixTransp2Mul( tmpRe, tmpIm, Ure, Uim, Pre, Pim ); /* Nearest orthonormal matrix P to matrix A formulated */
    2418             : 
    2419             :     /* These are the final formulas of the JAES publication M = Ky P Kx^(-1) */
    2420  5793726750 :     for ( chA = 0; chA < BINAURAL_CHANNELS; chA++ )
    2421             :     {
    2422 11587453500 :         for ( chB = 0; chB < BINAURAL_CHANNELS; chB++ )
    2423             :         {
    2424  7724969000 :             Pre[chA][chB] /= Sx[chB] + 1e-12f;
    2425  7724969000 :             Pim[chA][chB] /= Sx[chB] + 1e-12f;
    2426             :         }
    2427             :     }
    2428             : 
    2429  1931242250 :     matrixMul( KyRe, KyIm, Pre, Pim, tmpRe, tmpIm );
    2430             : 
    2431  1931242250 :     matrixTransp2Mul( tmpRe, tmpIm, Uxre, Uxim, Mre, Mim );
    2432             : 
    2433  1931242250 :     return;
    2434             : }
    2435             : 
    2436             : 
    2437  3004451318 : static void getDirectPartGains(
    2438             :     const int16_t bin,
    2439             :     int16_t aziDeg,
    2440             :     int16_t eleDeg,
    2441             :     float *lRealp,
    2442             :     float *lImagp,
    2443             :     float *rRealp,
    2444             :     float *rImagp,
    2445             :     const uint8_t renderStereoOutputInsteadOfBinaural,
    2446             :     float Rmat[3][3],
    2447             :     PARAMBIN_HRTF_GAIN_CACHE *gainCache,
    2448             :     const int16_t isHeadtracked,
    2449             :     HRTFS_PARAMBIN_HANDLE hHrtfParambin )
    2450             : {
    2451             :     float aziRad, eleRad;
    2452             :     float y, mappedX, aziRadMapped, A, A2, A3;
    2453  3004451318 :     const float LsAngleRad = 30.0f * PI_OVER_180;
    2454             : 
    2455  3004451318 :     if ( renderStereoOutputInsteadOfBinaural ) /* In stereo (i.e. non-binaural) rendering mode */
    2456             :     {
    2457   201129264 :         *lImagp = 0.0f;
    2458   201129264 :         *rImagp = 0.0f;
    2459   201129264 :         if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
    2460             :         {
    2461   147243429 :             *lRealp = gainCache->shVec[0]; /* Reused memory */
    2462   147243429 :             *rRealp = gainCache->shVec[1]; /* Reused memory */
    2463             :         }
    2464             :         else
    2465             :         {
    2466             :             /* Convert azi and ele to an azi value of the cone of confusion */
    2467    53885835 :             aziRad = (float) aziDeg * PI_OVER_180;
    2468    53885835 :             eleRad = (float) eleDeg * PI_OVER_180;
    2469    53885835 :             y = ( sinf( aziRad ) * cosf( eleRad ) );
    2470    53885835 :             mappedX = sqrtf( max( 0.0f, 1.0f - ( y * y ) ) );
    2471    53885835 :             aziRadMapped = atan2f( y, mappedX );
    2472             : 
    2473             :             /* Determine the real valued amplitude panning gains */
    2474    53885835 :             if ( aziRadMapped >= LsAngleRad )
    2475             :             { /* Left side */
    2476    20012130 :                 *lRealp = 1.0f;
    2477    20012130 :                 *rRealp = 0.0f;
    2478             :             }
    2479    33873705 :             else if ( aziRadMapped <= -LsAngleRad )
    2480             :             { /* Right side */
    2481    21423358 :                 *lRealp = 0.0f;
    2482    21423358 :                 *rRealp = 1.0f;
    2483             :             }
    2484             :             else /* Tangent panning law */
    2485             :             {
    2486    12450347 :                 A = tanf( aziRadMapped ) / tanf( LsAngleRad );
    2487    12450347 :                 A2 = ( A - 1.0f ) / max( 0.001f, A + 1.0f );
    2488    12450347 :                 A3 = 1.0f / ( A2 * A2 + 1.0f );
    2489    12450347 :                 *lRealp = sqrtf( A3 );
    2490    12450347 :                 *rRealp = sqrtf( 1.0f - A3 );
    2491             :             }
    2492             :             /* Scaling to have the same expected gain as for the HRTF rendering */
    2493    53885835 :             *lRealp *= SQRT2;
    2494    53885835 :             *rRealp *= SQRT2;
    2495             : 
    2496             :             /* Store to gain cache */
    2497    53885835 :             gainCache->azi = aziDeg;
    2498    53885835 :             gainCache->ele = eleDeg;
    2499    53885835 :             gainCache->shVec[0] = *lRealp; /* Reuse memory */
    2500    53885835 :             gainCache->shVec[1] = *rRealp; /* Reuse memory */
    2501             :         }
    2502             :     }
    2503             :     else /* In regular binaural rendering mode */
    2504             :     {
    2505  2803322054 :         if ( aziDeg == gainCache->azi && eleDeg == gainCache->ele )
    2506             :         {
    2507  1746812505 :             hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, TRUE, hHrtfParambin );
    2508             :         }
    2509             :         else
    2510             :         {
    2511  1056509549 :             gainCache->azi = aziDeg;
    2512  1056509549 :             gainCache->ele = eleDeg;
    2513  1056509549 :             if ( isHeadtracked )
    2514             :             {
    2515   404146928 :                 rotateAziEle( (float) aziDeg, (float) eleDeg, &aziDeg, &eleDeg, Rmat, 0 );
    2516             :             }
    2517  1056509549 :             hrtfShGetHrtf( bin, aziDeg, eleDeg, lRealp, lImagp, rRealp, rImagp, gainCache, FALSE, hHrtfParambin );
    2518             :         }
    2519             :     }
    2520             : 
    2521  3004451318 :     return;
    2522             : }
    2523             : 
    2524             : 
    2525  2803322054 : static void hrtfShGetHrtf(
    2526             :     const int16_t bin,
    2527             :     const int16_t aziDeg,
    2528             :     const int16_t eleDeg,
    2529             :     float *lRealp,
    2530             :     float *lImagp,
    2531             :     float *rRealp,
    2532             :     float *rImagp,
    2533             :     PARAMBIN_HRTF_GAIN_CACHE *gainCache,
    2534             :     const int16_t useCachedValue,
    2535             :     HRTFS_PARAMBIN_HANDLE hHrtfParambin )
    2536             : {
    2537             :     int16_t k;
    2538             :     float( *hrtfShCoeffsReInt )[16][60];
    2539             :     float( *hrtfShCoeffsImInt )[16][60];
    2540  2803322054 :     hrtfShCoeffsReInt = hHrtfParambin->hrtfShCoeffsRe;
    2541  2803322054 :     hrtfShCoeffsImInt = hHrtfParambin->hrtfShCoeffsIm;
    2542             : 
    2543  2803322054 :     *lRealp = 0.0f;
    2544  2803322054 :     *lImagp = 0.0f;
    2545  2803322054 :     *rRealp = 0.0f;
    2546  2803322054 :     *rImagp = 0.0f;
    2547             : 
    2548  2803322054 :     if ( useCachedValue )
    2549             :     {
    2550             :         float *shVec;
    2551  1746812505 :         shVec = gainCache->shVec;
    2552             : 
    2553 29695812585 :         for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
    2554             :         {
    2555 27949000080 :             *lRealp += hrtfShCoeffsReInt[0][k][bin] * shVec[k];
    2556 27949000080 :             *lImagp += hrtfShCoeffsImInt[0][k][bin] * shVec[k];
    2557 27949000080 :             *rRealp += hrtfShCoeffsReInt[1][k][bin] * shVec[k];
    2558 27949000080 :             *rImagp += hrtfShCoeffsImInt[1][k][bin] * shVec[k];
    2559             :         }
    2560             :     }
    2561             :     else
    2562             :     {
    2563             :         float shVec[HRTF_SH_CHANNELS];
    2564             : 
    2565  1056509549 :         ivas_dirac_dec_get_response( aziDeg,
    2566             :                                      eleDeg,
    2567             :                                      shVec,
    2568             :                                      HRTF_SH_ORDER );
    2569             : 
    2570 17960662333 :         for ( k = 0; k < HRTF_SH_CHANNELS; k++ )
    2571             :         {
    2572 16904152784 :             *lRealp += hrtfShCoeffsReInt[0][k][bin] * shVec[k];
    2573 16904152784 :             *lImagp += hrtfShCoeffsImInt[0][k][bin] * shVec[k];
    2574 16904152784 :             *rRealp += hrtfShCoeffsReInt[1][k][bin] * shVec[k];
    2575 16904152784 :             *rImagp += hrtfShCoeffsImInt[1][k][bin] * shVec[k];
    2576             : 
    2577 16904152784 :             gainCache->shVec[k] = shVec[k];
    2578             :         }
    2579             :     }
    2580             : 
    2581  2803322054 :     return;
    2582             : }
    2583             : 
    2584             : 
    2585             : /*-------------------------------------------------------------------------
    2586             :  * configure_reqularization_factor()
    2587             :  *
    2588             :  * Configure regularization factor for the mixing matrix generation of the
    2589             :  * parametric binauralizer using IVAS codec format and current bitrate.
    2590             :  *------------------------------------------------------------------------*/
    2591             : 
    2592             : /*! r: Configured reqularization factor value */
    2593      282350 : float configure_reqularization_factor(
    2594             :     const IVAS_FORMAT ivas_format, /* i  : IVAS format          */
    2595             :     const int32_t ivas_total_brate /* i  : IVAS total bitrate  */
    2596             : )
    2597             : {
    2598             :     float reqularizationFactor;
    2599      282350 :     reqularizationFactor = 1.0f; /* Default value */
    2600             : 
    2601      282350 :     if ( ivas_format == MASA_FORMAT )
    2602             :     {
    2603      108700 :         if ( ivas_total_brate >= IVAS_160k )
    2604             :         {
    2605        6985 :             reqularizationFactor = 0.4f;
    2606             :         }
    2607      101715 :         else if ( ivas_total_brate == IVAS_128k )
    2608             :         {
    2609        3655 :             reqularizationFactor = 0.5f;
    2610             :         }
    2611       98060 :         else if ( ivas_total_brate == IVAS_96k )
    2612             :         {
    2613        2712 :             reqularizationFactor = 0.6f;
    2614             :         }
    2615       95348 :         else if ( ivas_total_brate >= IVAS_64k )
    2616             :         {
    2617        5189 :             reqularizationFactor = 0.8f;
    2618             :         }
    2619             :         else
    2620             :         {
    2621       90159 :             reqularizationFactor = 1.0f;
    2622             :         }
    2623             :     }
    2624             : 
    2625      282350 :     if ( ivas_format == MC_FORMAT ) /* This is always McMASA for parametric binauralizer. */
    2626             :     {
    2627       18880 :         if ( ivas_total_brate >= IVAS_96k )
    2628             :         {
    2629        1079 :             reqularizationFactor = 0.4f;
    2630             :         }
    2631       17801 :         else if ( ivas_total_brate >= IVAS_80k )
    2632             :         {
    2633        1054 :             reqularizationFactor = 0.5f;
    2634             :         }
    2635       16747 :         else if ( ivas_total_brate >= IVAS_64k )
    2636             :         {
    2637        1150 :             reqularizationFactor = 0.7f;
    2638             :         }
    2639       15597 :         else if ( ivas_total_brate >= IVAS_48k )
    2640             :         {
    2641        2427 :             reqularizationFactor = 0.8f;
    2642             :         }
    2643             :         else
    2644             :         {
    2645       13170 :             reqularizationFactor = 1.0f;
    2646             :         }
    2647             :     }
    2648             : 
    2649             :     /* For SBA and parametric ISM, currently in default value of 1.0f. */
    2650             : 
    2651      282350 :     return reqularizationFactor;
    2652             : }
    2653             : 
    2654             : 
    2655             : /*-------------------------------------------------------------------*
    2656             :  * ivas_omasa_preProcessStereoTransportsForEditedObjects()
    2657             :  *
    2658             :  *
    2659             :  *-------------------------------------------------------------------*/
    2660             : 
    2661     2543563 : void ivas_omasa_preProcessStereoTransportsForEditedObjects(
    2662             :     Decoder_Struct *st_ivas,
    2663             :     float inRe[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2664             :     float inIm[][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX],
    2665             :     const int16_t nBins,
    2666             :     const int16_t subframe )
    2667             : {
    2668             :     int16_t bin, ch, inCh, outCh, ismDirIndex, slot, band_idx, bin_lo, bin_hi, max_band, n_ism;
    2669             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    2670             :     MASA_ISM_DATA_HANDLE hMasaIsmData;
    2671             :     PARAM_ISM_DEC_HANDLE hParamIsmDec;
    2672             :     uint8_t enableCentering;
    2673             :     int16_t dirac_read_idx;
    2674             :     int16_t nSlots;
    2675             :     float panGainsOut[4][2];
    2676             :     float panGainsIn[4][2];
    2677             :     float panEnesOut[4][2];
    2678             :     float panEnesIn[4][2];
    2679             :     uint8_t ismGainEdited[4];
    2680             :     uint8_t ismDirEdited[4];
    2681             :     uint8_t masaGainEdited;
    2682             :     uint8_t masaIsmMode;
    2683             : 
    2684     2543563 :     hSpatParamRendCom = st_ivas->hSpatParamRendCom;
    2685     2543563 :     hMasaIsmData = st_ivas->hMasaIsmData;
    2686     2543563 :     hParamIsmDec = st_ivas->hParamIsmDec;
    2687             : 
    2688     2543563 :     if ( st_ivas->ivas_format == MASA_ISM_FORMAT )
    2689             :     {
    2690     1447878 :         masaIsmMode = 1u;
    2691             :     }
    2692             :     else
    2693             :     {
    2694     1095685 :         masaIsmMode = 0u;
    2695             :     }
    2696             : 
    2697     2543563 :     if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_HOA3 )
    2698             :     {
    2699      160604 :         enableCentering = 0;
    2700             :     }
    2701             :     else
    2702             :     {
    2703     2382959 :         enableCentering = 1;
    2704             :     }
    2705             : 
    2706     2543563 :     if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC || st_ivas->ivas_format == ISM_FORMAT )
    2707             :     {
    2708     1669810 :         n_ism = st_ivas->nchan_ism;
    2709             :     }
    2710             :     else
    2711             :     {
    2712      873753 :         n_ism = hSpatParamRendCom->numIsmDirections;
    2713             :     }
    2714             : 
    2715    10950355 :     for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    2716             :     {
    2717     8406792 :         ismGainEdited[ismDirIndex] = hMasaIsmData->ism_gain_is_edited[ismDirIndex];
    2718     8406792 :         ismDirEdited[ismDirIndex] = hMasaIsmData->ism_dir_is_edited[ismDirIndex];
    2719             :     }
    2720     2543563 :     masaGainEdited = hMasaIsmData->masa_gain_is_edited;
    2721             : 
    2722             :     /* Bypass processing until first object is moved or gained */
    2723     2543563 :     if ( hMasaIsmData->objectsEdited == 0 )
    2724             :     {
    2725     9173856 :         for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    2726             :         {
    2727     6995510 :             if ( ismDirEdited[ismDirIndex] )
    2728             :             {
    2729       12798 :                 hMasaIsmData->objectsEdited = 1;
    2730             :             }
    2731             : 
    2732     6995510 :             if ( ismGainEdited[ismDirIndex] )
    2733             :             {
    2734       12139 :                 hMasaIsmData->objectsEdited = 1;
    2735             :             }
    2736             :         }
    2737             : 
    2738     2178346 :         if ( masaGainEdited )
    2739             :         {
    2740          14 :             hMasaIsmData->objectsEdited = 1;
    2741             :         }
    2742             : 
    2743     2178346 :         if ( hMasaIsmData->objectsEdited == 0 )
    2744             :         {
    2745             :             /* No objects have moved so far */
    2746     2175133 :             return;
    2747             :         }
    2748             :     }
    2749             : 
    2750             :     /* OMASA gaining for discrete OMASA mode with stereo_param/bin_room_param renderer */
    2751      368430 :     if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) && st_ivas->ism_mode == ISM_MASA_MODE_DISC )
    2752             :     {
    2753             :         /* ISM gaining */
    2754           0 :         for ( ch = 0; ch < n_ism; ch++ )
    2755             :         {
    2756           0 :             if ( st_ivas->hMasaIsmData->ism_gain_is_edited[ch] )
    2757             :             {
    2758           0 :                 for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    2759             :                 {
    2760             :                     float gain;
    2761           0 :                     gain = st_ivas->hMasaIsmData->gain_ism_edited[ch];
    2762           0 :                     v_multc( inRe[ch + 2][slot], gain, inRe[ch + 2][slot], nBins );
    2763           0 :                     v_multc( inIm[ch + 2][slot], gain, inIm[ch + 2][slot], nBins );
    2764             :                 }
    2765             :             }
    2766             :         }
    2767             : 
    2768             :         /* MASA gaining */
    2769           0 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2770             :         {
    2771           0 :             if ( masaGainEdited )
    2772             :             {
    2773           0 :                 for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    2774             :                 {
    2775             :                     float gain_masa;
    2776           0 :                     gain_masa = st_ivas->hMasaIsmData->gain_masa_edited;
    2777           0 :                     v_multc( inRe[ch][slot], gain_masa, inRe[ch][slot], nBins );
    2778           0 :                     v_multc( inIm[ch][slot], gain_masa, inIm[ch][slot], nBins );
    2779             :                 }
    2780             :             }
    2781             :         }
    2782             :     }
    2783      368430 :     else if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->hISMDTX.dtx_flag ) /* If dtx on, perform just the smoothing of the processing gains */
    2784           0 :     {
    2785             :         float totalTargetEne;
    2786             :         float ismPreprocMtxNew[2][2];
    2787             :         float ismPreprocMtxIncrement[2][2];
    2788             :         float nSlotDiv;
    2789             :         float outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    2790             :         float outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    2791             :         float eqVal;
    2792             : 
    2793           0 :         nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
    2794           0 :         nSlotDiv = 1.0f / ( (float) nSlots );
    2795             : 
    2796             :         /* Use diagonal mixing matrix as the instant mixing matrix, to slowly fade away the editing during dtx */
    2797           0 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2798             :         {
    2799           0 :             ismPreprocMtxNew[ch][ch] = 1.0f;
    2800           0 :             ismPreprocMtxNew[1 - ch][ch] = 0.0f;
    2801             :         }
    2802             : 
    2803             :         /* Determine the highest band */
    2804           0 :         max_band = 0;
    2805           0 :         while ( max_band < MAX_PARAM_ISM_NBANDS && hParamIsmDec->hParamIsm->band_grouping[max_band] < nBins )
    2806             :         {
    2807           0 :             max_band++;
    2808             :         }
    2809             : 
    2810             :         /* Init out array */
    2811           0 :         for ( slot = 0; slot < nSlots; slot++ )
    2812             :         {
    2813           0 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2814             :             {
    2815           0 :                 set_zero( outSlotRe[ch][slot], CLDFB_NO_CHANNELS_MAX );
    2816           0 :                 set_zero( outSlotIm[ch][slot], CLDFB_NO_CHANNELS_MAX );
    2817             :             }
    2818             :         }
    2819             : 
    2820             :         /* Perform the processing in frequency bands */
    2821           0 :         for ( band_idx = 0; band_idx < max_band; band_idx++ )
    2822             :         {
    2823           0 :             bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
    2824           0 :             bin_hi = min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins );
    2825             : 
    2826             :             /* Determine transport energies */
    2827           0 :             totalTargetEne = 0.0f;
    2828           0 :             for ( slot = 0; slot < nSlots; slot++ )
    2829             :             {
    2830           0 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2831             :                 {
    2832           0 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    2833             :                     {
    2834           0 :                         totalTargetEne += inRe[ch][slot][bin] * inRe[ch][slot][bin];
    2835           0 :                         totalTargetEne += inIm[ch][slot][bin] * inIm[ch][slot][bin];
    2836             :                     }
    2837             :                 }
    2838             :             }
    2839             : 
    2840             :             /* Get increment value for temporal interpolation */
    2841           0 :             for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
    2842             :             {
    2843           0 :                 for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
    2844             :                 {
    2845           0 :                     ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] ) * nSlotDiv;
    2846             :                 }
    2847             :             }
    2848             : 
    2849             :             /* Mix signals */
    2850           0 :             hMasaIsmData->preprocEneTarget[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    2851           0 :             hMasaIsmData->preprocEneRealized[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    2852           0 :             hMasaIsmData->preprocEneTarget[band_idx] += totalTargetEne;
    2853             : 
    2854           0 :             for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
    2855             :             {
    2856           0 :                 for ( slot = 0; slot < nSlots; slot++ )
    2857             :                 {
    2858           0 :                     for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
    2859             :                     {
    2860           0 :                         hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] += ismPreprocMtxIncrement[outCh][inCh];
    2861           0 :                         for ( bin = bin_lo; bin < bin_hi; bin++ )
    2862             :                         {
    2863           0 :                             outSlotRe[outCh][slot][bin] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
    2864           0 :                             outSlotIm[outCh][slot][bin] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
    2865             :                         }
    2866             :                     }
    2867             : 
    2868           0 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    2869             :                     {
    2870           0 :                         hMasaIsmData->preprocEneRealized[band_idx] += ( outSlotRe[outCh][slot][bin] * outSlotRe[outCh][slot][bin] ) + ( outSlotIm[outCh][slot][bin] * outSlotIm[outCh][slot][bin] );
    2871             :                     }
    2872             :                 }
    2873             :             }
    2874             : 
    2875           0 :             eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[band_idx] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[band_idx] ) ) );
    2876             : 
    2877           0 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2878             :             {
    2879           0 :                 for ( slot = 0; slot < nSlots; slot++ )
    2880             :                 {
    2881           0 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    2882             :                     {
    2883           0 :                         inRe[ch][slot][bin] = outSlotRe[ch][slot][bin] * eqVal;
    2884           0 :                         inIm[ch][slot][bin] = outSlotIm[ch][slot][bin] * eqVal;
    2885             :                     }
    2886             :                 }
    2887             :             }
    2888             :         }
    2889             :     }
    2890             :     else /* Other processing modes */
    2891             :     {
    2892             :         float subframeEne;
    2893             :         float subframeEneCh[2];
    2894             :         float normEnes[2];
    2895             :         float ratioAccOrig;
    2896             :         float ratioAccNew;
    2897             :         float ratio;
    2898             :         float ismEneThis;
    2899             :         float ismTargetEneThis;
    2900             :         float ismTargetEneThisCh[2];
    2901             :         float totalTargetEneCh[2];
    2902             :         float totalTargetEne;
    2903             :         float masaTargetEneThisCh[2];
    2904             :         float ismPreprocMtxNew[2][2];
    2905             :         float ismPreprocMtxIncrement[2][2];
    2906             :         float eneMove[2];
    2907             :         float enePreserve[2];
    2908             :         float ismRatioAcc;
    2909             :         float remainderNormEne;
    2910             :         float centeringFactor;
    2911             :         float eneMoveThis;
    2912             :         float enePreserveThis;
    2913             :         float normVal;
    2914             :         float eqVal;
    2915             :         float outSlotRe[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    2916             :         float outSlotIm[2][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    2917             :         float newRatios[6];
    2918             :         float gainIsmThis;
    2919             :         float gainMasaPow2;
    2920             :         float nSlotDiv;
    2921             :         float tempDivisor;
    2922             :         float masaEneThisCh[2];
    2923             :         float ratioAccNewDivisor;
    2924             : 
    2925      368430 :         gainMasaPow2 = 1.0f;
    2926      368430 :         if ( masaGainEdited )
    2927             :         {
    2928       97968 :             gainMasaPow2 = hMasaIsmData->gain_masa_edited;
    2929       97968 :             gainMasaPow2 *= gainMasaPow2;
    2930             :         }
    2931             : 
    2932      368430 :         nSlots = hSpatParamRendCom->subframe_nbslots[subframe];
    2933      368430 :         dirac_read_idx = hSpatParamRendCom->render_to_md_map[subframe];
    2934      368430 :         nSlotDiv = 1.0f / ( (float) nSlots );
    2935             : 
    2936             :         /* Determine panning gains and energies for each object */
    2937     1792550 :         for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    2938             :         {
    2939             :             /* Get input and output panning gains */
    2940     1424120 :             ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism[ismDirIndex][dirac_read_idx],
    2941     1424120 :                                            hMasaIsmData->elevation_ism[ismDirIndex][dirac_read_idx],
    2942     1424120 :                                            panGainsIn[ismDirIndex] );
    2943             : 
    2944     1424120 :             if ( ismDirEdited[ismDirIndex] )
    2945             :             {
    2946     1409471 :                 ivas_get_stereo_panning_gains( hMasaIsmData->azimuth_ism_edited[ismDirIndex],
    2947     1409471 :                                                hMasaIsmData->elevation_ism_edited[ismDirIndex],
    2948     1409471 :                                                panGainsOut[ismDirIndex] );
    2949             :             }
    2950             :             else
    2951             :             {
    2952             :                 /* When not edited, input and output pan gains are the same */
    2953       43947 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2954             :                 {
    2955       29298 :                     panGainsOut[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch];
    2956             :                 }
    2957             :             }
    2958             : 
    2959             :             /* Determine pan enes */
    2960     4272360 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2961             :             {
    2962     2848240 :                 panEnesOut[ismDirIndex][ch] = panGainsOut[ismDirIndex][ch] * panGainsOut[ismDirIndex][ch];
    2963     2848240 :                 panEnesIn[ismDirIndex][ch] = panGainsIn[ismDirIndex][ch] * panGainsIn[ismDirIndex][ch];
    2964             :             }
    2965             :         }
    2966             : 
    2967             :         /* Determine the highest band */
    2968      368430 :         max_band = 0;
    2969      368430 :         if ( masaIsmMode )
    2970             :         {
    2971     2480000 :             while ( max_band < MASA_FREQUENCY_BANDS && MASA_band_grouping_24[max_band] < nBins )
    2972             :             {
    2973     2380800 :                 max_band++;
    2974             :             }
    2975             :         }
    2976             :         else
    2977             :         {
    2978     3230760 :             while ( max_band < MAX_PARAM_ISM_NBANDS && hParamIsmDec->hParamIsm->band_grouping[max_band] < nBins )
    2979             :             {
    2980     2961530 :                 max_band++;
    2981             :             }
    2982             :         }
    2983             : 
    2984             :         /* Init out array */
    2985     1786924 :         for ( slot = 0; slot < nSlots; slot++ )
    2986             :         {
    2987     4255482 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    2988             :             {
    2989     2836988 :                 set_zero( outSlotRe[ch][slot], CLDFB_NO_CHANNELS_MAX );
    2990     2836988 :                 set_zero( outSlotIm[ch][slot], CLDFB_NO_CHANNELS_MAX );
    2991             :             }
    2992             :         }
    2993             : 
    2994             :         /* Perform the processing in frequency bands */
    2995     5710760 :         for ( band_idx = 0; band_idx < max_band; band_idx++ )
    2996             :         {
    2997     5342330 :             ratioAccOrig = 0.0f;
    2998     5342330 :             ratioAccNew = 0.0f;
    2999     5342330 :             ismRatioAcc = 0.0f;
    3000             : 
    3001     5342330 :             set_zero( subframeEneCh, 2 );
    3002     5342330 :             set_zero( ismPreprocMtxNew[0], 2 );
    3003     5342330 :             set_zero( ismPreprocMtxNew[1], 2 );
    3004     5342330 :             set_zero( eneMove, 2 );
    3005     5342330 :             set_zero( enePreserve, 2 );
    3006     5342330 :             if ( masaIsmMode )
    3007             :             {
    3008     2380800 :                 bin_lo = MASA_band_grouping_24[band_idx];
    3009     2380800 :                 bin_hi = min( MASA_band_grouping_24[band_idx + 1], nBins );
    3010             :             }
    3011             :             else
    3012             :             {
    3013     2961530 :                 bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
    3014     2961530 :                 bin_hi = min( hParamIsmDec->hParamIsm->band_grouping[band_idx + 1], nBins );
    3015             :             }
    3016             : 
    3017             :             /* Determine transport normalized energies and subframe energy */
    3018    26104164 :             for ( slot = 0; slot < nSlots; slot++ )
    3019             :             {
    3020    62285502 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3021             :                 {
    3022   211742948 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    3023             :                     {
    3024   170219280 :                         subframeEneCh[ch] += inRe[ch][slot][bin] * inRe[ch][slot][bin];
    3025   170219280 :                         subframeEneCh[ch] += inIm[ch][slot][bin] * inIm[ch][slot][bin];
    3026             :                     }
    3027             :                 }
    3028             :             }
    3029     5342330 :             subframeEne = subframeEneCh[0] + subframeEneCh[1];
    3030     5342330 :             totalTargetEneCh[0] = subframeEneCh[0];
    3031     5342330 :             totalTargetEneCh[1] = subframeEneCh[1];
    3032     5342330 :             masaEneThisCh[0] = subframeEneCh[0];
    3033     5342330 :             masaEneThisCh[1] = subframeEneCh[1];
    3034             : 
    3035             :             /* Gain editing */
    3036             :             /* For each object, estimate new target energy per channel based on the applied gain */
    3037    25521250 :             for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    3038             :             {
    3039    20178920 :                 ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo];
    3040    20178920 :                 ratioAccOrig += ratio;
    3041             : 
    3042             :                 /* Calculate MASA energy as a residual of original channel energies subtracted with ISM energies */
    3043    60536760 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3044             :                 {
    3045    40357840 :                     masaEneThisCh[ch] -= panEnesIn[ismDirIndex][ch] * ratio * subframeEne;
    3046             :                 }
    3047             : 
    3048             :                 /* Calculate target energy, gained ratio for accumulation, and transports gains, if ism gain is edited */
    3049    20178920 :                 if ( ismGainEdited[ismDirIndex] )
    3050             :                 {
    3051    18646565 :                     gainIsmThis = hMasaIsmData->gain_ism_edited[ismDirIndex];
    3052             :                     /* ISM original energy */
    3053    18646565 :                     ismEneThis = ratio * subframeEne;
    3054             : 
    3055             :                     /* ISM target energy */
    3056    18646565 :                     ismTargetEneThis = ( gainIsmThis * gainIsmThis ) * ismEneThis;
    3057             : 
    3058    18646565 :                     ratio *= gainIsmThis * gainIsmThis;
    3059             : 
    3060             :                     /* Determine panning energies and channel target energies */
    3061    55939695 :                     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3062             :                     {
    3063    37293130 :                         ismTargetEneThisCh[ch] = panEnesIn[ismDirIndex][ch] * ismTargetEneThis; /* Ism target energy per channel */
    3064    37293130 :                         totalTargetEneCh[ch] -= panEnesIn[ismDirIndex][ch] * ismEneThis;        /* Reduce original ism energy */
    3065    37293130 :                         totalTargetEneCh[ch] += ismTargetEneThisCh[ch];                         /* Add ism target energy per channel */
    3066             :                     }
    3067             : 
    3068             :                     /* If separated ism edited, apply gain directly to the separated ism */
    3069    18646565 :                     if ( ismDirIndex == hMasaIsmData->idx_separated_ism )
    3070             :                     {
    3071             :                         /* Separated object gaining is done elsewhere with DIRAC renderer */
    3072     2129376 :                         if ( st_ivas->renderer_type != RENDERER_DIRAC )
    3073             :                         {
    3074             :                             /* Gain transport channel of separated ism */
    3075    10646880 :                             for ( slot = 0; slot < nSlots; slot++ )
    3076             :                             {
    3077    29811264 :                                 for ( bin = bin_lo; bin < bin_hi; bin++ )
    3078             :                                 {
    3079    21293760 :                                     inRe[2][slot][bin] = gainIsmThis * inRe[2][slot][bin];
    3080    21293760 :                                     inIm[2][slot][bin] = gainIsmThis * inIm[2][slot][bin];
    3081             :                                 }
    3082             :                             }
    3083             :                         }
    3084             :                     }
    3085             :                 }
    3086    20178920 :                 ratioAccNew += ratio;
    3087             :             }
    3088             : 
    3089     5342330 :             if ( masaIsmMode )
    3090             :             {
    3091             :                 /* MASA original ratios */
    3092     2380800 :                 ratio = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin_lo] + hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin_lo];
    3093     2380800 :                 ratioAccOrig += ratio;
    3094             : 
    3095             :                 /* Estimate MASA original energies and determine adjusted target energies and gained ratio for accumulation, if a gain is applied to MASA */
    3096     2380800 :                 if ( masaGainEdited )
    3097             :                 {
    3098             :                     /* Gained MASA ratio */
    3099     2351232 :                     ratio *= gainMasaPow2;
    3100             : 
    3101             :                     /* Calculate MASA target energies and add to total target energy estimation */
    3102     7053696 :                     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3103             :                     {
    3104     4702464 :                         masaEneThisCh[ch] = fmaxf( masaEneThisCh[ch], 0.0f );       /* MASA original energy per channel */
    3105     4702464 :                         masaTargetEneThisCh[ch] = gainMasaPow2 * masaEneThisCh[ch]; /* MASA target energy per channel */
    3106     4702464 :                         totalTargetEneCh[ch] -= masaEneThisCh[ch];                  /* Reduce original energy per channel */
    3107     4702464 :                         totalTargetEneCh[ch] += masaTargetEneThisCh[ch];            /* Add target energy per channel */
    3108             :                     }
    3109             :                 }
    3110             : 
    3111     2380800 :                 ratioAccNew += ratio;
    3112             :             }
    3113             : 
    3114             :             /* Limit target energies to non-negative values */
    3115             : #ifdef NONBE_1399_1400_FIX_OBJ_EDIT_ISSUES
    3116    16026990 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3117             :             {
    3118    10684660 :                 totalTargetEneCh[ch] = max( totalTargetEneCh[ch], 0.0f );
    3119             :             }
    3120             : #endif
    3121             : 
    3122             :             /* due to rounding, the sum may exceed 1.0f ever so slightly, so clip it */
    3123     5342330 :             ratioAccOrig = min( ratioAccOrig, 1.0f );
    3124     5342330 :             if ( masaGainEdited )
    3125             :             {
    3126     2351232 :                 ratioAccNew += gainMasaPow2 * ( 1.0f - ratioAccOrig );
    3127             :             }
    3128             :             else
    3129             :             {
    3130     2991098 :                 ratioAccNew += ( 1.0f - ratioAccOrig );
    3131             :             }
    3132             : 
    3133     5342330 :             ratioAccNewDivisor = 1.0f / fmaxf( 1e-12f, ratioAccNew ); /* New target total energy ratio divider */
    3134             : 
    3135             :             /* Determine and process object energy ratios based on gaining */
    3136    25521250 :             for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    3137             :             {
    3138    20178920 :                 newRatios[ismDirIndex + 2] = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo]; /* Determine original object energy ratio */
    3139    20178920 :                 if ( ismGainEdited[ismDirIndex] )
    3140             :                 {
    3141    18646565 :                     gainIsmThis = hMasaIsmData->gain_ism_edited[ismDirIndex];
    3142    18646565 :                     newRatios[ismDirIndex + 2] *= ( gainIsmThis * gainIsmThis ); /* Gain original object energy ratio, if edited */
    3143             :                 }
    3144    20178920 :                 newRatios[ismDirIndex + 2] *= ratioAccNewDivisor; /* Divide with new target total ratio */
    3145             :             }
    3146             : 
    3147             :             /* Determine and process MASA energy ratios based on gaining */
    3148     5342330 :             newRatios[0] = hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin_lo];
    3149     5342330 :             newRatios[1] = hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin_lo];
    3150     5342330 :             if ( masaGainEdited )
    3151             :             {
    3152     2351232 :                 newRatios[0] *= gainMasaPow2;
    3153     2351232 :                 newRatios[1] *= gainMasaPow2;
    3154             :             }
    3155     5342330 :             newRatios[0] *= ratioAccNewDivisor;
    3156     5342330 :             newRatios[1] *= ratioAccNewDivisor;
    3157             : 
    3158             :             /* Set adjusted energy ratios */
    3159    27448130 :             for ( bin = bin_lo; bin < bin_hi; bin++ )
    3160             :             {
    3161   107553000 :                 for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    3162             :                 {
    3163    85447200 :                     hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin] = newRatios[ismDirIndex + 2];
    3164             :                 }
    3165    22105800 :                 hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin] = newRatios[0];
    3166    22105800 :                 hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] = newRatios[1];
    3167             :             }
    3168             : 
    3169             :             /* Direction editing */
    3170             :             /* Determine new energetic values after gaining */
    3171     5342330 :             totalTargetEne = totalTargetEneCh[0] + totalTargetEneCh[1];
    3172     5342330 :             tempDivisor = 1.0f / fmaxf( 1e-12f, totalTargetEne );
    3173     5342330 :             normEnes[0] = totalTargetEneCh[0] * tempDivisor;
    3174     5342330 :             normEnes[1] = totalTargetEneCh[1] * tempDivisor;
    3175             : 
    3176             :             /* For each ismDir, determine moved and preserve energy ratio per channel */
    3177    25521250 :             for ( ismDirIndex = 0; ismDirIndex < n_ism; ismDirIndex++ )
    3178             :             {
    3179    20178920 :                 ratio = hMasaIsmData->energy_ratio_ism[ismDirIndex][dirac_read_idx][bin_lo];
    3180             : 
    3181    20178920 :                 ismRatioAcc += ratio;
    3182             : 
    3183    20178920 :                 if ( enableCentering )
    3184             :                 {
    3185    20178920 :                     centeringFactor = fmaxf( 0.0f, 2.0f * fabsf( panEnesIn[ismDirIndex][0] - panEnesOut[ismDirIndex][0] ) - 1.0f );
    3186    60536760 :                     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3187             :                     {
    3188    40357840 :                         panEnesOut[ismDirIndex][ch] *= ( 1.0f - centeringFactor );
    3189    40357840 :                         panEnesOut[ismDirIndex][ch] += 0.5f * centeringFactor;
    3190             :                     }
    3191             :                 }
    3192             : 
    3193    60536760 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3194             :                 {
    3195    40357840 :                     eneMoveThis = fmaxf( 0.0f, panEnesIn[ismDirIndex][ch] - panEnesOut[ismDirIndex][ch] );
    3196    40357840 :                     enePreserveThis = panEnesIn[ismDirIndex][ch] - eneMoveThis;
    3197             : 
    3198    40357840 :                     eneMove[ch] += ratio * eneMoveThis;
    3199    40357840 :                     enePreserve[ch] += ratio * enePreserveThis;
    3200             : 
    3201             :                     /* Subtract object parts from normEnes */
    3202    40357840 :                     normEnes[ch] -= panEnesIn[ismDirIndex][ch] * ratio;
    3203             :                 }
    3204             :             }
    3205             : 
    3206             :             /* Any remaining (non-object) energy is set to be preserved at both channels */
    3207     5342330 :             remainderNormEne = fmaxf( 0.0f, ( 1.0f - ismRatioAcc ) - normEnes[0] - normEnes[1] );
    3208             : 
    3209             :             /* Normalize */
    3210    16026990 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3211             :             {
    3212    10684660 :                 enePreserve[ch] += fmaxf( 0.0f, normEnes[ch] + remainderNormEne / 2.0f );
    3213    10684660 :                 normVal = 1.0f / fmaxf( EPSILON, eneMove[ch] + enePreserve[ch] );
    3214    10684660 :                 normVal *= fminf( 10.0f, totalTargetEneCh[ch] / fmaxf( EPSILON, subframeEneCh[ch] ) );
    3215    10684660 :                 eneMove[ch] *= normVal;
    3216    10684660 :                 enePreserve[ch] *= normVal;
    3217             :             }
    3218             : 
    3219             :             /* Temporally average target energy */
    3220     5342330 :             hMasaIsmData->eneOrigIIR[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    3221     5342330 :             hMasaIsmData->eneOrigIIR[band_idx] += totalTargetEne;
    3222             : 
    3223             :             /* Temporally average energy moving and preserving, and generate the transport signal preprocessing matrix for
    3224             :              * gaining objects and moving objects between left and right */
    3225    16026990 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3226             :             {
    3227    10684660 :                 hMasaIsmData->eneMoveIIR[ch][band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    3228    10684660 :                 hMasaIsmData->eneMoveIIR[ch][band_idx] += eneMove[ch] * totalTargetEne;
    3229    10684660 :                 hMasaIsmData->enePreserveIIR[ch][band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    3230    10684660 :                 hMasaIsmData->enePreserveIIR[ch][band_idx] += enePreserve[ch] * totalTargetEne;
    3231    10684660 :                 normVal = 1.0f / fmaxf( EPSILON, hMasaIsmData->eneOrigIIR[band_idx] );
    3232    10684660 :                 ismPreprocMtxNew[ch][ch] = fminf( 4.0f, sqrtf( hMasaIsmData->enePreserveIIR[ch][band_idx] * normVal ) );
    3233    10684660 :                 ismPreprocMtxNew[1 - ch][ch] = fminf( 4.0f, sqrtf( hMasaIsmData->eneMoveIIR[ch][band_idx] * normVal ) );
    3234             :             }
    3235             : 
    3236             :             /* Get increment value for temporal interpolation */
    3237    16026990 :             for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
    3238             :             {
    3239    32053980 :                 for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
    3240             :                 {
    3241    21369320 :                     ismPreprocMtxIncrement[outCh][inCh] = ( ismPreprocMtxNew[outCh][inCh] - hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] ) * nSlotDiv;
    3242             :                 }
    3243             :             }
    3244             : 
    3245             :             /* Mix signals */
    3246     5342330 :             hMasaIsmData->preprocEneTarget[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    3247     5342330 :             hMasaIsmData->preprocEneRealized[band_idx] *= STEREO_PREPROCESS_IIR_FACTOR;
    3248     5342330 :             hMasaIsmData->preprocEneTarget[band_idx] += totalTargetEne;
    3249             : 
    3250    16026990 :             for ( outCh = 0; outCh < BINAURAL_CHANNELS; outCh++ )
    3251             :             {
    3252    52208328 :                 for ( slot = 0; slot < nSlots; slot++ )
    3253             :                 {
    3254   124571004 :                     for ( inCh = 0; inCh < BINAURAL_CHANNELS; inCh++ )
    3255             :                     {
    3256    83047336 :                         hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx] += ismPreprocMtxIncrement[outCh][inCh];
    3257   423485896 :                         for ( bin = bin_lo; bin < bin_hi; bin++ )
    3258             :                         {
    3259   340438560 :                             outSlotRe[outCh][slot][bin] += inRe[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
    3260   340438560 :                             outSlotIm[outCh][slot][bin] += inIm[inCh][slot][bin] * hMasaIsmData->ismPreprocMatrix[outCh][inCh][band_idx];
    3261             :                         }
    3262             :                     }
    3263             : 
    3264   211742948 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    3265             :                     {
    3266   170219280 :                         hMasaIsmData->preprocEneRealized[band_idx] += ( outSlotRe[outCh][slot][bin] * outSlotRe[outCh][slot][bin] ) + ( outSlotIm[outCh][slot][bin] * outSlotIm[outCh][slot][bin] );
    3267             :                     }
    3268             :                 }
    3269             :             }
    3270             : 
    3271     5342330 :             eqVal = fminf( 4.0f, sqrtf( hMasaIsmData->preprocEneTarget[band_idx] / fmaxf( 1e-12f, hMasaIsmData->preprocEneRealized[band_idx] ) ) );
    3272             : 
    3273    16026990 :             for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3274             :             {
    3275    52208328 :                 for ( slot = 0; slot < nSlots; slot++ )
    3276             :                 {
    3277   211742948 :                     for ( bin = bin_lo; bin < bin_hi; bin++ )
    3278             :                     {
    3279   170219280 :                         inRe[ch][slot][bin] = outSlotRe[ch][slot][bin] * eqVal;
    3280   170219280 :                         inIm[ch][slot][bin] = outSlotIm[ch][slot][bin] * eqVal;
    3281             :                     }
    3282             :                 }
    3283             :             }
    3284             :         }
    3285             : 
    3286      368430 :         if ( !masaIsmMode )
    3287             :         {
    3288             :             int16_t obj_idx1, obj_idx2;
    3289             : 
    3290     3230760 :             for ( band_idx = 0; band_idx < hParamIsmDec->hParamIsm->nbands; band_idx++ )
    3291             :             {
    3292     2961530 :                 bin_lo = hParamIsmDec->hParamIsm->band_grouping[band_idx];
    3293     2961530 :                 bin_hi = hParamIsmDec->hParamIsm->band_grouping[band_idx + 1];
    3294             : 
    3295     2961530 :                 obj_idx1 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][0];
    3296     2961530 :                 obj_idx2 = hParamIsmDec->hParamIsm->obj_indices[band_idx][0][1];
    3297             : 
    3298    19115330 :                 for ( bin = bin_lo; bin < bin_hi; bin++ )
    3299             :                 {
    3300    16153800 :                     hSpatParamRendCom->energy_ratio1[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism[obj_idx1][dirac_read_idx][bin];
    3301    16153800 :                     hSpatParamRendCom->energy_ratio2[dirac_read_idx][bin] = hMasaIsmData->energy_ratio_ism[obj_idx2][dirac_read_idx][bin];
    3302             :                 }
    3303             :             }
    3304             :         }
    3305             :     }
    3306             : 
    3307      368430 :     return;
    3308             : }
    3309             : 
    3310             : 
    3311    11010724 : static void ivas_masa_ext_rend_parambin_internal(
    3312             :     MASA_EXT_REND_HANDLE hMasaExtRend,
    3313             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,
    3314             :     float *output_f[],
    3315             :     const int16_t subframe,
    3316             :     const SPLIT_REND_WRAPPER *hSplitRendWrapper,
    3317             :     float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
    3318             :     float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] )
    3319             : {
    3320             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
    3321             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    3322             :     PARAMBIN_REND_CONFIG config_data;
    3323             :     int16_t slot, ch, numInChannels;
    3324             :     float Cldfb_RealBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3325             :     float Cldfb_ImagBuffer_in[6][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3326             :     float Rmat[3][3];
    3327             :     int16_t max_band_decorr;
    3328             :     int16_t nBins;
    3329             :     int16_t i, j;
    3330             :     int16_t nchan_transport;
    3331             : 
    3332             :     int16_t pos_idx;
    3333             :     const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
    3334             :     float tmp_Cldfb_out_re[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3335             :     float tmp_Cldfb_out_im[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3336             : 
    3337             :     /* these allow re-using the reverb and freq-domain decorrelator signals from ivas_dirac_dec_binaural_process_output() in split rendering for the side renderings */
    3338             :     float reverbRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3339             :     float reverbIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3340             :     float decorrRe[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3341             :     float decorrIm[BINAURAL_CHANNELS][CLDFB_SLOTS_PER_SUBFRAME][CLDFB_NO_CHANNELS_MAX];
    3342             :     float subFrameTotalEne[CLDFB_NO_CHANNELS_MAX];
    3343             :     float IIReneLimiter[CLDFB_NO_CHANNELS_MAX];
    3344             : 
    3345    11010724 :     hDiracDecBin = hMasaExtRend->hDiracDecBin[0];
    3346    11010724 :     assert( hDiracDecBin );
    3347    11010724 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
    3348    11010724 :     nBins = hSpatParamRendCom->num_freq_bands;
    3349             : 
    3350             :     /* Setup internal config. MASA EXT renderer is quite strict. */
    3351    11010724 :     config_data.separateCenterChannelRendering = 0;
    3352    11010724 :     config_data.ivas_format = MASA_FORMAT;
    3353    11010724 :     config_data.mc_mode = MC_MODE_NONE;
    3354    11010724 :     config_data.ivas_total_brate = IVAS_512k; /* Maximum bitrate set for external renderer */
    3355    11010724 :     config_data.nchan_transport = hMasaExtRend->nchan_input;
    3356    11010724 :     config_data.qualityBasedSmFactor = 1.0f;
    3357    11010724 :     config_data.processReverb = hMasaExtRend->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ? 1 : 0;
    3358    11010724 :     config_data.ism_mode = ISM_MODE_NONE;
    3359             : 
    3360             :     /* Set nchan_transport to number of transport channels in MASA input */
    3361    11010724 :     nchan_transport = hMasaExtRend->nchan_input;
    3362             : 
    3363             :     /* The input channel number at this processing function (not nchan_transport) */
    3364    11010724 :     numInChannels = BINAURAL_CHANNELS;
    3365             : 
    3366    11010724 :     Rmat[0][0] = 1.0f;
    3367    11010724 :     Rmat[0][1] = 0.0f;
    3368    11010724 :     Rmat[0][2] = 0.0f;
    3369             : 
    3370    11010724 :     Rmat[1][0] = 0.0f;
    3371    11010724 :     Rmat[1][1] = 1.0f;
    3372    11010724 :     Rmat[1][2] = 0.0f;
    3373             : 
    3374    11010724 :     Rmat[2][0] = 0.0f;
    3375    11010724 :     Rmat[2][1] = 0.0f;
    3376    11010724 :     Rmat[2][2] = 1.0f;
    3377             : 
    3378             :     /* CLDFB Analysis of input */
    3379    55053620 :     for ( slot = 0; slot < hSpatParamRendCom->subframe_nbslots[subframe]; slot++ )
    3380             :     {
    3381   132128688 :         for ( ch = 0; ch < numInChannels; ch++ )
    3382             :         {
    3383    88085792 :             if ( ch == 0 || nchan_transport == 2 )
    3384             :             {
    3385    67040424 :                 cldfbAnalysis_ts(
    3386    67040424 :                     &( output_f[ch][nBins * slot] ),
    3387    67040424 :                     Cldfb_RealBuffer_in[ch][slot],
    3388    67040424 :                     Cldfb_ImagBuffer_in[ch][slot],
    3389             :                     nBins, hMasaExtRend->cldfbAnaRend[ch] );
    3390             :             }
    3391             :             else /* when nchan_transport == 1 and ch == 1 */
    3392             :             {
    3393             :                 /* At mono input duplicate the channel to dual-mono, and apply gain
    3394             :                 correction to ensure same overall level as in stereo mode  */
    3395    21045368 :                 v_multc( Cldfb_RealBuffer_in[0][slot], INV_SQRT_2, Cldfb_RealBuffer_in[0][slot], nBins );
    3396    21045368 :                 v_multc( Cldfb_ImagBuffer_in[0][slot], INV_SQRT_2, Cldfb_ImagBuffer_in[0][slot], nBins );
    3397             : 
    3398    21045368 :                 mvr2r( Cldfb_RealBuffer_in[0][slot], Cldfb_RealBuffer_in[1][slot], nBins );
    3399    21045368 :                 mvr2r( Cldfb_ImagBuffer_in[0][slot], Cldfb_ImagBuffer_in[1][slot], nBins );
    3400             :             }
    3401             :         }
    3402             :     }
    3403             : 
    3404    11010724 :     if ( hCombinedOrientationData )
    3405             :     {
    3406    19004576 :         for ( i = 0; i < 3; i++ )
    3407             :         {
    3408    57013728 :             for ( j = 0; j < 3; j++ )
    3409             :             {
    3410    42760296 :                 Rmat[i][j] = hCombinedOrientationData->Rmat[hCombinedOrientationData->subframe_idx][i][j];
    3411             :             }
    3412             :         }
    3413             : 
    3414     4751144 :         if ( nchan_transport == 2 )
    3415             :         {
    3416             :             /* in case of split rendering, determine the prototype rotation based on the main direction and use the same prototypes for the offset directions */
    3417     2480152 :             adaptTransportSignalsHeadtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
    3418             : 
    3419     2480152 :             ivas_dirac_dec_binaural_check_and_switch_transports_headtracked( hCombinedOrientationData, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, nBins, hSpatParamRendCom->subframe_nbslots[subframe], Rmat );
    3420             :         }
    3421             :     }
    3422             : 
    3423             : 
    3424             :     /* Always using CLDFB decorrelation in MASA EXT renderer */
    3425    11010724 :     max_band_decorr = hDiracDecBin->h_freq_domain_decorr_ap_params->max_band_decorr;
    3426             : 
    3427             : 
    3428    11010724 :     ivas_dirac_dec_binaural_formulate_input_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in, subframe,
    3429             :                                                                  subFrameTotalEne, IIReneLimiter );
    3430             : 
    3431    11010724 :     ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat, subframe,
    3432    11010724 :                                                                   hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    3433             :                                                                   subFrameTotalEne, IIReneLimiter, NULL );
    3434             : 
    3435    11010724 :     ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat, subframe,
    3436    11010724 :                                                            hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[hCombinedOrientationData->subframe_idx] > 0,
    3437             :                                                            0, NULL );
    3438             : 
    3439    11010724 :     pMultiBinPoseData = NULL;
    3440    11010724 :     if ( hSplitRendWrapper != NULL )
    3441             :     {
    3442       57664 :         pMultiBinPoseData = &( hSplitRendWrapper->multiBinPoseData );
    3443             : 
    3444       57664 :         ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
    3445       57664 :                                                 max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
    3446             :                                                 reverbRe, reverbIm, decorrRe, decorrIm, 1 );
    3447             : 
    3448      172992 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3449             :         {
    3450      576640 :             for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
    3451             :             {
    3452      461312 :                 mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    3453      461312 :                 mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    3454             :             }
    3455             :         }
    3456             :     }
    3457             :     else
    3458             :     {
    3459    10953060 :         ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
    3460    10953060 :                                                 max_band_decorr, numInChannels, config_data.processReverb, subframe, NULL, NULL,
    3461             :                                                 reverbRe, reverbIm, decorrRe, decorrIm, 1 );
    3462             :     }
    3463             : 
    3464    11010724 :     hDiracDecBin->hDiffuseDist = NULL;
    3465             : 
    3466    11010724 :     if ( pMultiBinPoseData != NULL && pMultiBinPoseData->num_poses > 1 )
    3467             :     {
    3468             :         /* quaternion-based rotation from ivas_binRenderer_internal.c:ivas_binRenderer(), but using absolute rotation instead of delta rotations */
    3469             :         IVAS_QUATERNION Quaternions_rot, Quaternions_abs, *Quaternions_ref;
    3470             :         float Rmat_local[3][3];
    3471             : 
    3472       40704 :         if ( hCombinedOrientationData )
    3473             :         {
    3474       40704 :             Quaternions_ref = &hCombinedOrientationData->Quaternions[0];
    3475       40704 :             Quaternions_rot.w = -3.0f;                                                                        /* signal to use Euler */
    3476       40704 :             Quaternions_abs.w = -3.0f;                                                                        /* signal to use Euler */
    3477       40704 :             Quat2EulerDegree( *Quaternions_ref, &Quaternions_abs.z, &Quaternions_abs.y, &Quaternions_abs.x ); /*order in Quat2Euler seems to be reversed ?*/
    3478             : 
    3479      217088 :             for ( pos_idx = 1; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
    3480             :             {
    3481      176384 :                 Quaternions_rot.x = Quaternions_abs.x + pMultiBinPoseData->relative_head_poses[pos_idx][0];
    3482      176384 :                 Quaternions_rot.y = Quaternions_abs.y + pMultiBinPoseData->relative_head_poses[pos_idx][1];
    3483      176384 :                 Quaternions_rot.z = Quaternions_abs.z + pMultiBinPoseData->relative_head_poses[pos_idx][2];
    3484             : 
    3485      176384 :                 QuatToRotMat( Quaternions_rot, Rmat_local );
    3486             : 
    3487      176384 :                 hDiracDecBin = hMasaExtRend->hDiracDecBin[pos_idx];
    3488      176384 :                 assert( hDiracDecBin != NULL && "No DiracDecBin handle for this position" );
    3489             : 
    3490             :                 /* re-use input covariance for the side renderings */
    3491      529152 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3492             :                 {
    3493      352768 :                     mvr2r( hMasaExtRend->hDiracDecBin[0]->ChEne[ch], hDiracDecBin->ChEne[ch], hSpatParamRendCom->num_freq_bands );
    3494             :                 }
    3495      176384 :                 mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossRe, hDiracDecBin->ChCrossRe, hSpatParamRendCom->num_freq_bands );
    3496      176384 :                 mvr2r( hMasaExtRend->hDiracDecBin[0]->ChCrossIm, hDiracDecBin->ChCrossIm, hSpatParamRendCom->num_freq_bands );
    3497             : 
    3498      176384 :                 ivas_dirac_dec_binaural_formulate_target_covariance_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, Rmat_local, subframe,
    3499      176384 :                                                                               hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    3500             :                                                                               subFrameTotalEne, IIReneLimiter, NULL );
    3501             : 
    3502      176384 :                 ivas_dirac_dec_binaural_determine_processing_matrices( hDiracDecBin, hSpatParamRendCom, &config_data, max_band_decorr, Rmat_local, subframe,
    3503      176384 :                                                                        hCombinedOrientationData && hCombinedOrientationData->enableCombinedOrientation[subframe] > 0,
    3504             :                                                                        0, NULL );
    3505             : 
    3506             : 
    3507             :                 /* re-use reverb and decorr from main direction for the sides */
    3508      176384 :                 ivas_dirac_dec_binaural_process_output( hDiracDecBin, hSpatParamRendCom, hMasaExtRend->cldfbSynRend, output_f, Cldfb_RealBuffer_in, Cldfb_ImagBuffer_in,
    3509      176384 :                                                         max_band_decorr, numInChannels, config_data.processReverb, subframe, tmp_Cldfb_out_re, tmp_Cldfb_out_im,
    3510             :                                                         reverbRe, reverbIm, decorrRe, decorrIm, 0 );
    3511             : 
    3512             :                 /* copy from temporary buffer to the main split rendering buffer */
    3513      529152 :                 for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3514             :                 {
    3515     1763840 :                     for ( i = 0; i < CLDFB_SLOTS_PER_SUBFRAME; i++ )
    3516             :                     {
    3517     1411072 :                         mvr2r( tmp_Cldfb_out_re[ch][i], Cldfb_Out_Real[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    3518     1411072 :                         mvr2r( tmp_Cldfb_out_im[ch][i], Cldfb_Out_Imag[pos_idx * BINAURAL_CHANNELS + ch][subframe * CLDFB_SLOTS_PER_SUBFRAME + i], CLDFB_NO_CHANNELS_MAX );
    3519             :                     }
    3520             :                 }
    3521             : 
    3522      176384 :                 hDiracDecBin->hDiffuseDist = NULL;
    3523             :             }
    3524             :         }
    3525             :     }
    3526             : 
    3527             :     /* update this counter only after the last rendering of split directions */
    3528    11010724 :     hSpatParamRendCom->slots_rendered += hSpatParamRendCom->subframe_nbslots[subframe];
    3529    11010724 :     hSpatParamRendCom->subframes_rendered++;
    3530             : 
    3531    11010724 :     return;
    3532             : }
    3533             : 
    3534             : 
    3535     6859363 : void ivas_masa_ext_rend_parambin_render(
    3536             :     MASA_EXT_REND_HANDLE hMasaExtRend,                               /* i/o: MASA ext rend structure                                  */
    3537             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData,            /* i  : combined orientation handle                              */
    3538             :     float *output_f[],                                               /* i/o: synthesized core-coder transport channels/DirAC output   */
    3539             :     const int16_t num_subframes,                                     /* i  : number of subframes to render                            */
    3540             :     const SPLIT_REND_WRAPPER *hSplitRendWrapper,                     /* i  : split rendering orientation data                         */
    3541             :     float Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* o  : rendered orientations for split rend. real part of cldfb */
    3542             :     float Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]  /* o  : rendered orientations for split rend. imag part of cldfb */
    3543             : )
    3544             : {
    3545             :     int16_t subframe;
    3546             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    3547             :     float *p_output[BINAURAL_CHANNELS];
    3548             :     int16_t ch;
    3549             : 
    3550     6859363 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
    3551             : 
    3552    20578089 :     for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3553             :     {
    3554    13718726 :         p_output[ch] = output_f[ch];
    3555             :     }
    3556             : 
    3557     6859363 :     hSpatParamRendCom->subframes_rendered = hSpatParamRendCom->dirac_read_idx;
    3558             : 
    3559    17870087 :     for ( subframe = 0; subframe < num_subframes; subframe++ )
    3560             :     {
    3561    11010724 :         int16_t n_samples_sf = hSpatParamRendCom->slot_size * CLDFB_SLOTS_PER_SUBFRAME;
    3562    11010724 :         hSpatParamRendCom->slots_rendered = 0;
    3563             : 
    3564    11010724 :         ivas_masa_ext_rend_parambin_internal( hMasaExtRend, hCombinedOrientationData, p_output, hSpatParamRendCom->dirac_read_idx, hSplitRendWrapper, Cldfb_Out_Real, Cldfb_Out_Imag );
    3565             : 
    3566    33032172 :         for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ )
    3567             :         {
    3568    22021448 :             p_output[ch] += n_samples_sf;
    3569             :         }
    3570             : 
    3571    11010724 :         ivas_combined_orientation_update_index( hCombinedOrientationData, n_samples_sf );
    3572             : 
    3573    11010724 :         hSpatParamRendCom->dirac_read_idx = ( hSpatParamRendCom->dirac_read_idx + 1 ) % hSpatParamRendCom->dirac_md_buffer_length;
    3574             :     }
    3575             : 
    3576     6859363 :     return;
    3577             : }

Generated by: LCOV version 1.14