LCOV - code coverage report
Current view: top level - lib_rend - lib_rend_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main enc/dec/rend @ ca3146eb9de8185ed0247945c643267826a32a94 Lines: 3134 4455 70.3 %
Date: 2025-08-26 01:31:27 Functions: 135 170 79.4 %

          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 "basop_util.h"
      34             : #include "options.h"
      35             : #include "lib_rend.h"
      36             : #include "prot_fx.h"
      37             : #include "ivas_prot_fx.h"
      38             : #include "ivas_prot_rend_fx.h"
      39             : #include "isar_prot.h"
      40             : #include "isar_stat.h"
      41             : #include "lib_isar_pre_rend.h"
      42             : #include "ivas_cnst.h"
      43             : #include "ivas_rom_com.h"
      44             : #include "ivas_rom_com_fx.h"
      45             : #include "ivas_rom_rend.h"
      46             : #include <assert.h>
      47             : #include <math.h>
      48             : #include <stdbool.h>
      49             : #include "wmc_auto.h"
      50             : #ifdef DEBUGGING
      51             : #include "debug.h"
      52             : #endif
      53             : 
      54             : /*-------------------------------------------------------------------*
      55             :  * Local constants
      56             :  *-------------------------------------------------------------------*/
      57             : 
      58             : /* Maximum buffer length (total) in samples. */
      59             : #define MAX_BUFFER_LENGTH     ( MAX_BUFFER_LENGTH_PER_CHANNEL * MAX_INPUT_CHANNELS )
      60             : #define MAX_BIN_DELAY_SAMPLES 150 /* Maximum supported rendering latency for binaural IRs */
      61             : 
      62             : /*-------------------------------------------------------------------*
      63             :  * Local types
      64             :  *-------------------------------------------------------------------*/
      65             : 
      66             : typedef float pan_vector[MAX_OUTPUT_CHANNELS];
      67             : typedef float pan_matrix[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
      68             : typedef float rotation_gains[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS];
      69             : typedef Word32 pan_vector_fx[MAX_OUTPUT_CHANNELS];
      70             : typedef Word32 pan_matrix_fx[MAX_INPUT_CHANNELS][MAX_OUTPUT_CHANNELS];
      71             : typedef Word16 rotation_gains_fx[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS];
      72             : typedef Word32 rotation_gains_Word32[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS];
      73             : typedef Word32 rotation_matrix_fx[3][3];
      74             : typedef float rotation_matrix[3][3];
      75             : 
      76             : /* EFAP wrapper to simplify writing panning gains to a vector that includes LFE channels */
      77             : typedef struct
      78             : {
      79             :     EFAP_HANDLE hEfap;
      80             :     AUDIO_CONFIG speakerConfig;
      81             :     const LSSETUP_CUSTOM_STRUCT *pCustomLsSetup; /* Pointer to main custom LS struct from renderer handle - doesn't need freeing */
      82             : } EFAP_WRAPPER;
      83             : 
      84             : /* Lightweight helper struct that gathers all information required for rendering
      85             :  * any config to any other config. Used to simplify signatures of rendering functions.
      86             :  *
      87             :  * This struct should store ONLY CONST POINTERS to data existing elsewhere.
      88             :  * Storing pointers instead of data itself ensures that no additional updates
      89             :  * are required when any of these are changed in the renderer. Making the pointers
      90             :  * const ensures that this data is only read, but not modified by the rendering functions. */
      91             : typedef struct
      92             : {
      93             :     const Word32 *pOutSampleRate;
      94             :     const AUDIO_CONFIG *pOutConfig;
      95             :     const LSSETUP_CUSTOM_STRUCT *pCustomLsOut;
      96             :     const EFAP_WRAPPER *pEfapOutWrapper;
      97             :     IVAS_REND_HeadRotData *pHeadRotData; // for now removing the const qualifier TODO: will modify later
      98             :     const RENDER_CONFIG_HANDLE *hhRendererConfig;
      99             :     const Word16 *pSplitRendBFI;
     100             :     const SPLIT_REND_WRAPPER *pSplitRendWrapper;
     101             :     const COMBINED_ORIENTATION_HANDLE *pCombinedOrientationData;
     102             : } rendering_context;
     103             : 
     104             : /* Common base for input structs */
     105             : typedef struct
     106             : {
     107             :     AUDIO_CONFIG inConfig;
     108             :     IVAS_REND_InputId id;
     109             :     IVAS_REND_AudioBuffer inputBuffer;
     110             :     Word32 gain_fx; /* Linear, not in dB Q30 */
     111             :     rendering_context ctx;
     112             :     Word32 numNewSamplesPerChannel; /* Used to keep track how much new audio was fed before rendering current frame */
     113             : } input_base;
     114             : 
     115             : typedef struct
     116             : {
     117             :     input_base base;
     118             :     IVAS_ISM_METADATA currentPos;
     119             :     IVAS_ISM_METADATA previousPos;
     120             :     TDREND_WRAPPER tdRendWrapper;
     121             :     CREND_WRAPPER_HANDLE crendWrapper;
     122             :     REVERB_HANDLE hReverb;
     123             :     rotation_matrix_fx rot_mat_prev;
     124             :     pan_vector_fx prev_pan_gains_fx;
     125             :     rotation_matrix_fx rot_mat_prev_fx;
     126             :     pan_vector prev_pan_gains;
     127             :     Word8 firstFrameRendered;
     128             :     TDREND_WRAPPER splitTdRendWrappers[MAX_HEAD_ROT_POSES - 1]; /* Additional TD Rend instances used for split rendering */
     129             :     Word32 *bufferData_fx;
     130             :     Word16 nonDiegeticPan;
     131             :     Word32 nonDiegeticPanGain_fx; /* Q31 */
     132             :     OMASA_ANA_HANDLE hOMasa;
     133             :     UWord16 total_num_objects;
     134             :     Word32 ism_metadata_delay_ms_fx; /* Q0 */
     135             : } input_ism;
     136             : 
     137             : typedef struct
     138             : {
     139             :     Word16 numLfeChannels;
     140             :     bool pan_lfe;
     141             :     // float lfeInputGain;
     142             :     Word32 lfeInputGain_fx; /* Q31 */
     143             :     // float lfeOutputAzimuth;
     144             :     Word16 lfeOutputAzimuth_fx;
     145             :     // float lfeOutputElevation;
     146             :     Word16 lfeOutputElevation_fx;
     147             :     // IVAS_REND_LfePanMtx lfePanMtx;
     148             :     IVAS_REND_LfePanMtx_fx lfePanMtx_fx; /* Q31 */
     149             : } lfe_routing;
     150             : 
     151             : typedef struct
     152             : {
     153             :     input_base base;
     154             : 
     155             :     /* Full panning matrix. 1st index is input channel, 2nd index is output channel.
     156             :        All LFE channels should be included, both for inputs and outputs */
     157             :     pan_matrix_fx panGains_fx; /* Q31 */
     158             : 
     159             :     LSSETUP_CUSTOM_STRUCT customLsInput;
     160             :     EFAP_WRAPPER efapInWrapper;
     161             :     TDREND_WRAPPER tdRendWrapper;
     162             :     CREND_WRAPPER_HANDLE crendWrapper;
     163             :     TDREND_WRAPPER splitTdRendWrappers[MAX_HEAD_ROT_POSES - 1]; /* Additional TD Rend instances used for split rendering */
     164             :     REVERB_HANDLE hReverb;
     165             :     rotation_gains_Word32 rot_gains_prev_fx[MAX_HEAD_ROT_POSES];
     166             :     Word16 nonDiegeticPan;
     167             :     Word32 nonDiegeticPanGain_fx;
     168             :     lfe_routing lfeRouting;
     169             :     Word32 *bufferData_fx;
     170             :     Word16 binauralDelaySmp;
     171             :     Word32 *lfeDelayBuffer_fx;
     172             :     MCMASA_ANA_HANDLE hMcMasa;
     173             : } input_mc;
     174             : 
     175             : typedef struct
     176             : {
     177             :     input_base base;
     178             :     // pan_matrix hoaDecMtx;
     179             :     pan_matrix_fx hoaDecMtx_fx;
     180             :     CLDFB_REND_WRAPPER cldfbRendWrapper;
     181             :     CREND_WRAPPER_HANDLE crendWrapper;
     182             :     rotation_gains_fx rot_gains_prev_fx[MAX_HEAD_ROT_POSES];
     183             :     Word32 *bufferData_fx;
     184             :     DIRAC_ANA_HANDLE hDirAC;
     185             : } input_sba;
     186             : 
     187             : typedef struct
     188             : {
     189             :     input_base base;
     190             :     MASA_METADATA_FRAME masaMetadata;
     191             :     bool metadataHasBeenFed;
     192             :     Word32 *bufferData_fx;
     193             :     MASA_EXT_REND_HANDLE hMasaExtRend;
     194             :     MASA_PREREND_HANDLE hMasaPrerend;
     195             : } input_masa;
     196             : 
     197             : typedef struct hrtf_handles
     198             : {
     199             :     IVAS_DEC_HRTF_CREND_HANDLE hSetOfHRTF;
     200             :     IVAS_DEC_HRTF_FASTCONV_HANDLE hHrtfFastConv;
     201             :     IVAS_DEC_HRTF_PARAMBIN_HANDLE hHrtfParambin;
     202             :     IVAS_DEC_HRTF_HANDLE hHrtfTD;
     203             :     IVAS_DEC_HRTF_STATISTICS_HANDLE hHrtfStatistics;
     204             : } hrtf_handles;
     205             : 
     206             : 
     207             : struct IVAS_REND
     208             : {
     209             :     Word32 sampleRateOut;
     210             :     IVAS_LIMITER_HANDLE hLimiter;
     211             : 
     212             :     input_ism inputsIsm[RENDERER_MAX_ISM_INPUTS];
     213             :     input_mc inputsMc[RENDERER_MAX_MC_INPUTS];
     214             :     input_sba inputsSba[RENDERER_MAX_SBA_INPUTS];
     215             :     input_masa inputsMasa[RENDERER_MAX_MASA_INPUTS];
     216             : 
     217             :     AUDIO_CONFIG inputConfig;
     218             :     AUDIO_CONFIG outputConfig;
     219             :     EFAP_WRAPPER efapOutWrapper;
     220             :     IVAS_LSSETUP_CUSTOM_STRUCT customLsOut;
     221             : 
     222             :     SPLIT_REND_WRAPPER *splitRendWrapper;
     223             :     IVAS_REND_AudioBuffer splitRendEncBuffer;
     224             :     IVAS_REND_HeadRotData headRotData;
     225             :     Word16 splitRendBFI;
     226             : 
     227             :     EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData;
     228             :     COMBINED_ORIENTATION_HANDLE hCombinedOrientationData;
     229             : 
     230             :     Word8 rendererConfigEnabled;
     231             :     RENDER_CONFIG_DATA *hRendererConfig; /* Renderer config pointer */
     232             : 
     233             :     Word16 num_subframes;
     234             :     hrtf_handles hHrtfs;
     235             : };
     236             : 
     237             : 
     238             : /*-------------------------------------------------------------------*
     239             :  * Local function prototypes
     240             :  *-------------------------------------------------------------------*/
     241             : 
     242             : static ivas_error initMasaExtRenderer( input_masa *inputMasa, const AUDIO_CONFIG outConfig, const RENDER_CONFIG_DATA *hRendCfg, hrtf_handles *hHrtfs );
     243             : 
     244             : static void freeMasaExtRenderer( MASA_EXT_REND_HANDLE *hMasaExtRendOut );
     245             : 
     246             : static void intermidiate_ext_dirac_render( MASA_EXT_REND_HANDLE hMasaExtRend, Word16 to_fix );
     247             : 
     248             : static ivas_error renderSbaToMultiBinauralCldfb( input_sba *sbaInput, Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], const Word16 low_res_pre_rend_rot, const Word16 num_subframes, const Word16 Q_in );
     249             : #ifdef FIX_1843_IO_QFACTOR_INIT
     250             : static ivas_error renderSbaToMultiBinaural( input_sba *sbaInput, const AUDIO_CONFIG outConfig, Word32 out[][L_FRAME48k], const Word16 *pq_fact );
     251             : #else
     252             : static ivas_error renderSbaToMultiBinaural( input_sba *sbaInput, const AUDIO_CONFIG outConfig, Word32 out[][L_FRAME48k] );
     253             : #endif
     254             : 
     255             : 
     256             : /*-------------------------------------------------------------------*
     257             :  * Local functions
     258             :  *-------------------------------------------------------------------*/
     259             : 
     260         973 : static ivas_error allocateInputBaseBufferData_fx(
     261             :     Word32 **data, /* Qx */
     262             :     const Word16 data_size )
     263             : {
     264         973 :     *data = (Word32 *) malloc( data_size * sizeof( Word32 ) );
     265         973 :     IF( *data == NULL )
     266             :     {
     267           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for input base buffer data" );
     268             :     }
     269             : 
     270         973 :     return IVAS_ERR_OK;
     271             : }
     272        4662 : static void freeInputBaseBufferData_fx(
     273             :     Word32 **data /* Qx */ )
     274             : {
     275        4662 :     IF( *data != NULL )
     276             :     {
     277         973 :         free( *data );
     278         973 :         *data = NULL;
     279             :     }
     280             : 
     281        4662 :     return;
     282             : }
     283         372 : static ivas_error allocateMcLfeDelayBuffer_fx(
     284             :     Word32 **lfeDelayBuffer, /* Qx */
     285             :     const Word16 data_size )
     286             : {
     287         372 :     *lfeDelayBuffer = (Word32 *) malloc( data_size * sizeof( Word32 ) );
     288         372 :     IF( *lfeDelayBuffer == NULL )
     289             :     {
     290           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for LFE delay buffer" );
     291             :     }
     292             : 
     293         372 :     return IVAS_ERR_OK;
     294             : }
     295         666 : static void freeMcLfeDelayBuffer_fx(
     296             :     Word32 **lfeDelayBuffer /* Qx */ )
     297             : {
     298         666 :     IF( *lfeDelayBuffer != NULL )
     299             :     {
     300         372 :         free( *lfeDelayBuffer );
     301         372 :         *lfeDelayBuffer = NULL;
     302             :     }
     303             : 
     304         666 :     return;
     305             : }
     306             : 
     307             : 
     308         235 : static IVAS_QUATERNION quaternionInit_fx(
     309             :     void )
     310             : {
     311             :     IVAS_QUATERNION q;
     312         235 :     q.w_fx = ONE_IN_Q29;
     313         235 :     move32();
     314         235 :     q.x_fx = q.y_fx = q.z_fx = 0;
     315         235 :     move32();
     316         235 :     move32();
     317         235 :     move32();
     318             : 
     319         235 :     q.q_fact = Q29;
     320         235 :     move16();
     321         235 :     move16();
     322         235 :     move16();
     323         235 :     move16();
     324             : 
     325         235 :     return q;
     326             : }
     327             : 
     328   215021437 : static Word32 *getSmplPtr_fx(
     329             :     IVAS_REND_AudioBuffer buffer,
     330             :     const UWord32 chnlIdx,
     331             :     const UWord32 smplIdx )
     332             : {
     333   215021437 :     return buffer.data_fx + chnlIdx * buffer.config.numSamplesPerChannel + smplIdx;
     334             : }
     335             : 
     336           0 : static void convertBitsBufferToInternalBitsBuff(
     337             :     const IVAS_REND_BitstreamBuffer outBits,
     338             :     ISAR_SPLIT_REND_BITS_HANDLE hBits )
     339             : {
     340           0 :     hBits->bits_buf = outBits.bits;
     341           0 :     hBits->bits_read = outBits.config.bitsRead;
     342           0 :     hBits->bits_written = outBits.config.bitsWritten;
     343           0 :     hBits->buf_len = outBits.config.bufLenInBytes;
     344           0 :     hBits->codec = outBits.config.codec;
     345           0 :     hBits->pose_correction = outBits.config.poseCorrection;
     346           0 :     hBits->codec_frame_size_ms = outBits.config.codec_frame_size_ms;
     347             : 
     348           0 :     move16();
     349           0 :     move32();
     350           0 :     move32();
     351           0 :     move32();
     352           0 :     move32();
     353           0 :     move32();
     354           0 :     move32();
     355             : 
     356           0 :     return;
     357             : }
     358             : 
     359           0 : static void convertInternalBitsBuffToBitsBuffer(
     360             :     IVAS_REND_BitstreamBuffer *hOutBits,
     361             :     const ISAR_SPLIT_REND_BITS_DATA bits )
     362             : {
     363           0 :     hOutBits->bits = bits.bits_buf;
     364           0 :     hOutBits->config.bitsRead = bits.bits_read;
     365           0 :     hOutBits->config.bitsWritten = bits.bits_written;
     366           0 :     hOutBits->config.bufLenInBytes = bits.buf_len;
     367           0 :     hOutBits->config.codec = bits.codec;
     368           0 :     hOutBits->config.poseCorrection = bits.pose_correction;
     369           0 :     hOutBits->config.codec_frame_size_ms = bits.codec_frame_size_ms;
     370             : 
     371           0 :     return;
     372             : }
     373             : 
     374           0 : static void copyBufferToCLDFBarray_fx(
     375             :     const IVAS_REND_AudioBuffer buffer,
     376             :     Word32 re[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
     377             :     Word32 im[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX] )
     378             : {
     379             :     UWord32 smplIdx, slotIdx;
     380             :     UWord32 numCldfbSamples, num_bands;
     381             :     UWord32 chnlIdx;
     382             :     const Word32 *readPtr;
     383             : 
     384           0 :     assert( ( buffer.config.is_cldfb == 1 ) && "for time domain input call copyBufferTo2dArray()" );
     385           0 :     readPtr = buffer.data_fx;
     386           0 :     numCldfbSamples = (UWord32) shr( buffer.config.numSamplesPerChannel, 1 );
     387           0 :     num_bands = (UWord32) Mpy_32_32( numCldfbSamples, ONE_BY_CLDFB_NO_COL_MAX_Q31 );
     388           0 :     FOR( chnlIdx = 0; chnlIdx < (UWord32) buffer.config.numChannels; ++chnlIdx )
     389             :     {
     390           0 :         FOR( slotIdx = 0; slotIdx < CLDFB_NO_COL_MAX; ++slotIdx )
     391             :         {
     392           0 :             FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx )
     393             :             {
     394           0 :                 re[chnlIdx][slotIdx][smplIdx] = *readPtr++;
     395             :             }
     396           0 :             FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx )
     397             :             {
     398           0 :                 im[chnlIdx][slotIdx][smplIdx] = *readPtr++;
     399             :             }
     400             :         }
     401             :     }
     402             : 
     403           0 :     return;
     404             : }
     405             : 
     406           0 : static void accumulateCLDFBArrayToBuffer_fx(
     407             :     Word32 re[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
     408             :     Word32 im[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
     409             :     IVAS_REND_AudioBuffer *buffer )
     410             : {
     411             :     UWord32 smplIdx, slotIdx;
     412             :     UWord32 numCldfbSamples, num_bands;
     413             :     Word16 chnlIdx;
     414             :     Word32 *writePtr;
     415             : 
     416           0 :     assert( ( buffer->config.is_cldfb == 1 ) && "for time domain input call copyBufferTo2dArray()" );
     417           0 :     writePtr = buffer->data_fx;
     418           0 :     numCldfbSamples = (UWord32) shr( buffer->config.numSamplesPerChannel, 1 );
     419           0 :     num_bands = (UWord32) Mpy_32_32( numCldfbSamples, ONE_BY_CLDFB_NO_COL_MAX_Q31 );
     420             : 
     421           0 :     FOR( chnlIdx = 0; chnlIdx < buffer->config.numChannels; ++chnlIdx )
     422             :     {
     423           0 :         FOR( slotIdx = 0; slotIdx < CLDFB_NO_COL_MAX; ++slotIdx )
     424             :         {
     425           0 :             FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx )
     426             :             {
     427           0 :                 *writePtr++ += re[chnlIdx][slotIdx][smplIdx];
     428             :             }
     429           0 :             FOR( smplIdx = 0; smplIdx < num_bands; ++smplIdx )
     430             :             {
     431           0 :                 *writePtr++ += im[chnlIdx][slotIdx][smplIdx];
     432             :             }
     433             :         }
     434             :     }
     435             : 
     436           0 :     return;
     437             : }
     438             : 
     439      645648 : static void copyBufferTo2dArray_fx(
     440             :     const IVAS_REND_AudioBuffer buffer,
     441             :     Word32 array[][L_FRAME48k] )
     442             : {
     443             :     UWord32 smplIdx;
     444             :     UWord32 chnlIdx;
     445             :     const Word32 *readPtr;
     446             : 
     447      645648 :     assert( ( buffer.config.is_cldfb == 0 ) && "for CLDFB input call copyBufferToCLDFBarray()" );
     448             : 
     449      645648 :     readPtr = buffer.data_fx;
     450             : 
     451     4569484 :     FOR( chnlIdx = 0; chnlIdx < (UWord32) buffer.config.numChannels; ++chnlIdx )
     452             :     {
     453  1512693436 :         FOR( smplIdx = 0; smplIdx < (UWord32) buffer.config.numSamplesPerChannel; ++smplIdx )
     454             :         {
     455  1508769600 :             array[chnlIdx][smplIdx] = *readPtr++;
     456  1508769600 :             move32();
     457             :         }
     458             :     }
     459             : 
     460      645648 :     return;
     461             : }
     462      645648 : static void accumulate2dArrayToBuffer_fx(
     463             :     Word32 array[][L_FRAME48k],
     464             :     const IVAS_REND_AudioBuffer *buffer )
     465             : {
     466             :     Word16 smplIdx, chnlIdx;
     467             :     Word32 *writePtr;
     468             : 
     469      645648 :     writePtr = buffer->data_fx;
     470     2020944 :     FOR( chnlIdx = 0; chnlIdx < buffer->config.numChannels; ++chnlIdx )
     471             :     {
     472   530200896 :         FOR( smplIdx = 0; smplIdx < buffer->config.numSamplesPerChannel; ++smplIdx )
     473             :         {
     474   528825600 :             *writePtr = L_add( *writePtr, array[chnlIdx][smplIdx] );
     475   528825600 :             move32();
     476   528825600 :             writePtr++;
     477             :         }
     478             :     }
     479             : 
     480      645648 :     return;
     481             : }
     482             : /*-------------------------------------------------------------------*
     483             :  * limitRendererOutput()
     484             :  *
     485             :  * In-place saturation control for multichannel buffers with adaptive release time
     486             :  *-------------------------------------------------------------------*/
     487             : 
     488             : #ifndef DISABLE_LIMITER
     489             : /*! r: number of clipped output samples */
     490     1126140 : static Word32 limitRendererOutput_fx(
     491             :     IVAS_LIMITER_HANDLE hLimiter, /* i/o: limiter struct handle                                           */
     492             :     Word32 *output,               /* i/o: I/O buffer                                          Q(q_factor) */
     493             :     const Word16 output_frame,    /* i  : number of samples per channel in the buffer                     */
     494             :     const Word32 threshold,       /* i  : signal amplitude above which limiting starts to be applied      */
     495             :     Word16 q_factor )             /* i : q factor of output samples */
     496             : {
     497             :     Word16 i;
     498             :     Word32 **channels;
     499             :     Word16 num_channels;
     500     1126140 :     Word32 numClipping = 0;
     501     1126140 :     move32();
     502             : 
     503             :     /* return early if given bad parameters */
     504     1126140 :     test();
     505     1126140 :     test();
     506     1126140 :     IF( hLimiter == NULL || output == NULL || output_frame <= 0 )
     507             :     {
     508           0 :         return 0;
     509             :     }
     510             : 
     511     1126140 :     channels = hLimiter->channel_ptrs_fx;
     512     1126140 :     num_channels = hLimiter->num_channels;
     513     1126140 :     move16();
     514             : 
     515     7755488 :     FOR( i = 0; i < num_channels; ++i )
     516             :     {
     517     6629348 :         channels[i] = output + imult1616( i, output_frame );
     518             :     }
     519             : 
     520     1126140 :     limiter_process_fx( hLimiter, output_frame, threshold, 0, NULL, q_factor );
     521             : 
     522             :     /* Apply clipping to buffer in case the limiter let through some samples > 1.0f */
     523  2809398780 :     FOR( i = 0; i < output_frame * num_channels; ++i )
     524             :     {
     525             : 
     526  2808272640 :         output[i] = L_min( L_max( L_shl( INT16_MIN, q_factor ), output[i] ), L_shl( INT16_MAX, q_factor ) );
     527  2808272640 :         move32();
     528             :     }
     529             : 
     530     1126140 :     return numClipping;
     531             : }
     532             : #endif
     533             : 
     534             : /*-------------------------------------------------------------------*
     535             :  * validateOutputAudioConfig()
     536             :  *
     537             :  *
     538             :  *-------------------------------------------------------------------*/
     539             : 
     540         666 : static ivas_error validateOutputAudioConfig(
     541             :     const AUDIO_CONFIG outConfig )
     542             : {
     543         666 :     SWITCH( outConfig )
     544             :     {
     545         666 :         case IVAS_AUDIO_CONFIG_MONO:
     546             :         case IVAS_AUDIO_CONFIG_STEREO:
     547             :         case IVAS_AUDIO_CONFIG_5_1:
     548             :         case IVAS_AUDIO_CONFIG_7_1:
     549             :         case IVAS_AUDIO_CONFIG_5_1_2:
     550             :         case IVAS_AUDIO_CONFIG_5_1_4:
     551             :         case IVAS_AUDIO_CONFIG_7_1_4:
     552             :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
     553             :         case IVAS_AUDIO_CONFIG_FOA:
     554             :         case IVAS_AUDIO_CONFIG_HOA2:
     555             :         case IVAS_AUDIO_CONFIG_HOA3:
     556             :         case IVAS_AUDIO_CONFIG_BINAURAL:
     557             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
     558             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
     559             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
     560             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
     561             :         case IVAS_AUDIO_CONFIG_MASA1:
     562             :         case IVAS_AUDIO_CONFIG_MASA2:
     563         666 :             return IVAS_ERR_OK;
     564           0 :         default:
     565           0 :             BREAK;
     566             :     }
     567             : 
     568           0 :     return IVAS_ERR_INVALID_OUTPUT_FORMAT;
     569             : }
     570             : 
     571             : /*-------------------------------------------------------------------*
     572             :  * getAudioConfigType()
     573             :  *
     574             :  *
     575             :  *-------------------------------------------------------------------*/
     576             : 
     577     8577247 : IVAS_REND_AudioConfigType getAudioConfigType(
     578             :     const AUDIO_CONFIG config )
     579             : {
     580             :     IVAS_REND_AudioConfigType type;
     581             : 
     582     8577247 :     SWITCH( config )
     583             :     {
     584     4218502 :         case IVAS_AUDIO_CONFIG_MONO:
     585             :         case IVAS_AUDIO_CONFIG_STEREO:
     586             :         case IVAS_AUDIO_CONFIG_5_1:
     587             :         case IVAS_AUDIO_CONFIG_7_1:
     588             :         case IVAS_AUDIO_CONFIG_5_1_2:
     589             :         case IVAS_AUDIO_CONFIG_5_1_4:
     590             :         case IVAS_AUDIO_CONFIG_7_1_4:
     591             :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
     592     4218502 :             type = IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED;
     593     4218502 :             move16();
     594     4218502 :             BREAK;
     595     1511617 :         case IVAS_AUDIO_CONFIG_FOA:
     596             :         case IVAS_AUDIO_CONFIG_HOA2:
     597             :         case IVAS_AUDIO_CONFIG_HOA3:
     598     1511617 :             type = IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS;
     599     1511617 :             move16();
     600     1511617 :             BREAK;
     601      301983 :         case IVAS_AUDIO_CONFIG_OBA:
     602      301983 :             type = IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED;
     603      301983 :             move16();
     604      301983 :             BREAK;
     605     2536040 :         case IVAS_AUDIO_CONFIG_BINAURAL:
     606             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
     607             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
     608             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
     609             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
     610     2536040 :             type = IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL;
     611     2536040 :             move16();
     612     2536040 :             BREAK;
     613        9105 :         case IVAS_AUDIO_CONFIG_MASA1:
     614             :         case IVAS_AUDIO_CONFIG_MASA2:
     615        9105 :             type = IVAS_REND_AUDIO_CONFIG_TYPE_MASA;
     616        9105 :             move16();
     617        9105 :             BREAK;
     618           0 :         default:
     619           0 :             type = IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN;
     620           0 :             move16();
     621           0 :             BREAK;
     622             :     }
     623             : 
     624     8577247 :     return type;
     625             : }
     626             : 
     627             : /*-------------------------------------------------------------------*
     628             :  * validateOutputSampleRate()
     629             :  *
     630             :  *
     631             :  *-------------------------------------------------------------------*/
     632             : 
     633         666 : static ivas_error validateOutputSampleRate(
     634             :     const Word32 sampleRate,
     635             :     const AUDIO_CONFIG outConfig )
     636             : {
     637             : 
     638         666 :     IF( NE_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) )
     639             :     {
     640             :         /* If no binaural rendering, any sampling rate is supported */
     641         478 :         return IVAS_ERR_OK;
     642             :     }
     643         188 :     ELSE IF( ( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && NE_32( sampleRate, 48000 ) )
     644             :     {
     645           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_SAMPLING_RATE, "Error: Only 48kHz output sampling rate is supported for split rendering." );
     646             :     }
     647             :     ELSE
     648             :     {
     649             : 
     650             :         /* Otherwise rendering to binaural, support the same set as IVAS decoder */
     651         188 :         SWITCH( sampleRate )
     652             :         {
     653         188 :             case 16000:
     654             :             case 32000:
     655             :             case 48000:
     656         188 :                 return IVAS_ERR_OK;
     657             :         }
     658             : 
     659           0 :         return IVAS_ERR_INVALID_SAMPLING_RATE;
     660             :     }
     661             : }
     662             : 
     663             : /*-------------------------------------------------------------------*
     664             :  * getAudioConfigNumChannels()
     665             :  *
     666             :  *
     667             :  *-------------------------------------------------------------------*/
     668             : 
     669     6102527 : ivas_error getAudioConfigNumChannels(
     670             :     const AUDIO_CONFIG config,
     671             :     Word16 *numChannels )
     672             : {
     673     6102527 :     SWITCH( config )
     674             :     {
     675     1484449 :         case IVAS_AUDIO_CONFIG_MONO:
     676             :         case IVAS_AUDIO_CONFIG_OBA:
     677             :         case IVAS_AUDIO_CONFIG_MASA1:
     678     1484449 :             *numChannels = 1;
     679     1484449 :             move16();
     680     1484449 :             BREAK;
     681     1528116 :         case IVAS_AUDIO_CONFIG_STEREO:
     682             :         case IVAS_AUDIO_CONFIG_BINAURAL:
     683             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
     684             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
     685             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
     686             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
     687             :         case IVAS_AUDIO_CONFIG_MASA2:
     688     1528116 :             *numChannels = 2;
     689     1528116 :             move16();
     690     1528116 :             BREAK;
     691      371308 :         case IVAS_AUDIO_CONFIG_FOA:
     692      371308 :             *numChannels = 4;
     693      371308 :             move16();
     694      371308 :             BREAK;
     695      403308 :         case IVAS_AUDIO_CONFIG_5_1:
     696      403308 :             *numChannels = 6;
     697      403308 :             move16();
     698      403308 :             BREAK;
     699      278307 :         case IVAS_AUDIO_CONFIG_7_1:
     700             :         case IVAS_AUDIO_CONFIG_5_1_2:
     701      278307 :             *numChannels = 8;
     702      278307 :             move16();
     703      278307 :             BREAK;
     704      365987 :         case IVAS_AUDIO_CONFIG_HOA2:
     705      365987 :             *numChannels = 9;
     706      365987 :             move16();
     707      365987 :             BREAK;
     708      149099 :         case IVAS_AUDIO_CONFIG_5_1_4:
     709      149099 :             *numChannels = 10;
     710      149099 :             move16();
     711      149099 :             BREAK;
     712     1155065 :         case IVAS_AUDIO_CONFIG_7_1_4:
     713     1155065 :             *numChannels = 12;
     714     1155065 :             move16();
     715     1155065 :             BREAK;
     716      366888 :         case IVAS_AUDIO_CONFIG_HOA3:
     717      366888 :             *numChannels = 16;
     718      366888 :             move16();
     719      366888 :             BREAK;
     720           0 :         default:
     721           0 :             return IVAS_ERR_NUM_CHANNELS_UNKNOWN;
     722             :     }
     723             : 
     724     6102527 :     move16();
     725     6102527 :     return IVAS_ERR_OK;
     726             : }
     727             : 
     728             : /*-------------------------------------------------------------------*
     729             :  * Local functions
     730             :  *-------------------------------------------------------------------*/
     731             : 
     732         713 : static ivas_error initLimiter(
     733             :     IVAS_LIMITER_HANDLE *phLimiter,
     734             :     const Word16 numChannels,
     735             :     const Word32 sampleRate )
     736             : {
     737             :     ivas_error error;
     738             : 
     739             :     /* If re-initializing with unchanged values, return early */
     740         713 :     test();
     741         713 :     test();
     742         713 :     IF( *phLimiter != NULL && EQ_16( ( *phLimiter )->num_channels, numChannels ) && EQ_32( ( *phLimiter )->sampling_rate, sampleRate ) )
     743             :     {
     744           0 :         return IVAS_ERR_OK;
     745             :     }
     746             : 
     747             :     /* Support re-init: close if already allocated */
     748         713 :     IF( *phLimiter != NULL )
     749             :     {
     750          47 :         ivas_limiter_close_fx( phLimiter );
     751             :     }
     752             : 
     753         713 :     IF( NE_32( ( error = ivas_limiter_open_fx( phLimiter, numChannels, sampleRate ) ), IVAS_ERR_OK ) )
     754             :     {
     755           0 :         return error;
     756             :     }
     757             : 
     758         713 :     return IVAS_ERR_OK;
     759             : }
     760        1038 : static LSSETUP_CUSTOM_STRUCT defaultCustomLs(
     761             :     void )
     762             : {
     763             :     LSSETUP_CUSTOM_STRUCT ls;
     764             : 
     765             :     /* Set mono by default. This simplifies initialization,
     766             :        since output config is never in an undefined state. */
     767        1038 :     ls.is_planar_setup = 1;
     768        1038 :     ls.num_spk = 1;
     769        1038 :     move16();
     770        1038 :     move16();
     771        1038 :     set32_fx( ls.ls_azimuth_fx, 0, MAX_OUTPUT_CHANNELS );
     772        1038 :     set32_fx( ls.ls_elevation_fx, 0, MAX_OUTPUT_CHANNELS );
     773        1038 :     ls.num_lfe = 0;
     774        1038 :     move16();
     775        1038 :     set16_fx( ls.lfe_idx, 0, MAX_OUTPUT_CHANNELS );
     776        1038 :     ls.separate_ch_found = 0;
     777        1038 :     move16();
     778        1038 :     set16_fx( ls.separate_ch_gains_fx, 0, MAX_OUTPUT_CHANNELS );
     779             : 
     780        1038 :     return ls;
     781             : }
     782             : 
     783             : 
     784       13041 : static ivas_error getSpeakerAzimuths_fx(
     785             :     AUDIO_CONFIG config,
     786             :     const Word32 **azimuths /* Q22 */ )
     787             : {
     788       13041 :     SWITCH( config )
     789             :     {
     790          63 :         case IVAS_AUDIO_CONFIG_MONO:
     791          63 :             *azimuths = ls_azimuth_CICP1_fx;
     792          63 :             BREAK;
     793          67 :         case IVAS_AUDIO_CONFIG_STEREO:
     794          67 :             *azimuths = ls_azimuth_CICP2_fx;
     795          67 :             BREAK;
     796        5057 :         case IVAS_AUDIO_CONFIG_5_1:
     797        5057 :             *azimuths = ls_azimuth_CICP6_fx;
     798        5057 :             BREAK;
     799         807 :         case IVAS_AUDIO_CONFIG_7_1:
     800         807 :             *azimuths = ls_azimuth_CICP12_fx;
     801         807 :             BREAK;
     802        2307 :         case IVAS_AUDIO_CONFIG_5_1_2:
     803        2307 :             *azimuths = ls_azimuth_CICP14_fx;
     804        2307 :             BREAK;
     805        2313 :         case IVAS_AUDIO_CONFIG_5_1_4:
     806        2313 :             *azimuths = ls_azimuth_CICP16_fx;
     807        2313 :             BREAK;
     808        2427 :         case IVAS_AUDIO_CONFIG_7_1_4:
     809        2427 :             *azimuths = ls_azimuth_CICP19_fx;
     810        2427 :             BREAK;
     811           0 :         default:
     812           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" );
     813             :     }
     814             : 
     815       13041 :     return IVAS_ERR_OK;
     816             : }
     817             : 
     818       13041 : static ivas_error getSpeakerElevations_fx(
     819             :     AUDIO_CONFIG config,
     820             :     const Word32 **elevations /* Q22 */ )
     821             : {
     822       13041 :     SWITCH( config )
     823             :     {
     824          63 :         case IVAS_AUDIO_CONFIG_MONO:
     825          63 :             *elevations = ls_elevation_CICP1_fx;
     826          63 :             BREAK;
     827          67 :         case IVAS_AUDIO_CONFIG_STEREO:
     828          67 :             *elevations = ls_elevation_CICP2_fx;
     829          67 :             BREAK;
     830        5057 :         case IVAS_AUDIO_CONFIG_5_1:
     831        5057 :             *elevations = ls_elevation_CICP6_fx;
     832        5057 :             BREAK;
     833         807 :         case IVAS_AUDIO_CONFIG_7_1:
     834         807 :             *elevations = ls_elevation_CICP12_fx;
     835         807 :             BREAK;
     836        2307 :         case IVAS_AUDIO_CONFIG_5_1_2:
     837        2307 :             *elevations = ls_elevation_CICP14_fx;
     838        2307 :             BREAK;
     839        2313 :         case IVAS_AUDIO_CONFIG_5_1_4:
     840        2313 :             *elevations = ls_elevation_CICP16_fx;
     841        2313 :             BREAK;
     842        2427 :         case IVAS_AUDIO_CONFIG_7_1_4:
     843        2427 :             *elevations = ls_elevation_CICP19_fx;
     844        2427 :             BREAK;
     845           0 :         default:
     846           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" );
     847             :     }
     848             : 
     849       13041 :     return IVAS_ERR_OK;
     850             : }
     851             : 
     852      273185 : static ivas_error getAmbisonicsOrder_fx(
     853             :     AUDIO_CONFIG config,
     854             :     Word16 *order )
     855             : {
     856      273185 :     SWITCH( config )
     857             :     {
     858       91071 :         case IVAS_AUDIO_CONFIG_FOA:
     859       91071 :             *order = 1;
     860       91071 :             move16();
     861       91071 :             BREAK;
     862       91057 :         case IVAS_AUDIO_CONFIG_HOA2:
     863       91057 :             *order = 2;
     864       91057 :             move16();
     865       91057 :             BREAK;
     866       91057 :         case IVAS_AUDIO_CONFIG_HOA3:
     867       91057 :             *order = 3;
     868       91057 :             move16();
     869       91057 :             BREAK;
     870           0 :         default:
     871           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unsupported audio config" );
     872             :     }
     873             : 
     874      273185 :     return IVAS_ERR_OK;
     875             : }
     876             : 
     877             : 
     878           0 : static Word16 getNumLfeChannels(
     879             :     input_mc *inputMc )
     880             : {
     881           0 :     SWITCH( inputMc->base.inConfig )
     882             :     {
     883           0 :         case IVAS_AUDIO_CONFIG_5_1:
     884             :         case IVAS_AUDIO_CONFIG_7_1:
     885             :         case IVAS_AUDIO_CONFIG_5_1_2:
     886             :         case IVAS_AUDIO_CONFIG_5_1_4:
     887             :         case IVAS_AUDIO_CONFIG_7_1_4:
     888           0 :             return 1;
     889           0 :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
     890           0 :             return inputMc->customLsInput.num_lfe;
     891           0 :         default:
     892           0 :             BREAK;
     893             :     }
     894             : 
     895           0 :     return 0;
     896             : }
     897         541 : static ivas_error getNumNonLfeChannelsInSpeakerLayout(
     898             :     AUDIO_CONFIG config,
     899             :     Word16 *numNonLfeChannels )
     900             : {
     901         541 :     SWITCH( config )
     902             :     {
     903          63 :         case IVAS_AUDIO_CONFIG_MONO:
     904          63 :             *numNonLfeChannels = 1;
     905          63 :             move16();
     906          63 :             BREAK;
     907          67 :         case IVAS_AUDIO_CONFIG_STEREO:
     908          67 :             *numNonLfeChannels = 2;
     909          67 :             move16();
     910          67 :             BREAK;
     911          57 :         case IVAS_AUDIO_CONFIG_5_1:
     912          57 :             *numNonLfeChannels = 5;
     913          57 :             move16();
     914          57 :             BREAK;
     915         114 :         case IVAS_AUDIO_CONFIG_5_1_2:
     916             :         case IVAS_AUDIO_CONFIG_7_1:
     917         114 :             *numNonLfeChannels = 7;
     918         114 :             move16();
     919         114 :             BREAK;
     920          63 :         case IVAS_AUDIO_CONFIG_5_1_4:
     921          63 :             *numNonLfeChannels = 9;
     922          63 :             move16();
     923          63 :             BREAK;
     924         177 :         case IVAS_AUDIO_CONFIG_7_1_4:
     925         177 :             *numNonLfeChannels = 11;
     926         177 :             move16();
     927         177 :             BREAK;
     928           0 :         default:
     929           0 :             return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Unexpected audio config" );
     930             :     }
     931             : 
     932         541 :     return IVAS_ERR_OK;
     933             : }
     934       25504 : static ivas_error getMcConfigValues_fx(
     935             :     AUDIO_CONFIG inConfig,
     936             :     const LSSETUP_CUSTOM_STRUCT *pInCustomLs,
     937             :     const Word32 **azimuth,   /* Q22 */
     938             :     const Word32 **elevation, /* Q22 */
     939             :     Word16 *lfe_idx,
     940             :     Word16 *is_planar )
     941             : {
     942             :     Word16 i;
     943             :     ivas_error error;
     944             : 
     945       25504 :     *lfe_idx = -1;
     946       25504 :     *is_planar = 1;
     947       25504 :     move16();
     948       25504 :     move16();
     949       25504 :     SWITCH( inConfig )
     950             :     {
     951       13004 :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
     952       13004 :             *azimuth = (const Word32 *) &pInCustomLs->ls_azimuth_fx;
     953       13004 :             *elevation = (const Word32 *) &pInCustomLs->ls_elevation_fx;
     954       13004 :             IF( pInCustomLs->num_lfe > 0 )
     955             :             {
     956           0 :                 *lfe_idx = pInCustomLs->lfe_idx[0];
     957           0 :                 move16();
     958             :             }
     959       99036 :             FOR( i = 0; i < pInCustomLs->num_spk; i++ )
     960             :             {
     961       99036 :                 IF( pInCustomLs->ls_elevation_fx[i] != 0 )
     962             :                 {
     963       13004 :                     *is_planar = 0;
     964       13004 :                     move16();
     965       13004 :                     BREAK;
     966             :                 }
     967             :             }
     968       13004 :             BREAK;
     969           0 :         case IVAS_AUDIO_CONFIG_MONO:
     970             :         case IVAS_AUDIO_CONFIG_STEREO:
     971           0 :             IF( NE_32( ( error = getSpeakerAzimuths_fx( inConfig, azimuth ) ), IVAS_ERR_OK ) )
     972             :             {
     973           0 :                 return error;
     974             :             }
     975           0 :             IF( NE_32( error = getSpeakerElevations_fx( inConfig, elevation ), IVAS_ERR_OK ) )
     976             :             {
     977           0 :                 return error;
     978             :             }
     979           0 :             BREAK;
     980       12500 :         case IVAS_AUDIO_CONFIG_5_1:
     981             :         case IVAS_AUDIO_CONFIG_7_1:
     982             :         case IVAS_AUDIO_CONFIG_5_1_2:
     983             :         case IVAS_AUDIO_CONFIG_5_1_4:
     984             :         case IVAS_AUDIO_CONFIG_7_1_4:
     985       12500 :             IF( NE_32( ( error = getSpeakerAzimuths_fx( inConfig, azimuth ) ), IVAS_ERR_OK ) )
     986             :             {
     987           0 :                 return error;
     988             :             }
     989       12500 :             IF( NE_32( ( error = getSpeakerElevations_fx( inConfig, elevation ) ), IVAS_ERR_OK ) )
     990             :             {
     991           0 :                 return error;
     992             :             }
     993       12500 :             *lfe_idx = LFE_CHANNEL;
     994       12500 :             move16();
     995             : 
     996       12500 :             test();
     997       12500 :             IF( EQ_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) )
     998             :             {
     999        5750 :                 *is_planar = 1;
    1000        5750 :                 move16();
    1001             :             }
    1002             :             ELSE
    1003             :             {
    1004        6750 :                 *is_planar = 0;
    1005        6750 :                 move16();
    1006             :             }
    1007       12500 :             BREAK;
    1008           0 :         default:
    1009           0 :             assert( !"Invalid speaker config" );
    1010             :             return IVAS_ERR_WRONG_PARAMS;
    1011             :     }
    1012             : 
    1013       25504 :     return IVAS_ERR_OK;
    1014             : }
    1015         848 : static ivas_error initEfap(
    1016             :     EFAP_WRAPPER *pEfapWrapper,
    1017             :     AUDIO_CONFIG outConfig,
    1018             :     const LSSETUP_CUSTOM_STRUCT *pCustomLsOut )
    1019             : {
    1020             :     ivas_error error;
    1021             :     const Word32 *azimuths;   /* Q22 */
    1022             :     const Word32 *elevations; /* Q22 */
    1023             :     Word16 numNonLfeChannels;
    1024             : 
    1025         848 :     test();
    1026         848 :     IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
    1027             :     {
    1028         120 :         pEfapWrapper->speakerConfig = IVAS_AUDIO_CONFIG_7_1_4;
    1029         120 :         move32();
    1030             :     }
    1031             :     ELSE
    1032             :     {
    1033         728 :         pEfapWrapper->speakerConfig = outConfig;
    1034         728 :         move32();
    1035             :     }
    1036         848 :     pEfapWrapper->pCustomLsSetup = pCustomLsOut;
    1037             : 
    1038             :     /* If re-initializing, free existing EFAP handle. */
    1039         848 :     IF( pEfapWrapper->hEfap != NULL )
    1040             :     {
    1041          47 :         efap_free_data_fx( &pEfapWrapper->hEfap );
    1042             :     }
    1043             : 
    1044             :     /* Only initialize EFAP handle if output config is channel-based */
    1045         848 :     IF( NE_32( getAudioConfigType( pEfapWrapper->speakerConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    1046             :     {
    1047         195 :         pEfapWrapper->hEfap = NULL;
    1048         195 :         return IVAS_ERR_OK;
    1049             :     }
    1050             : 
    1051         653 :     IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1052             :     {
    1053         199 :         IF( NE_32( ( error = efap_init_data_fx( &pEfapWrapper->hEfap, pCustomLsOut->ls_azimuth_fx, pCustomLsOut->ls_elevation_fx, pCustomLsOut->num_spk, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) )
    1054             :         {
    1055           0 :             return error;
    1056             :         }
    1057             :     }
    1058             :     ELSE
    1059             :     {
    1060         454 :         IF( NE_32( ( error = getSpeakerAzimuths_fx( pEfapWrapper->speakerConfig, &azimuths ) ), IVAS_ERR_OK ) )
    1061             :         {
    1062           0 :             return error;
    1063             :         }
    1064             : 
    1065         454 :         IF( NE_32( ( error = getSpeakerElevations_fx( pEfapWrapper->speakerConfig, &elevations ) ), IVAS_ERR_OK ) )
    1066             :         {
    1067           0 :             return error;
    1068             :         }
    1069             : 
    1070         454 :         IF( NE_32( ( error = getNumNonLfeChannelsInSpeakerLayout( pEfapWrapper->speakerConfig, &numNonLfeChannels ) ), IVAS_ERR_OK ) )
    1071             :         {
    1072           0 :             return error;
    1073             :         }
    1074         454 :         IF( NE_32( ( error = efap_init_data_fx( &pEfapWrapper->hEfap, azimuths, elevations, numNonLfeChannels, EFAP_MODE_EFAP ) ), IVAS_ERR_OK ) )
    1075             :         {
    1076           0 :             return error;
    1077             :         }
    1078             :     }
    1079             : 
    1080         653 :     return IVAS_ERR_OK;
    1081             : }
    1082             : 
    1083      423262 : static ivas_error getEfapGains_fx(
    1084             :     EFAP_WRAPPER efapWrapper,
    1085             :     const Word32 azi, /* Q22 */
    1086             :     const Word32 ele, /* Q22 */
    1087             :     pan_vector_fx panGains /* Q31 */ )
    1088             : {
    1089             :     pan_vector_fx tmpPanGains; /* tmp pan gain buffer without LFE channels */ /* Q30 */
    1090             :     Word32 *readPtr;
    1091             :     Word16 i;
    1092             :     Word16 lfeCount;
    1093             :     Word16 numChannels;
    1094             :     ivas_error error;
    1095             : 
    1096             :     /* EFAP returns an array of gains only for non-LFE speakers */
    1097      423262 :     efap_determine_gains_fx( efapWrapper.hEfap, tmpPanGains, azi, ele, EFAP_MODE_EFAP );
    1098             : 
    1099             :     /* Now copy to buffer that includes LFE channels */
    1100      423262 :     IF( EQ_32( efapWrapper.speakerConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1101             :     {
    1102       29835 :         numChannels = add( efapWrapper.pCustomLsSetup->num_spk, efapWrapper.pCustomLsSetup->num_lfe );
    1103       29835 :         readPtr = tmpPanGains;
    1104       29835 :         lfeCount = 0;
    1105       29835 :         move16();
    1106      387823 :         FOR( i = 0; i < numChannels; ++i )
    1107             :         {
    1108      357988 :             test();
    1109      357988 :             IF( LT_16( lfeCount, efapWrapper.pCustomLsSetup->num_lfe ) && EQ_16( i, efapWrapper.pCustomLsSetup->lfe_idx[lfeCount] ) )
    1110             :             {
    1111           0 :                 panGains[i] = 0;
    1112           0 :                 move32();
    1113           0 :                 lfeCount = add( lfeCount, 1 );
    1114             :             }
    1115             :             ELSE
    1116             :             {
    1117      357988 :                 IF( EQ_32( *readPtr, ONE_IN_Q30 ) )
    1118             :                 {
    1119           0 :                     panGains[i] = ONE_IN_Q31;
    1120             :                 }
    1121             :                 ELSE
    1122             :                 {
    1123      357988 :                     panGains[i] = L_shl( *readPtr, 1 );
    1124             :                 }
    1125      357988 :                 move32();
    1126      357988 :                 ++readPtr;
    1127             :             }
    1128             :         }
    1129             :     }
    1130             :     ELSE
    1131             :     {
    1132      393427 :         IF( NE_32( ( error = getAudioConfigNumChannels( efapWrapper.speakerConfig, &numChannels ) ), IVAS_ERR_OK ) )
    1133             :         {
    1134           0 :             return error;
    1135             :         }
    1136             : 
    1137      393427 :         readPtr = tmpPanGains;
    1138             : 
    1139     4311225 :         FOR( i = 0; i < numChannels; ++i )
    1140             :         {
    1141     3917798 :             IF( EQ_16( i, LFE_CHANNEL ) )
    1142             :             {
    1143      363625 :                 panGains[i] = 0;
    1144      363625 :                 move32();
    1145             :             }
    1146             :             ELSE
    1147             :             {
    1148     3554173 :                 IF( GE_32( *readPtr, ONE_IN_Q30 ) )
    1149             :                 {
    1150       14998 :                     panGains[i] = ONE_IN_Q31;
    1151             :                 }
    1152             :                 ELSE
    1153             :                 {
    1154     3539175 :                     panGains[i] = L_shl( *readPtr, 1 );
    1155             :                 }
    1156             : 
    1157     3554173 :                 move32();
    1158     3554173 :                 ++readPtr;
    1159             :             }
    1160             :         }
    1161             :     }
    1162             : 
    1163      423262 :     return IVAS_ERR_OK;
    1164             : }
    1165             : 
    1166          94 : static ivas_error initHeadRotation_fx(
    1167             :     IVAS_REND_HANDLE hIvasRend )
    1168             : {
    1169             :     Word16 i, crossfade_len;
    1170             :     Word32 tmp_fx; /* Q31 */
    1171             :     ivas_error error;
    1172             : 
    1173             :     /* Head rotation is enabled by default */
    1174          94 :     hIvasRend->headRotData.headRotEnabled = 1;
    1175          94 :     move16();
    1176             : 
    1177             :     /* Initialize 5ms crossfade */
    1178          94 :     crossfade_len = L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES;
    1179          94 :     move16();
    1180          94 :     tmp_fx = Q31_BY_SUB_FRAME_240;
    1181          94 :     move16();
    1182             : 
    1183       22654 :     FOR( i = 0; i < crossfade_len; i++ )
    1184             :     {
    1185       22560 :         hIvasRend->headRotData.crossfade_fx[i] = UL_Mpy_32_32( i, tmp_fx );
    1186       22560 :         move32();
    1187             :     }
    1188             : 
    1189             :     /* Initialize with unit quaternions */
    1190         329 :     FOR( i = 0; i < hIvasRend->num_subframes; ++i )
    1191             :     {
    1192         235 :         hIvasRend->headRotData.headPositions[i] = quaternionInit_fx();
    1193             :     }
    1194             : 
    1195          94 :     hIvasRend->headRotData.sr_pose_pred_axis = DEFAULT_AXIS;
    1196          94 :     move32();
    1197             : 
    1198          94 :     IF( ( hIvasRend->headRotData.hOrientationTracker = (ivas_orient_trk_state_t *) malloc( sizeof( ivas_orient_trk_state_t ) ) ) == NULL )
    1199             :     {
    1200           0 :         return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Orientation tracking" );
    1201             :     }
    1202             : 
    1203          94 :     IF( NE_32( ( error = ivas_orient_trk_Init_fx( hIvasRend->headRotData.hOrientationTracker ) ), IVAS_ERR_OK ) )
    1204             :     {
    1205           0 :         return error;
    1206             :     }
    1207             : 
    1208          94 :     return IVAS_ERR_OK;
    1209             : }
    1210             : 
    1211             : 
    1212         666 : static void closeHeadRotation(
    1213             :     IVAS_REND_HANDLE hIvasRend )
    1214             : {
    1215         666 :     test();
    1216             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    1217         666 :     test();
    1218         666 :     IF( hIvasRend != NULL && hIvasRend->headRotData.headRotEnabled && hIvasRend->headRotData.hOrientationTracker != NULL )
    1219             : #else
    1220             :     IF( ( hIvasRend != NULL ) && ( hIvasRend->headRotData.hOrientationTracker != NULL ) )
    1221             : #endif
    1222             :     {
    1223          94 :         free( hIvasRend->headRotData.hOrientationTracker );
    1224             :     }
    1225             : 
    1226         666 :     return;
    1227             : }
    1228             : 
    1229             : 
    1230         426 : static void initRotMatrix_fx(
    1231             :     rotation_matrix_fx rot_mat )
    1232             : {
    1233             :     Word16 i;
    1234             : 
    1235             :     /* Initialize rotation matrices */
    1236        1704 :     FOR( i = 0; i < 3; i++ )
    1237             :     {
    1238        1278 :         set_zero_fx( rot_mat[i], 3 );
    1239        1278 :         rot_mat[i][i] = ONE_IN_Q30;
    1240        1278 :         move32();
    1241             :     }
    1242             : 
    1243         426 :     return;
    1244             : }
    1245             : 
    1246        1008 : static void initRotGains_fx(
    1247             :     rotation_gains_fx rot_gains )
    1248             : {
    1249             :     Word16 i;
    1250             : 
    1251             :     /* Set gains to passthrough */
    1252       17136 :     FOR( i = 0; i < MAX_INPUT_CHANNELS; i++ )
    1253             :     {
    1254       16128 :         set16_fx( rot_gains[i], 0, MAX_INPUT_CHANNELS );
    1255       16128 :         rot_gains[i][i] = ONE_IN_Q14;
    1256       16128 :         move16();
    1257             :     }
    1258             : 
    1259        1008 :     return;
    1260             : }
    1261             : 
    1262        2976 : static void initRotGainsWord32_fx(
    1263             :     rotation_gains_Word32 rot_gains )
    1264             : {
    1265             :     Word16 i;
    1266             : 
    1267             :     /* Set gains to passthrough */
    1268       50592 :     FOR( i = 0; i < MAX_INPUT_CHANNELS; i++ )
    1269             :     {
    1270       47616 :         set32_fx( rot_gains[i], 0, MAX_INPUT_CHANNELS );
    1271       47616 :         rot_gains[i][i] = ONE_IN_Q30;
    1272       47616 :         move16();
    1273             :     }
    1274             : 
    1275        2976 :     return;
    1276             : }
    1277       10297 : static void initRendInputBase_fx(
    1278             :     input_base *inputBase,
    1279             :     const AUDIO_CONFIG inConfig,
    1280             :     const IVAS_REND_InputId id,
    1281             :     const rendering_context rendCtx,
    1282             :     Word32 *dataBuf,
    1283             :     const Word16 dataBufSize )
    1284             : {
    1285       10297 :     inputBase->inConfig = inConfig;
    1286       10297 :     move32();
    1287       10297 :     inputBase->id = id;
    1288       10297 :     move16();
    1289       10297 :     inputBase->gain_fx = ONE_IN_Q30;
    1290       10297 :     move32();
    1291       10297 :     inputBase->ctx = rendCtx;
    1292       10297 :     inputBase->numNewSamplesPerChannel = 0;
    1293       10297 :     move32();
    1294             : 
    1295       10297 :     inputBase->inputBuffer.config.numSamplesPerChannel = 0;
    1296       10297 :     inputBase->inputBuffer.config.numChannels = 0;
    1297       10297 :     move16();
    1298       10297 :     move16();
    1299       10297 :     inputBase->inputBuffer.data_fx = dataBuf;
    1300       10297 :     IF( inputBase->inputBuffer.data_fx != NULL )
    1301             :     {
    1302         973 :         set32_fx( inputBase->inputBuffer.data_fx, 0, dataBufSize );
    1303             :     }
    1304             : 
    1305       10297 :     return;
    1306             : }
    1307             : 
    1308      300852 : static IVAS_ISM_METADATA defaultObjectPosition(
    1309             :     void )
    1310             : {
    1311             :     IVAS_ISM_METADATA pos;
    1312             : 
    1313      300852 :     pos.azimuth_fx = 0;
    1314      300852 :     move32();
    1315      300852 :     pos.elevation_fx = 0;
    1316      300852 :     move32();
    1317      300852 :     pos.radius_fx = ONE_IN_Q9;
    1318      300852 :     move16();
    1319      300852 :     pos.spread_fx = 0;
    1320      300852 :     move32();
    1321      300852 :     pos.gainFactor_fx = ONE_IN_Q31;
    1322      300852 :     move32();
    1323      300852 :     pos.yaw_fx = 0;
    1324      300852 :     move32();
    1325      300852 :     pos.pitch_fx = 0;
    1326      300852 :     move32();
    1327      300852 :     return pos;
    1328             : }
    1329             : 
    1330             : 
    1331      947155 : static Word8 checkObjectPositionChanged_fx(
    1332             :     IVAS_ISM_METADATA *currentPos,
    1333             :     IVAS_ISM_METADATA *previousPos )
    1334             : {
    1335      947155 :     test();
    1336     1555417 :     return !( LT_32( L_abs( L_sub( currentPos->azimuth_fx, previousPos->azimuth_fx ) ), EPSILLON_FX ) &&
    1337      608262 :               LT_32( L_abs( L_sub( currentPos->elevation_fx, previousPos->elevation_fx ) ), EPSILLON_FX ) );
    1338             : }
    1339             : 
    1340        4662 : static rendering_context getRendCtx(
    1341             :     IVAS_REND_HANDLE hIvasRend )
    1342             : {
    1343             :     rendering_context ctx;
    1344             : 
    1345             :     /* Note: when refactoring this, always take the ADDRESS of a member of the
    1346             :      * renderer struct, so that the context stores a POINTER to the member, even
    1347             :      * if the member is a pointer or handle itself. */
    1348        4662 :     ctx.pOutConfig = &hIvasRend->outputConfig;
    1349        4662 :     ctx.pOutSampleRate = &hIvasRend->sampleRateOut;
    1350        4662 :     ctx.pCustomLsOut = &hIvasRend->customLsOut;
    1351        4662 :     ctx.pEfapOutWrapper = &hIvasRend->efapOutWrapper;
    1352        4662 :     ctx.pHeadRotData = &hIvasRend->headRotData;
    1353        4662 :     ctx.hhRendererConfig = &hIvasRend->hRendererConfig;
    1354        4662 :     ctx.pSplitRendBFI = &hIvasRend->splitRendBFI;
    1355        4662 :     ctx.pSplitRendWrapper = hIvasRend->splitRendWrapper;
    1356        4662 :     ctx.pCombinedOrientationData = &hIvasRend->hCombinedOrientationData;
    1357             : 
    1358        4662 :     return ctx;
    1359             : }
    1360             : 
    1361             : 
    1362         798 : static TDREND_WRAPPER defaultTdRendWrapper(
    1363             :     void )
    1364             : {
    1365             :     TDREND_WRAPPER w;
    1366             : 
    1367         798 :     w.binaural_latency_ns = 0;
    1368         798 :     move32();
    1369         798 :     w.hBinRendererTd = NULL;
    1370         798 :     w.hHrtfTD = NULL;
    1371             : 
    1372         798 :     return w;
    1373             : }
    1374             : 
    1375             : 
    1376         973 : static bool isIoConfigPairSupported(
    1377             :     const AUDIO_CONFIG inConfig,
    1378             :     const AUDIO_CONFIG outConfig )
    1379             : {
    1380             :     /* Rendering mono or stereo to binaural is not supported */
    1381         973 :     test();
    1382         973 :     test();
    1383         973 :     IF( ( EQ_32( inConfig, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_STEREO ) ) && EQ_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) )
    1384             :     {
    1385           0 :         return false;
    1386             :     }
    1387             : 
    1388             :     /* If not returned so far, config pair is supported */
    1389         973 :     return true;
    1390             : }
    1391             : 
    1392           1 : static ivas_error initIsmMasaRendering(
    1393             :     input_ism *inputIsm,
    1394             :     const Word32 inSampleRate )
    1395             : {
    1396             :     ivas_error error;
    1397             :     Word16 num_poses;
    1398             : 
    1399           1 :     num_poses = 1;
    1400           1 :     move16();
    1401           1 :     if ( inputIsm->base.ctx.pSplitRendWrapper != NULL )
    1402             :     {
    1403           0 :         num_poses = inputIsm->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    1404           0 :         move16();
    1405             :     }
    1406             : 
    1407           1 :     IF( inputIsm->tdRendWrapper.hBinRendererTd != NULL )
    1408             :     {
    1409           0 :         ivas_td_binaural_close_fx( &inputIsm->tdRendWrapper.hBinRendererTd );
    1410             :     }
    1411             : 
    1412           1 :     ivas_rend_closeCrend( &inputIsm->crendWrapper, num_poses );
    1413             : 
    1414           1 :     ivas_reverb_close( &inputIsm->hReverb );
    1415             : 
    1416           1 :     IF( NE_32( ( error = ivas_omasa_ana_open( &inputIsm->hOMasa, inSampleRate, inputIsm->total_num_objects ) ), IVAS_ERR_OK ) )
    1417             :     {
    1418           0 :         return error;
    1419             :     }
    1420             : 
    1421           1 :     return IVAS_ERR_OK;
    1422             : }
    1423             : 
    1424             : 
    1425         426 : static ivas_error setRendInputActiveIsm(
    1426             :     void *input,
    1427             :     const AUDIO_CONFIG inConfig,
    1428             :     const IVAS_REND_InputId id,
    1429             :     RENDER_CONFIG_DATA *hRendCfg,
    1430             :     hrtf_handles *hrtfs )
    1431             : {
    1432             :     ivas_error error;
    1433             :     rendering_context rendCtx;
    1434             :     AUDIO_CONFIG outConfig;
    1435             :     input_ism *inputIsm;
    1436             :     Word16 i;
    1437             :     Word16 SrcInd[MAX_NUM_TDREND_CHANNELS];
    1438             :     Word16 num_src;
    1439             :     Word16 ivas_format;
    1440             :     Word16 num_poses;
    1441             : 
    1442         426 :     IF( EQ_32( getAudioConfigType( inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    1443             :     {
    1444           0 :         ivas_format = MC_FORMAT;
    1445             :     }
    1446             :     ELSE
    1447             :     {
    1448         426 :         ivas_format = ISM_FORMAT;
    1449             :     }
    1450             : 
    1451         426 :     inputIsm = (input_ism *) input;
    1452         426 :     rendCtx = inputIsm->base.ctx;
    1453         426 :     outConfig = *rendCtx.pOutConfig;
    1454             : 
    1455         426 :     num_poses = 1;
    1456         426 :     move16();
    1457         426 :     if ( rendCtx.pSplitRendWrapper != NULL )
    1458             :     {
    1459           0 :         num_poses = rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses;
    1460           0 :         move16();
    1461             :     }
    1462             : 
    1463         426 :     IF( !isIoConfigPairSupported( inConfig, outConfig ) )
    1464             :     {
    1465           0 :         return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED;
    1466             :     }
    1467             : 
    1468         426 :     IF( NE_32( ( error = allocateInputBaseBufferData_fx( &inputIsm->bufferData_fx, MAX_BUFFER_LENGTH ) ), IVAS_ERR_OK ) )
    1469             :     {
    1470           0 :         return error;
    1471             :     }
    1472         426 :     initRendInputBase_fx( &inputIsm->base, inConfig, id, rendCtx, inputIsm->bufferData_fx, MAX_BUFFER_LENGTH );
    1473             : 
    1474         426 :     inputIsm->firstFrameRendered = FALSE;
    1475         426 :     move16();
    1476             : 
    1477         426 :     inputIsm->currentPos = defaultObjectPosition();
    1478         426 :     inputIsm->previousPos = defaultObjectPosition();
    1479         426 :     inputIsm->crendWrapper = NULL;
    1480         426 :     inputIsm->hReverb = NULL;
    1481         426 :     inputIsm->tdRendWrapper = defaultTdRendWrapper();
    1482             : 
    1483         426 :     initRotMatrix_fx( inputIsm->rot_mat_prev );
    1484             : 
    1485         426 :     set_zero_fx( inputIsm->prev_pan_gains_fx, MAX_OUTPUT_CHANNELS );
    1486             : 
    1487        3408 :     FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    1488             :     {
    1489        2982 :         inputIsm->splitTdRendWrappers[i].hHrtfTD = &hrtfs->hHrtfTD;
    1490             :     }
    1491             : 
    1492         426 :     inputIsm->hOMasa = NULL;
    1493             : 
    1494         426 :     error = IVAS_ERR_OK;
    1495         426 :     move32();
    1496             : 
    1497         426 :     inputIsm->tdRendWrapper.hHrtfTD = &hrtfs->hHrtfTD;
    1498             : 
    1499         426 :     test();
    1500         426 :     test();
    1501         426 :     test();
    1502         426 :     IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    1503          40 :     {
    1504          40 :         IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) )
    1505             :         {
    1506           0 :             return error;
    1507             :         }
    1508             : 
    1509          40 :         Word16 nchan_rend = num_src;
    1510          40 :         move16();
    1511             : 
    1512          40 :         test();
    1513          40 :         IF( EQ_16( ivas_format, MC_FORMAT ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1514             :         {
    1515           0 :             nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */
    1516             :         }
    1517             : 
    1518          80 :         FOR( Word16 nS = 0; nS < nchan_rend; nS++ )
    1519             :         {
    1520          40 :             TDREND_SRC_t *Src_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[SrcInd[nS]];
    1521          40 :             IF( Src_p != NULL )
    1522             :             {
    1523          40 :                 IF( Src_p->SrcSpatial_p != NULL )
    1524             :                 {
    1525          40 :                     Src_p->SrcSpatial_p->q_Pos_p = Q31;
    1526          40 :                     move16();
    1527             :                 }
    1528          40 :                 TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[nS]->SrcSpatial_p;
    1529          40 :                 SrcSpatial_p->q_Pos_p = Q31;
    1530          40 :                 move16();
    1531             :             }
    1532             :         }
    1533             : 
    1534             :         /* Open TD renderer wrappers */
    1535         320 :         FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    1536             :         {
    1537         280 :             IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputIsm->splitTdRendWrappers[i], inConfig, hRendCfg, NULL, *inputIsm->base.ctx.pOutSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) )
    1538             :             {
    1539           0 :                 return error;
    1540             :             }
    1541             : 
    1542             :             /* Assert same delay as main TD renderer */
    1543         280 :             assert( inputIsm->splitTdRendWrappers[i].binaural_latency_ns == inputIsm->tdRendWrapper.binaural_latency_ns );
    1544             : 
    1545         560 :             FOR( Word16 nS = 0; nS < nchan_rend; nS++ )
    1546             :             {
    1547         280 :                 TDREND_SRC_t *Src_p = inputIsm->splitTdRendWrappers[i].hBinRendererTd->Sources[SrcInd[nS]];
    1548         280 :                 IF( Src_p != NULL )
    1549             :                 {
    1550         280 :                     IF( Src_p->SrcSpatial_p != NULL )
    1551             :                     {
    1552         280 :                         Src_p->SrcSpatial_p->q_Pos_p = Q31;
    1553         280 :                         move16();
    1554             :                     }
    1555         280 :                     TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputIsm->splitTdRendWrappers[i].hBinRendererTd->Sources[nS]->SrcSpatial_p;
    1556         280 :                     SrcSpatial_p->q_Pos_p = Q31;
    1557         280 :                     move16();
    1558             :                 }
    1559             :             }
    1560             :         }
    1561             :     }
    1562         386 :     ELSE IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA2 ) )
    1563             :     {
    1564           1 :         IF( NE_32( ( error = initIsmMasaRendering( inputIsm, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    1565             :         {
    1566           0 :             return error;
    1567             :         }
    1568             :     }
    1569             :     ELSE
    1570             :     {
    1571         385 :         IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) )
    1572             :         {
    1573           0 :             return error;
    1574             :         }
    1575             : 
    1576         385 :         Word16 nchan_rend = num_src;
    1577         385 :         move16();
    1578             : 
    1579         385 :         test();
    1580         385 :         IF( EQ_16( ivas_format, MC_FORMAT ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1581             :         {
    1582           0 :             nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */
    1583             :         }
    1584             : 
    1585         770 :         FOR( Word16 nS = 0; nS < nchan_rend; nS++ )
    1586             :         {
    1587         385 :             TDREND_SRC_t *Src_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[SrcInd[nS]];
    1588         385 :             IF( Src_p != NULL )
    1589             :             {
    1590         385 :                 IF( Src_p->SrcSpatial_p != NULL )
    1591             :                 {
    1592         385 :                     Src_p->SrcSpatial_p->q_Pos_p = Q31;
    1593         385 :                     move16();
    1594             :                 }
    1595         385 :                 TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputIsm->tdRendWrapper.hBinRendererTd->Sources[nS]->SrcSpatial_p;
    1596         385 :                 SrcSpatial_p->q_Pos_p = Q31;
    1597         385 :                 move16();
    1598             :             }
    1599             :         }
    1600             : 
    1601         385 :         IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
    1602             :         {
    1603          40 :             IF( NE_32( ( error = ivas_reverb_open_fx( &( inputIsm->hReverb ), hrtfs->hHrtfStatistics, hRendCfg, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    1604             :             {
    1605           0 :                 return error;
    1606             :             }
    1607             :         }
    1608         345 :         ELSE IF( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR )
    1609             :         {
    1610          40 :             IF( NE_32( ( error = ivas_rend_openCrend( &inputIsm->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, hrtfs->hSetOfHRTF, hrtfs->hHrtfStatistics, *rendCtx.pOutSampleRate, num_poses ) ), IVAS_ERR_OK ) )
    1611             :             {
    1612           0 :                 return error;
    1613             :             }
    1614             :         }
    1615             :     }
    1616             : 
    1617         426 :     return IVAS_ERR_OK;
    1618             : }
    1619             : 
    1620        2664 : static void clearInputIsm(
    1621             :     input_ism *inputIsm )
    1622             : {
    1623             :     rendering_context rendCtx;
    1624             :     Word16 i, num_poses;
    1625             : 
    1626        2664 :     num_poses = 1;
    1627        2664 :     move16();
    1628        2664 :     if ( inputIsm->base.ctx.pSplitRendWrapper != NULL )
    1629             :     {
    1630           0 :         num_poses = inputIsm->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    1631           0 :         move16();
    1632             :     }
    1633             : 
    1634        2664 :     rendCtx = inputIsm->base.ctx;
    1635             : 
    1636        2664 :     freeInputBaseBufferData_fx( &inputIsm->base.inputBuffer.data_fx );
    1637             : 
    1638        2664 :     initRendInputBase_fx( &inputIsm->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 );
    1639             : 
    1640             :     /* Free input's internal handles */
    1641        2664 :     ivas_rend_closeCrend( &inputIsm->crendWrapper, num_poses );
    1642             : 
    1643        2664 :     ivas_reverb_close( &inputIsm->hReverb );
    1644             : 
    1645        2664 :     IF( inputIsm->tdRendWrapper.hBinRendererTd != NULL )
    1646             :     {
    1647         425 :         ivas_td_binaural_close_fx( &inputIsm->tdRendWrapper.hBinRendererTd );
    1648             :     }
    1649             : 
    1650       21312 :     FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    1651             :     {
    1652       18648 :         ivas_td_binaural_close_fx( &inputIsm->splitTdRendWrappers[i].hBinRendererTd );
    1653             :     }
    1654             : 
    1655        2664 :     ivas_omasa_ana_close( &( inputIsm->hOMasa ) );
    1656             : 
    1657        2664 :     return;
    1658             : }
    1659             : 
    1660          62 : static void copyLsConversionMatrixToPanMatrix_fx(
    1661             :     const LS_CONVERSION_MATRIX_FX *lsConvMatrix,
    1662             :     pan_matrix_fx panMatrix )
    1663             : {
    1664             :     Word16 i;
    1665             :     Word16 inCh, outCh;
    1666             :     Word16 numNonZeroGains;
    1667             :     Word16 numColumns;
    1668             :     Word16 tmp_e, tmp;
    1669             :     /* Index 0 is special and describes the following values */
    1670          62 :     numNonZeroGains = lsConvMatrix[0].index;
    1671          62 :     move16();
    1672          62 :     numColumns = (Word16) lsConvMatrix[0].value;
    1673          62 :     move16();
    1674             : 
    1675         654 :     FOR( i = 1; i < numNonZeroGains + 1; ++i )
    1676             :     {
    1677         592 :         tmp = BASOP_Util_Divide1616_Scale( lsConvMatrix[i].index, numColumns, &tmp_e );
    1678         592 :         move16();
    1679         592 :         tmp = shr( tmp, add( 15, negate( tmp_e ) ) );
    1680         592 :         move16();
    1681         592 :         inCh = tmp;
    1682         592 :         move16();
    1683             :         // inCh = lsConvMatrix[i].index / numColumns;
    1684         592 :         outCh = lsConvMatrix[i].index % numColumns;
    1685         592 :         move16();
    1686             : 
    1687         592 :         IF( EQ_32( lsConvMatrix[i].value, ONE_IN_Q30 ) )
    1688             :         {
    1689         492 :             panMatrix[inCh][outCh] = ONE_IN_Q31;
    1690             :         }
    1691             :         ELSE
    1692             :         {
    1693         100 :             panMatrix[inCh][outCh] = L_shl( lsConvMatrix[i].value, 1 ); /* Q30 + Q1 = Q31 */
    1694             :         }
    1695         592 :         move32();
    1696             :     }
    1697             : 
    1698          62 :     return;
    1699             : }
    1700             : 
    1701        1101 : static void setZeroPanMatrix_fx(
    1702             :     pan_matrix_fx panMatrix )
    1703             : {
    1704             :     Word16 i;
    1705             : 
    1706       18717 :     FOR( i = 0; i < MAX_INPUT_CHANNELS; ++i )
    1707             :     {
    1708       17616 :         set32_fx( panMatrix[i], 0, MAX_OUTPUT_CHANNELS );
    1709             :     }
    1710             : 
    1711        1101 :     return;
    1712             : }
    1713             : 
    1714             : /* Note: this only sets non-zero elements, call setZeroPanMatrix() to init first. */
    1715          91 : static void fillIdentityPanMatrix_fx(
    1716             :     pan_matrix_fx panMatrix )
    1717             : {
    1718             :     Word16 i;
    1719             : 
    1720        1547 :     FOR( i = 0; i < s_min( MAX_INPUT_CHANNELS, MAX_OUTPUT_CHANNELS ); ++i )
    1721             :     {
    1722        1456 :         panMatrix[i][i] = ONE_IN_Q31;
    1723        1456 :         move32();
    1724             :     }
    1725             : 
    1726          91 :     return;
    1727             : }
    1728             : 
    1729          29 : static ivas_error initMcPanGainsWithIdentMatrix(
    1730             :     input_mc *inputMc )
    1731             : {
    1732          29 :     fillIdentityPanMatrix_fx( inputMc->panGains_fx );
    1733             : 
    1734          29 :     return IVAS_ERR_OK;
    1735             : }
    1736             : 
    1737         100 : static ivas_error initMcPanGainsWithConversionMapping_fx(
    1738             :     input_mc *inputMc,
    1739             :     const AUDIO_CONFIG outConfig )
    1740             : {
    1741             :     AUDIO_CONFIG ivasConfigIn, ivasConfigOut;
    1742             :     Word16 i;
    1743             : 
    1744         100 :     ivasConfigIn = inputMc->base.inConfig;
    1745         100 :     move32();
    1746         100 :     ivasConfigOut = outConfig;
    1747         100 :     move32();
    1748             : 
    1749             :     /* Find conversion mapping for current I/O config pair.
    1750             :      * Stay with default panning matrix if conversion_matrix is NULL */
    1751        2580 :     FOR( i = 0; i < LS_SETUP_CONVERSION_NUM_MAPPINGS; ++i )
    1752             :     {
    1753        2580 :         test();
    1754        2580 :         IF( EQ_32( ls_conversion_mapping_fx[i].input_config, ivasConfigIn ) && EQ_32( ls_conversion_mapping_fx[i].output_config, ivasConfigOut ) )
    1755             :         {
    1756             :             /* Mapping found with valid matrix - copy */
    1757         100 :             IF( ls_conversion_mapping_fx[i].conversion_matrix_fx != NULL )
    1758             :             {
    1759          62 :                 copyLsConversionMatrixToPanMatrix_fx( ls_conversion_mapping_fx[i].conversion_matrix_fx, inputMc->panGains_fx );
    1760             :             }
    1761             :             /* Mapping found with NULL matrix - use identity matrix */
    1762             :             ELSE
    1763             :             {
    1764          38 :                 fillIdentityPanMatrix_fx( inputMc->panGains_fx );
    1765             :             }
    1766             : 
    1767         100 :             return IVAS_ERR_OK;
    1768             :         }
    1769             :     }
    1770             : 
    1771           0 :     return IVAS_ERROR( IVAS_ERR_INTERNAL_FATAL, "Missing multichannel conversion mapping" );
    1772             : }
    1773             : 
    1774         180 : static ivas_error initMcPanGainsWithEfap_fx(
    1775             :     input_mc *inputMc,
    1776             :     const AUDIO_CONFIG outConfig )
    1777             : {
    1778             :     Word16 i;
    1779             :     Word16 numNonLfeInChannels;
    1780             :     Word16 inLfeChIdx, outChIdx;
    1781             :     const Word32 *spkAzi, *spkEle; /* Q22 */
    1782             :     ivas_error error;
    1783             : 
    1784         180 :     IF( NE_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1785             :     {
    1786          33 :         IF( NE_32( ( error = getNumNonLfeChannelsInSpeakerLayout( inputMc->base.inConfig, &numNonLfeInChannels ) ), IVAS_ERR_OK ) )
    1787             :         {
    1788           0 :             return error;
    1789             :         }
    1790             : 
    1791          33 :         IF( NE_32( ( error = getSpeakerAzimuths_fx( inputMc->base.inConfig, &spkAzi ) ), IVAS_ERR_OK ) )
    1792             :         {
    1793           0 :             return error;
    1794             :         }
    1795             : 
    1796          33 :         IF( NE_32( ( error = getSpeakerElevations_fx( inputMc->base.inConfig, &spkEle ) ), IVAS_ERR_OK ) )
    1797             :         {
    1798           0 :             return error;
    1799             :         }
    1800             : 
    1801          33 :         inLfeChIdx = LFE_CHANNEL;
    1802          33 :         move16();
    1803             :     }
    1804             :     ELSE
    1805             :     {
    1806         147 :         numNonLfeInChannels = inputMc->customLsInput.num_spk;
    1807         147 :         move16();
    1808         147 :         spkAzi = inputMc->customLsInput.ls_azimuth_fx;
    1809         147 :         move32();
    1810         147 :         spkEle = inputMc->customLsInput.ls_elevation_fx;
    1811         147 :         move32();
    1812         147 :         inLfeChIdx = -1;
    1813         147 :         move16();
    1814         147 :         if ( inputMc->customLsInput.num_lfe > 0 )
    1815             :         {
    1816           0 :             inLfeChIdx = inputMc->customLsInput.lfe_idx[0];
    1817           0 :             move16();
    1818             :         }
    1819             :     }
    1820         180 :     outChIdx = 0;
    1821         180 :     move16();
    1822        1257 :     FOR( i = 0; i < numNonLfeInChannels; ++i )
    1823             :     {
    1824        1077 :         IF( EQ_16( i, inLfeChIdx ) )
    1825             :         {
    1826          15 :             outChIdx = add( outChIdx, 1 );
    1827             :         }
    1828             : 
    1829        1077 :         IF( NE_32( ( error = getEfapGains_fx( *inputMc->base.ctx.pEfapOutWrapper, spkAzi[i], spkEle[i], inputMc->panGains_fx[outChIdx] ) ), IVAS_ERR_OK ) )
    1830             :         {
    1831           0 :             return error;
    1832             :         }
    1833        1077 :         outChIdx = add( outChIdx, 1 );
    1834             :     }
    1835             : 
    1836         180 :     test();
    1837         180 :     test();
    1838         180 :     IF( NE_32( outConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && inLfeChIdx >= 0 )
    1839             :     {
    1840          12 :         inputMc->panGains_fx[inLfeChIdx][LFE_CHANNEL] = ONE_IN_Q31;
    1841          12 :         move32();
    1842             :     }
    1843         168 :     ELSE IF( inputMc->base.ctx.pCustomLsOut->num_lfe > 0 && inLfeChIdx >= 0 )
    1844             :     {
    1845           0 :         inputMc->panGains_fx[inLfeChIdx][inputMc->base.ctx.pCustomLsOut->lfe_idx[0]] = ONE_IN_Q31;
    1846           0 :         move32();
    1847             :     }
    1848         180 :     return IVAS_ERR_OK;
    1849             : }
    1850             : 
    1851     2507531 : static ivas_error getRendInputNumChannels(
    1852             :     const void *rendInput,
    1853             :     Word16 *numInChannels )
    1854             : {
    1855             :     /* Using a void pointer for this function to be reusable for any input type (input_ism, input_mc, input_sba).
    1856             :         Assumptions:        - input_base is always the first member in the input struct    */
    1857             : 
    1858             :     ivas_error error;
    1859             :     const input_base *pInputBase;
    1860             :     const input_mc *pInputMc;
    1861             : 
    1862     2507531 :     pInputBase = (const input_base *) rendInput;
    1863             : 
    1864     2507531 :     IF( EQ_32( pInputBase->inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1865             :     {
    1866      215975 :         pInputMc = (const input_mc *) rendInput;
    1867      215975 :         *numInChannels = add( pInputMc->customLsInput.num_spk, pInputMc->customLsInput.num_lfe );
    1868      215975 :         move16();
    1869             :     }
    1870             :     ELSE
    1871             :     {
    1872     2291556 :         IF( NE_32( ( error = getAudioConfigNumChannels( pInputBase->inConfig, numInChannels ) ), IVAS_ERR_OK ) )
    1873             :         {
    1874           0 :             return error;
    1875             :         }
    1876             :     }
    1877             : 
    1878     2507531 :     return IVAS_ERR_OK;
    1879             : }
    1880             : 
    1881          16 : static ivas_error initMcPanGainsWithMonoOut_fx(
    1882             :     input_mc *inputMc )
    1883             : {
    1884             :     Word16 i;
    1885             :     Word16 numInChannels;
    1886             :     Word16 readIdx;
    1887             :     Word16 writeIdx;
    1888             :     bool skipSideSpeakers;
    1889             :     ivas_error error;
    1890             : 
    1891          16 :     IF( NE_32( ( error = getRendInputNumChannels( inputMc, &numInChannels ) ), IVAS_ERR_OK ) )
    1892             :     {
    1893           0 :         return error;
    1894             :     }
    1895             : 
    1896          16 :     IF( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    1897             :     {
    1898           0 :         FOR( i = 0; i < numInChannels; ++i )
    1899             :         {
    1900             :             /* It's OK to also set gain 1 for LFE input channels here.
    1901             :              * Correct LFE handling will be applied within updateMcPanGains() */
    1902           0 :             inputMc->panGains_fx[i][0] = ONE_IN_Q31;
    1903           0 :             move32();
    1904             :         }
    1905             :     }
    1906          16 :     ELSE IF( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_STEREO ) )
    1907             :     {
    1908             :         /* Special case for STEREO to MONO: Passive downmix (L+R)/2 */
    1909           4 :         inputMc->panGains_fx[0][0] = ONE_IN_Q30; // Q31(of 0.5)
    1910           4 :         move32();
    1911           4 :         inputMc->panGains_fx[1][0] = ONE_IN_Q30; // Q31(of 0.5)
    1912           4 :         move32();
    1913             :     }
    1914             :     ELSE
    1915             :     {
    1916             :         /* ls_conversion_cicpX_stereo contains gains for side speakers.
    1917             :          * These should be skipped with 5.1+X inputs. */
    1918          12 :         skipSideSpeakers = false;
    1919          12 :         move16();
    1920          12 :         test();
    1921          12 :         if ( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_5_1_2 ) || EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_5_1_4 ) )
    1922             :         {
    1923           6 :             skipSideSpeakers = true;
    1924           6 :             move16();
    1925             :         }
    1926          12 :         readIdx = 0;
    1927          12 :         move16();
    1928         120 :         FOR( writeIdx = 0; writeIdx < numInChannels; ++writeIdx )
    1929             :         {
    1930         108 :             test();
    1931         108 :             IF( ( skipSideSpeakers ) && EQ_16( readIdx, 4 ) )
    1932             :             {
    1933             :                 /* Skip gains for side speakers in lookup table */
    1934           6 :                 readIdx = add( readIdx, 2 );
    1935             :             }
    1936             : 
    1937         108 :             IF( EQ_32( ls_conversion_cicpX_mono_fx[readIdx][0], ONE_IN_Q30 ) )
    1938             :             {
    1939          48 :                 inputMc->panGains_fx[writeIdx][0] = ONE_IN_Q31;
    1940             :             }
    1941             :             ELSE
    1942             :             {
    1943          60 :                 inputMc->panGains_fx[writeIdx][0] = L_shl( ls_conversion_cicpX_mono_fx[readIdx][0], 1 );
    1944             :             }
    1945         108 :             move32();
    1946             : 
    1947         108 :             IF( EQ_32( ls_conversion_cicpX_mono_fx[readIdx][0], ONE_IN_Q30 ) )
    1948             :             {
    1949          48 :                 inputMc->panGains_fx[writeIdx][0] = ONE_IN_Q31;
    1950             :             }
    1951             :             ELSE
    1952             :             {
    1953          60 :                 inputMc->panGains_fx[writeIdx][0] = L_shl( ls_conversion_cicpX_mono_fx[readIdx][0], 1 ); // Q31
    1954             :             }
    1955         108 :             move32();
    1956         108 :             readIdx = add( readIdx, 1 );
    1957             :         }
    1958             :     }
    1959             : 
    1960          16 :     return IVAS_ERR_OK;
    1961             : }
    1962             : 
    1963          12 : static ivas_error initMcPanGainsWithStereoLookup_fx(
    1964             :     input_mc *inputMc )
    1965             : {
    1966             :     Word16 readIdx;
    1967             :     Word16 writeIdx;
    1968             :     bool skipSideSpeakers;
    1969             :     Word16 numInChannels;
    1970             :     ivas_error error;
    1971             : 
    1972             :     /* Special case - MONO input.
    1973             :      * Use gains for center CICP speaker and return early. */
    1974          12 :     IF( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_MONO ) )
    1975             :     {
    1976           0 :         inputMc->panGains_fx[0][0] = L_shl( ls_conversion_cicpX_stereo_fx[2][0], 1 ); /* Q30 + Q1 = Q31 */
    1977           0 :         move32();
    1978           0 :         inputMc->panGains_fx[0][1] = L_shl( ls_conversion_cicpX_stereo_fx[2][1], 1 ); /* Q30 + Q1 = Q31 */
    1979           0 :         move32();
    1980           0 :         return IVAS_ERR_OK;
    1981             :     }
    1982             : 
    1983             :     /* ls_conversion_cicpX_stereo contains gains for side speakers.
    1984             :      * These should be skipped with 5.1+X inputs. */
    1985          12 :     skipSideSpeakers = false;
    1986          12 :     move16();
    1987          12 :     test();
    1988          12 :     if ( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_5_1_2 ) || EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_5_1_4 ) )
    1989             :     {
    1990           6 :         skipSideSpeakers = true;
    1991           6 :         move16();
    1992             :     }
    1993             : 
    1994          12 :     IF( NE_32( ( error = getRendInputNumChannels( inputMc, &numInChannels ) ), IVAS_ERR_OK ) )
    1995             :     {
    1996           0 :         return error;
    1997             :     }
    1998          12 :     readIdx = 0;
    1999          12 :     move16();
    2000         120 :     FOR( writeIdx = 0; writeIdx < numInChannels; ++writeIdx )
    2001             :     {
    2002         108 :         test();
    2003         108 :         IF( skipSideSpeakers && EQ_16( readIdx, 4 ) )
    2004             :         {
    2005             :             /* Skip gains for side speakers in lookup table */
    2006           6 :             readIdx = add( readIdx, 2 );
    2007             :         }
    2008             : 
    2009         108 :         IF( EQ_32( ls_conversion_cicpX_stereo_fx[readIdx][0], ONE_IN_Q30 ) )
    2010             :         {
    2011          12 :             inputMc->panGains_fx[writeIdx][0] = ONE_IN_Q31;
    2012             :         }
    2013             :         ELSE
    2014             :         {
    2015          96 :             inputMc->panGains_fx[writeIdx][0] = L_shl( ls_conversion_cicpX_stereo_fx[readIdx][0], 1 ); /* Q30 + Q1 = Q31 */
    2016             :         }
    2017         108 :         move32();
    2018             : 
    2019         108 :         IF( EQ_32( ls_conversion_cicpX_stereo_fx[readIdx][1], ONE_IN_Q30 ) )
    2020             :         {
    2021          12 :             inputMc->panGains_fx[writeIdx][1] = ONE_IN_Q31;
    2022             :         }
    2023             :         ELSE
    2024             :         {
    2025          96 :             inputMc->panGains_fx[writeIdx][1] = L_shl( ls_conversion_cicpX_stereo_fx[readIdx][1], 1 ); /* Q30 + Q1 = Q31 */
    2026             :         }
    2027         108 :         move32();
    2028         108 :         readIdx = add( readIdx, 1 );
    2029             :     }
    2030             : 
    2031          12 :     return IVAS_ERR_OK;
    2032             : }
    2033             : 
    2034             : 
    2035             : /* Returns 1 (true) if configs A and B are equal, otherwise returns 0 (false).
    2036             :  * If both configs are custom LS layouts, layout details are compared to determine equality. */
    2037         342 : static bool configsAreEqual(
    2038             :     const AUDIO_CONFIG configA,
    2039             :     const LSSETUP_CUSTOM_STRUCT customLsA,
    2040             :     const AUDIO_CONFIG configB,
    2041             :     const LSSETUP_CUSTOM_STRUCT customLsB )
    2042             : {
    2043             :     Word16 i;
    2044             : 
    2045             :     /* Both input and output are custom LS - compare structs */
    2046         342 :     test();
    2047         342 :     IF( EQ_32( configA, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && EQ_32( configB, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    2048             :     {
    2049          18 :         IF( NE_16( customLsA.num_spk, customLsB.num_spk ) )
    2050             :         {
    2051          15 :             return false;
    2052             :         }
    2053             : 
    2054           3 :         IF( NE_16( customLsA.num_lfe, customLsB.num_lfe ) )
    2055             :         {
    2056           0 :             return false;
    2057             :         }
    2058             : 
    2059           3 :         IF( NE_16( customLsA.is_planar_setup, customLsB.is_planar_setup ) )
    2060             :         {
    2061           0 :             return false;
    2062             :         }
    2063             : 
    2064          39 :         FOR( i = 0; i < customLsA.num_spk; ++i )
    2065             :         {
    2066             :             /* Compare to nearest degree (hence the int16_t cast) */
    2067          36 :             test();
    2068          36 :             IF( NE_32( customLsA.ls_azimuth_fx[i], customLsB.ls_azimuth_fx[i] ) ||
    2069             :                 NE_32( customLsA.ls_elevation_fx[i], customLsB.ls_elevation_fx[i] ) )
    2070             :             {
    2071           0 :                 return false;
    2072             :             }
    2073             :         }
    2074           3 :         FOR( i = 0; i < customLsA.num_lfe; ++i )
    2075             :         {
    2076           0 :             IF( NE_16( customLsA.lfe_idx[i], customLsB.lfe_idx[i] ) )
    2077             :             {
    2078           0 :                 return false;
    2079             :             }
    2080             :         }
    2081             : 
    2082           3 :         return true;
    2083             :     }
    2084             : 
    2085             :     /* Otherwise it's enough to compare config enums */
    2086         324 :     return configA == configB;
    2087             : }
    2088         342 : static ivas_error updateLfePanGainsForMcOut(
    2089             :     input_mc *inputMc,
    2090             :     const AUDIO_CONFIG outConfig )
    2091             : {
    2092             :     Word16 i, numLfeIn, numOutChannels;
    2093             :     ivas_error error;
    2094         342 :     error = IVAS_ERR_OK;
    2095         342 :     move32();
    2096             : 
    2097             :     /* If panning is not required, simply return */
    2098         342 :     IF( !inputMc->lfeRouting.pan_lfe )
    2099             :     {
    2100         342 :         return error;
    2101             :     }
    2102             : 
    2103           0 :     numLfeIn = getNumLfeChannels( inputMc );
    2104             : 
    2105           0 :     IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    2106             :     {
    2107           0 :         numOutChannels = add( inputMc->base.ctx.pCustomLsOut->num_spk, inputMc->base.ctx.pCustomLsOut->num_lfe );
    2108             :     }
    2109             :     ELSE
    2110             :     {
    2111           0 :         IF( NE_32( ( error = getAudioConfigNumChannels( outConfig, &numOutChannels ) ), IVAS_ERR_OK ) )
    2112             :         {
    2113           0 :             return error;
    2114             :         }
    2115             :     }
    2116             : 
    2117           0 :     FOR( i = 0; i < numLfeIn; i++ )
    2118             :     {
    2119             :         /* panning gains */
    2120           0 :         IF( NE_32( ( error = getEfapGains_fx( *inputMc->base.ctx.pEfapOutWrapper, inputMc->lfeRouting.lfeOutputAzimuth_fx, inputMc->lfeRouting.lfeOutputElevation_fx, inputMc->lfeRouting.lfePanMtx_fx[i] ) ), IVAS_ERR_OK ) )
    2121             :         {
    2122           0 :             return error;
    2123             :         }
    2124             : 
    2125             :         /* linear input gain */
    2126           0 :         v_multc_fixed( inputMc->lfeRouting.lfePanMtx_fx[i], inputMc->lfeRouting.lfeInputGain_fx, inputMc->lfeRouting.lfePanMtx_fx[i], numOutChannels ); /* Q31 */
    2127             :     }
    2128             : 
    2129           0 :     return error;
    2130             : }
    2131          90 : static ivas_error updateLfePanGainsForAmbiOut(
    2132             :     input_mc *inputMc,
    2133             :     const AUDIO_CONFIG outConfig )
    2134             : {
    2135             :     Word16 i;
    2136             :     Word16 numLfeIn, outAmbiOrder;
    2137             :     ivas_error error;
    2138          90 :     error = IVAS_ERR_OK;
    2139          90 :     move32();
    2140             : 
    2141             :     /* If panning is not required, simply return */
    2142          90 :     IF( !inputMc->lfeRouting.pan_lfe )
    2143             :     {
    2144          90 :         return error;
    2145             :     }
    2146             : 
    2147           0 :     IF( NE_32( ( error = getAmbisonicsOrder_fx( outConfig, &outAmbiOrder ) ), IVAS_ERR_OK ) )
    2148             :     {
    2149           0 :         return error;
    2150             :     }
    2151             : 
    2152           0 :     numLfeIn = getNumLfeChannels( inputMc );
    2153           0 :     move16();
    2154           0 :     FOR( i = 0; i < numLfeIn; i++ )
    2155             :     {
    2156             :         /* panning gains */
    2157           0 :         ivas_dirac_dec_get_response_fx( inputMc->lfeRouting.lfeOutputAzimuth_fx, inputMc->lfeRouting.lfeOutputElevation_fx, inputMc->lfeRouting.lfePanMtx_fx[i], outAmbiOrder, Q29 );
    2158             : 
    2159             :         /* linear input gain */
    2160           0 :         v_multc_fixed( inputMc->lfeRouting.lfePanMtx_fx[i], inputMc->lfeRouting.lfeInputGain_fx, inputMc->lfeRouting.lfePanMtx_fx[i], IVAS_MAX_OUTPUT_CHANNELS ); /* Q31 */
    2161             :     }
    2162             : 
    2163           0 :     return error;
    2164             : }
    2165         342 : static ivas_error updateMcPanGainsForMcOut(
    2166             :     input_mc *inputMc,
    2167             :     const AUDIO_CONFIG outConfig )
    2168             : {
    2169             :     ivas_error error;
    2170             : 
    2171             :     /* "if" conditions below realize the following mapping:
    2172             : 
    2173             :     If in == out, use identity matrix, otherwise follow the table:
    2174             :     +-----------+-------------+---------------+-----------+--------------------+
    2175             :     |  in\out   |   MONO      |   STEREO      | custom LS |       other        |
    2176             :     +-----------+-------------+---------------+-----------+--------------------+
    2177             :     | MONO      | mono out    | EFAP          | EFAP      | EFAP               |
    2178             :     | custom LS | mono out    | EFAP          | EFAP      | EFAP               |
    2179             :     | other     | mono lookup | stereo lookup | EFAP      | conversion mapping |
    2180             :     +-----------+-------------+---------------+-----------+--------------------+
    2181             :     */
    2182             : 
    2183         342 :     test();
    2184         342 :     test();
    2185         342 :     IF( configsAreEqual( inputMc->base.inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut ) )
    2186             :     {
    2187          29 :         error = initMcPanGainsWithIdentMatrix( inputMc );
    2188             :     }
    2189         313 :     ELSE IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ||
    2190             :              EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_MONO ) ||
    2191             :              EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    2192             :     {
    2193         185 :         test();
    2194         185 :         IF( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_MONO ) && ( inputMc->nonDiegeticPan ) )
    2195             :         {
    2196           5 :             IF( EQ_32( inputMc->nonDiegeticPanGain_fx, ONE_IN_Q31 ) )
    2197             :             {
    2198           1 :                 inputMc->panGains_fx[0][0] = ONE_IN_Q31;
    2199             :             }
    2200             :             ELSE
    2201             :             {
    2202           4 :                 inputMc->panGains_fx[0][0] = L_add( L_shr( inputMc->nonDiegeticPanGain_fx, 1 ), ONE_IN_Q30 /* 0.5f in Q31 */ ); /* Q31 */
    2203             :             }
    2204           5 :             move32();
    2205           5 :             inputMc->panGains_fx[0][1] = L_sub( ONE_IN_Q31, inputMc->panGains_fx[0][0] );
    2206           5 :             move32();
    2207           5 :             error = IVAS_ERR_OK;
    2208           5 :             move32();
    2209             :         }
    2210             :         ELSE
    2211             :         {
    2212         180 :             error = initMcPanGainsWithEfap_fx( inputMc, outConfig );
    2213             :         }
    2214             :     }
    2215         128 :     ELSE IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_MONO ) )
    2216             :     {
    2217          16 :         error = initMcPanGainsWithMonoOut_fx( inputMc );
    2218             :     }
    2219         112 :     ELSE IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_STEREO ) )
    2220             :     {
    2221          12 :         error = initMcPanGainsWithStereoLookup_fx( inputMc );
    2222             :     }
    2223             :     ELSE /* default */
    2224             :     {
    2225         100 :         error = initMcPanGainsWithConversionMapping_fx( inputMc, outConfig );
    2226             :     }
    2227             : 
    2228             :     /* check for errors from above block */
    2229         342 :     IF( NE_32( error, IVAS_ERR_OK ) )
    2230             :     {
    2231           0 :         return error;
    2232             :     }
    2233             : 
    2234             :     /* update LFE panning */
    2235         342 :     error = updateLfePanGainsForMcOut( inputMc, outConfig );
    2236             : 
    2237         342 :     return error;
    2238             : }
    2239          90 : static ivas_error updateMcPanGainsForAmbiOut(
    2240             :     input_mc *inputMc,
    2241             :     const AUDIO_CONFIG outConfig )
    2242             : {
    2243             :     Word16 ch_in, ch_out, lfeIdx, i;
    2244             :     Word16 numNonLfeInChannels, outAmbiOrder;
    2245             :     const Word32 *spkAzi_fx, *spkEle_fx; /* Q22 */
    2246             :     ivas_error error;
    2247             : 
    2248          90 :     IF( NE_32( ( error = getAmbisonicsOrder_fx( outConfig, &outAmbiOrder ) ), IVAS_ERR_OK ) )
    2249             :     {
    2250           0 :         return error;
    2251             :     }
    2252             : 
    2253          90 :     IF( NE_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    2254             :     {
    2255          54 :         IF( NE_32( ( error = getNumNonLfeChannelsInSpeakerLayout( inputMc->base.inConfig, &numNonLfeInChannels ) ), IVAS_ERR_OK ) )
    2256             :         {
    2257           0 :             return error;
    2258             :         }
    2259             : 
    2260          54 :         IF( NE_32( ( error = getSpeakerAzimuths_fx( inputMc->base.inConfig, &spkAzi_fx ) ), IVAS_ERR_OK ) )
    2261             :         {
    2262           0 :             return error;
    2263             :         }
    2264             : 
    2265          54 :         IF( NE_32( ( error = getSpeakerElevations_fx( inputMc->base.inConfig, &spkEle_fx ) ), IVAS_ERR_OK ) )
    2266             :         {
    2267           0 :             return error;
    2268             :         }
    2269          54 :         ch_in = 0;
    2270          54 :         move16();
    2271         372 :         FOR( ch_out = 0; ch_in < numNonLfeInChannels; ++ch_out )
    2272             :         {
    2273         318 :             IF( EQ_16( ch_in, LFE_CHANNEL ) )
    2274             :             {
    2275          36 :                 ch_out = add( ch_out, 1 );
    2276             :             }
    2277         318 :             move16();
    2278         318 :             move16(); // move for typecasting Word32 to Word16
    2279         318 :             ivas_dirac_dec_get_response_fx( (Word16) L_shr( spkAzi_fx[ch_in], 22 ), (Word16) L_shr( spkEle_fx[ch_in], 22 ), inputMc->panGains_fx[ch_out], outAmbiOrder, Q29 );
    2280        5406 :             FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    2281             :             {
    2282        5088 :                 Word32 temp = inputMc->panGains_fx[ch_out][i];
    2283        5088 :                 move32();
    2284             : 
    2285        5088 :                 IF( GE_32( L_abs( temp ), ONE_IN_Q29 ) )
    2286             :                 {
    2287         324 :                     IF( temp > 0 )
    2288             :                     {
    2289         318 :                         inputMc->panGains_fx[ch_out][i] = ONE_IN_Q31;
    2290         318 :                         move32();
    2291             :                     }
    2292             :                     ELSE
    2293             :                     {
    2294           6 :                         inputMc->panGains_fx[ch_out][i] = L_negate( ONE_IN_Q31 );
    2295           6 :                         move32();
    2296             :                     }
    2297             :                 }
    2298             :                 ELSE
    2299             :                 {
    2300        4764 :                     inputMc->panGains_fx[ch_out][i] = L_shl( temp, 2 ); /* Q29 + Q2 = Q31 */
    2301        4764 :                     move32();
    2302             :                 }
    2303             :             }
    2304         318 :             ch_in = add( ch_in, 1 );
    2305             :         }
    2306             :     }
    2307             :     ELSE
    2308             :     {
    2309          36 :         numNonLfeInChannels = inputMc->customLsInput.num_spk;
    2310          36 :         move16();
    2311          36 :         spkAzi_fx = inputMc->customLsInput.ls_azimuth_fx;
    2312          36 :         move32();
    2313          36 :         spkEle_fx = inputMc->customLsInput.ls_elevation_fx;
    2314          36 :         move32();
    2315          36 :         ch_in = 0;
    2316          36 :         move16();
    2317         270 :         FOR( ch_out = 0; ch_in < numNonLfeInChannels; ++ch_out )
    2318             :         {
    2319         234 :             FOR( lfeIdx = 0; lfeIdx < inputMc->customLsInput.num_lfe; ++lfeIdx )
    2320             :             {
    2321           0 :                 IF( EQ_16( inputMc->customLsInput.lfe_idx[lfeIdx], ch_in ) )
    2322             :                 {
    2323           0 :                     ch_out = add( ch_out, 1 );
    2324           0 :                     BREAK;
    2325             :                 }
    2326             :             }
    2327             : 
    2328         234 :             ivas_dirac_dec_get_response_fx( (Word16) L_shr( spkAzi_fx[ch_in], 22 ), (Word16) L_shr( spkEle_fx[ch_in], 22 ), inputMc->panGains_fx[ch_out], outAmbiOrder, Q29 );
    2329        3978 :             FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    2330             :             {
    2331        3744 :                 Word32 temp = inputMc->panGains_fx[ch_out][i];
    2332        3744 :                 move32();
    2333        3744 :                 IF( GE_32( L_abs( temp ), ONE_IN_Q29 ) )
    2334             :                 {
    2335         240 :                     IF( temp > 0 )
    2336             :                     {
    2337         234 :                         inputMc->panGains_fx[ch_out][i] = ONE_IN_Q31;
    2338         234 :                         move32();
    2339             :                     }
    2340             :                     ELSE
    2341             :                     {
    2342           6 :                         inputMc->panGains_fx[ch_out][i] = L_negate( ONE_IN_Q31 );
    2343           6 :                         move32();
    2344             :                     }
    2345             :                 }
    2346             :                 ELSE
    2347             :                 {
    2348        3504 :                     inputMc->panGains_fx[ch_out][i] = L_shl( temp, 2 ); /* Q29 + Q2 = Q31 */
    2349        3504 :                     move32();
    2350             :                 }
    2351             :             }
    2352         234 :             ch_in = add( ch_in, 1 );
    2353             :         }
    2354             :     }
    2355             : 
    2356             :     /* update LFE panning */
    2357          90 :     IF( NE_32( ( error = updateLfePanGainsForAmbiOut( inputMc, outConfig ) ), IVAS_ERR_OK ) )
    2358             :     {
    2359           0 :         return error;
    2360             :     }
    2361             : 
    2362          90 :     return IVAS_ERR_OK;
    2363             : }
    2364         477 : static ivas_error updateMcPanGains(
    2365             :     input_mc *inputMc,
    2366             :     const AUDIO_CONFIG outConfig )
    2367             : {
    2368             :     Word16 i;
    2369             :     ivas_error error;
    2370             : 
    2371             :     /* Reset to all zeros - some functions below only write non-zero elements. */
    2372         477 :     setZeroPanMatrix_fx( inputMc->panGains_fx );
    2373             : 
    2374         477 :     error = IVAS_ERR_OK;
    2375         477 :     move32();
    2376         477 :     SWITCH( getAudioConfigType( outConfig ) )
    2377             :     {
    2378         254 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    2379         254 :             error = updateMcPanGainsForMcOut( inputMc, outConfig );
    2380         254 :             BREAK;
    2381          90 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    2382          90 :             error = updateMcPanGainsForAmbiOut( inputMc, outConfig );
    2383          90 :             BREAK;
    2384         132 :         case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL:
    2385             :             SWITCH( outConfig )
    2386             :             {
    2387          44 :                 case IVAS_AUDIO_CONFIG_BINAURAL:
    2388             :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
    2389             :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
    2390          44 :                     BREAK; /* Do nothing */
    2391          88 :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
    2392             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    2393             :                     /* Prepare rendering to intermediate format */
    2394          88 :                     error = updateMcPanGainsForMcOut( inputMc, IVAS_AUDIO_CONFIG_7_1_4 );
    2395          88 :                     BREAK;
    2396           0 :                 default:
    2397           0 :                     return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    2398             :             }
    2399         132 :             BREAK;
    2400           1 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    2401           1 :             BREAK; /* Do nothing */
    2402           0 :         default:
    2403           0 :             return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    2404             :     }
    2405             :     /* Check error here to keep switch statement more compact */
    2406         477 :     IF( NE_32( error, IVAS_ERR_OK ) )
    2407             :     {
    2408           0 :         return error;
    2409             :     }
    2410             : 
    2411             :     /* Copy LFE routing to pan gains array */
    2412         477 :     IF( EQ_16( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    2413             :     {
    2414         210 :         FOR( i = 0; i < inputMc->customLsInput.num_lfe; ++i )
    2415             :         {
    2416           0 :             Copy32( inputMc->lfeRouting.lfePanMtx_fx[i], inputMc->panGains_fx[inputMc->customLsInput.lfe_idx[i]], IVAS_MAX_OUTPUT_CHANNELS );
    2417             :         }
    2418             :     }
    2419             :     ELSE
    2420             :     {
    2421             :         /* For code simplicity, always copy LFE gains. If config has no LFE, gains will be zero anyway. */
    2422         267 :         Copy32( inputMc->lfeRouting.lfePanMtx_fx[0], inputMc->panGains_fx[LFE_CHANNEL], IVAS_MAX_OUTPUT_CHANNELS );
    2423             :     }
    2424             : 
    2425         477 :     return IVAS_ERR_OK;
    2426             : }
    2427             : 
    2428      113253 : static ivas_error initMcBinauralRendering(
    2429             :     input_mc *inputMc,
    2430             :     const AUDIO_CONFIG inConfig,
    2431             :     const AUDIO_CONFIG outConfig,
    2432             :     RENDER_CONFIG_DATA *hRendCfg,
    2433             :     IVAS_DEC_HRTF_CREND_HANDLE hMixconv,
    2434             :     HRTFS_STATISTICS_HANDLE hHrtfStatistics,
    2435             :     uint8_t reconfigureFlag )
    2436             : {
    2437             :     ivas_error error;
    2438             :     Word32 binauralDelayNs;
    2439             :     Word32 outSampleRate;
    2440             :     Word8 useTDRend;
    2441             :     Word16 i, num_poses;
    2442             : 
    2443      113253 :     num_poses = 1;
    2444      113253 :     move16();
    2445      113253 :     if ( inputMc->base.ctx.pSplitRendWrapper != NULL )
    2446             :     {
    2447           0 :         num_poses = inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    2448           0 :         move16();
    2449             :     }
    2450             : 
    2451             :     /* Allocate TD binaural renderer for custom loudspeaker layouts (regardless of headrotation)
    2452             :       or planar MC layouts with headrotation, CREND for the rest */
    2453      113253 :     useTDRend = FALSE;
    2454      113253 :     move16();
    2455      113253 :     IF( NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) )
    2456             :     {
    2457       75502 :         test();
    2458       75502 :         test();
    2459       75502 :         test();
    2460       75502 :         IF( EQ_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
    2461             :         {
    2462       16931 :             useTDRend = TRUE;
    2463       16931 :             move16();
    2464             :         }
    2465       58571 :         ELSE IF( ( EQ_16( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_16( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) &&
    2466             :                  ( inputMc->base.ctx.pHeadRotData->headRotEnabled ) )
    2467             :         {
    2468       18408 :             useTDRend = TRUE;
    2469       18408 :             move16();
    2470             :         }
    2471             :     }
    2472             : 
    2473             :     /* if TD renderer was open and we need to use CREND, close it */
    2474      113253 :     test();
    2475      113253 :     IF( !reconfigureFlag || ( !useTDRend && inputMc->tdRendWrapper.hBinRendererTd != NULL ) )
    2476             :     {
    2477         132 :         ivas_td_binaural_close_fx( &inputMc->tdRendWrapper.hBinRendererTd );
    2478             :     }
    2479             : 
    2480      113253 :     IF( !reconfigureFlag || !useTDRend )
    2481             :     {
    2482      623568 :         FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    2483             :         {
    2484      545622 :             IF( inputMc->splitTdRendWrappers[i].hBinRendererTd != NULL )
    2485             :             {
    2486           0 :                 ivas_td_binaural_close_fx( &inputMc->splitTdRendWrappers[i].hBinRendererTd );
    2487             :             }
    2488             :         }
    2489             :     }
    2490             : 
    2491             :     /* if we need to use TD renderer and CREND was open, close it */
    2492      113253 :     IF( useTDRend )
    2493             :     {
    2494       35339 :         ivas_rend_closeCrend( &inputMc->crendWrapper, num_poses );
    2495             :     }
    2496             : 
    2497      113253 :     test();
    2498      113253 :     test();
    2499      113253 :     IF( !reconfigureFlag || ( !useTDRend && NE_16( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && inputMc->hReverb != NULL ) )
    2500             :     {
    2501         132 :         ivas_reverb_close( &inputMc->hReverb );
    2502             :     }
    2503             : 
    2504      113253 :     test();
    2505      113253 :     test();
    2506      113253 :     IF( !reconfigureFlag || ( EQ_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && !inputMc->base.ctx.pHeadRotData->headRotEnabled ) )
    2507             :     {
    2508       19638 :         IF( inputMc->efapInWrapper.hEfap != NULL )
    2509             :         {
    2510          36 :             efap_free_data_fx( &inputMc->efapInWrapper.hEfap );
    2511             :         }
    2512             :     }
    2513             : 
    2514      113253 :     outSampleRate = *inputMc->base.ctx.pOutSampleRate;
    2515      113253 :     move32();
    2516             : 
    2517      113253 :     test();
    2518      113253 :     test();
    2519      113253 :     IF( useTDRend && inputMc->tdRendWrapper.hBinRendererTd == NULL )
    2520          32 :     {
    2521             :         Word16 SrcInd[MAX_NUM_TDREND_CHANNELS];
    2522             :         Word16 num_src;
    2523          32 :         IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputMc->tdRendWrapper, inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) )
    2524             :         {
    2525           0 :             return error;
    2526             :         }
    2527          32 :         Word16 nchan_rend = num_src;
    2528          32 :         move16();
    2529             : 
    2530          32 :         test();
    2531          32 :         IF( ( EQ_32( getAudioConfigType( inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ) && NE_16( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    2532             :         {
    2533           8 :             nchan_rend = sub( nchan_rend, 1 ); /* Skip LFE channel -- added to the others */
    2534             :         }
    2535         236 :         FOR( Word16 nS = 0; nS < nchan_rend; nS++ )
    2536             :         {
    2537         204 :             TDREND_SRC_t *Src_p = inputMc->tdRendWrapper.hBinRendererTd->Sources[SrcInd[nS]];
    2538         204 :             IF( Src_p != NULL )
    2539             :             {
    2540         204 :                 IF( Src_p->SrcSpatial_p != NULL )
    2541             :                 {
    2542         204 :                     Src_p->SrcSpatial_p->q_Pos_p = 31;
    2543         204 :                     move16();
    2544             :                 }
    2545         204 :                 IF( inputMc->tdRendWrapper.hBinRendererTd->Sources[nS] != NULL )
    2546             :                 {
    2547         204 :                     TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputMc->tdRendWrapper.hBinRendererTd->Sources[nS]->SrcSpatial_p;
    2548         204 :                     SrcSpatial_p->q_Pos_p = 31;
    2549         204 :                     move16();
    2550             :                 }
    2551             :             }
    2552             :         }
    2553             : 
    2554          32 :         IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    2555             :         {
    2556             :             /* Open TD renderer wrappers */
    2557           0 :             FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    2558             :             {
    2559           0 :                 IF( NE_32( ( error = ivas_td_binaural_open_ext_fx( &inputMc->splitTdRendWrappers[i], inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate, SrcInd, &num_src ) ), IVAS_ERR_OK ) )
    2560             :                 {
    2561           0 :                     return error;
    2562             :                 }
    2563             : 
    2564             :                 /* Assert same delay as main TD renderer */
    2565           0 :                 assert( inputMc->splitTdRendWrappers[i].binaural_latency_ns == inputMc->tdRendWrapper.binaural_latency_ns );
    2566             : 
    2567           0 :                 FOR( Word16 nS = 0; nS < nchan_rend; nS++ )
    2568             :                 {
    2569           0 :                     TDREND_SRC_t *Src_p = inputMc->splitTdRendWrappers[i].hBinRendererTd->Sources[SrcInd[nS]];
    2570           0 :                     IF( Src_p != NULL )
    2571             :                     {
    2572           0 :                         IF( Src_p->SrcSpatial_p != NULL )
    2573             :                         {
    2574           0 :                             Src_p->SrcSpatial_p->q_Pos_p = 31;
    2575           0 :                             move16();
    2576             :                         }
    2577           0 :                         IF( inputMc->splitTdRendWrappers[i].hBinRendererTd->Sources[nS] != NULL )
    2578             :                         {
    2579           0 :                             TDREND_SRC_SPATIAL_t *SrcSpatial_p = inputMc->splitTdRendWrappers[i].hBinRendererTd->Sources[nS]->SrcSpatial_p;
    2580           0 :                             SrcSpatial_p->q_Pos_p = 31;
    2581           0 :                             move16();
    2582             :                         }
    2583             :                     }
    2584             :                 }
    2585             :             }
    2586             :         }
    2587             : 
    2588             : 
    2589          32 :         test();
    2590          32 :         IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && inputMc->hReverb == NULL )
    2591             :         {
    2592           4 :             IF( NE_32( ( error = ivas_reverb_open_fx( &( inputMc->hReverb ), hHrtfStatistics, hRendCfg, outSampleRate ) ), IVAS_ERR_OK ) )
    2593             :             {
    2594           0 :                 return error;
    2595             :             }
    2596             :         }
    2597             :     }
    2598      113221 :     ELSE IF( !useTDRend && inputMc->crendWrapper == NULL )
    2599             :     {
    2600             :         /* open CREND */
    2601          76 :         IF( NE_32( ( error = ivas_rend_openCrend( &inputMc->crendWrapper, ( inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM ) ? IVAS_AUDIO_CONFIG_7_1_4 : inConfig, outConfig, hRendCfg, hMixconv, hHrtfStatistics, outSampleRate, num_poses ) ), IVAS_ERR_OK ) )
    2602             :         {
    2603           0 :             return error;
    2604             :         }
    2605             :     }
    2606             : 
    2607             :     /* Initialise the EFAP handle for rotation on input layout */
    2608      113253 :     test();
    2609      113253 :     test();
    2610      113253 :     IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && inputMc->base.ctx.pHeadRotData->headRotEnabled && inputMc->efapInWrapper.hEfap == NULL )
    2611             :     {
    2612          30 :         IF( NE_32( ( error = initEfap( &inputMc->efapInWrapper, inConfig, NULL ) ), IVAS_ERR_OK ) )
    2613             :         {
    2614           0 :             return error;
    2615             :         }
    2616             :     }
    2617             : 
    2618             :     /* determine binaural delay ( used for aligning LFE to output signal ) */
    2619             : 
    2620      113253 :     IF( ( inputMc->crendWrapper != NULL ) )
    2621             :     {
    2622       77914 :         binauralDelayNs = inputMc->crendWrapper->binaural_latency_ns;
    2623             :     }
    2624             :     ELSE
    2625             :     {
    2626       35339 :         binauralDelayNs = 0;
    2627             :     }
    2628      113253 :     move32();
    2629             : 
    2630      113253 :     binauralDelayNs = L_max( binauralDelayNs, inputMc->tdRendWrapper.binaural_latency_ns );
    2631      113253 :     Word16 exp = 0;
    2632      113253 :     move16();
    2633      113253 :     Word16 var1 = BASOP_Util_Divide3232_Scale( *inputMc->base.ctx.pOutSampleRate, 1000000000, &exp );
    2634      113253 :     Word32 var2 = L_shr_r( Mpy_32_32( binauralDelayNs, L_deposit_h( var1 ) ), negate( exp ) ); /* Q0 */
    2635      113253 :     inputMc->binauralDelaySmp = extract_l( var2 );
    2636      113253 :     move16();
    2637             :     // inputMc->binauralDelaySmp = (int16_t) roundf( (float) binauralDelayNs * *inputMc->base.ctx.pOutSampleRate / 1000000000.f );
    2638             : 
    2639      113253 :     IF( GT_16( inputMc->binauralDelaySmp, MAX_BIN_DELAY_SAMPLES ) )
    2640             :     {
    2641           0 :         return IVAS_ERROR( IVAS_ERR_WRONG_PARAMS, "Invalid delay for LFE binaural rendering!)" );
    2642             :     }
    2643             : 
    2644      113253 :     return IVAS_ERR_OK;
    2645             : }
    2646             : 
    2647           1 : static ivas_error initMcMasaRendering(
    2648             :     input_mc *inputMc,
    2649             :     const AUDIO_CONFIG inConfig,
    2650             :     const Word32 inSampleRate )
    2651             : {
    2652             :     ivas_error error;
    2653             :     Word16 num_poses;
    2654             : 
    2655           1 :     num_poses = 1;
    2656           1 :     move16();
    2657           1 :     if ( inputMc->base.ctx.pSplitRendWrapper != NULL )
    2658             :     {
    2659           0 :         num_poses = inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    2660           0 :         move16();
    2661             :     }
    2662             : 
    2663           1 :     IF( inputMc->tdRendWrapper.hBinRendererTd != NULL )
    2664             :     {
    2665           0 :         ivas_td_binaural_close_fx( &inputMc->tdRendWrapper.hBinRendererTd );
    2666             :     }
    2667             : 
    2668           1 :     ivas_rend_closeCrend( &inputMc->crendWrapper, num_poses );
    2669             : 
    2670           1 :     ivas_reverb_close( &inputMc->hReverb );
    2671             : 
    2672           1 :     IF( inputMc->efapInWrapper.hEfap != NULL )
    2673             :     {
    2674           0 :         efap_free_data_fx( &inputMc->efapInWrapper.hEfap );
    2675             :     }
    2676             : 
    2677           1 :     IF( NE_32( ( error = ivas_mcmasa_ana_open( &inputMc->hMcMasa, inConfig, inSampleRate ) ), IVAS_ERR_OK ) )
    2678             :     {
    2679           0 :         return error;
    2680             :     }
    2681             : 
    2682           1 :     return IVAS_ERR_OK;
    2683             : }
    2684             : 
    2685         477 : static lfe_routing defaultLfeRouting(
    2686             :     const AUDIO_CONFIG inConfig,
    2687             :     const LSSETUP_CUSTOM_STRUCT customLsIn,
    2688             :     const AUDIO_CONFIG outConfig,
    2689             :     const LSSETUP_CUSTOM_STRUCT customLsOut )
    2690             : {
    2691             :     Word16 i;
    2692             :     lfe_routing routing;
    2693             : 
    2694             :     /* Set all output gains to zero, then route each input LFE consecutively to the next available output LFE. */
    2695             : 
    2696        2385 :     FOR( i = 0; i < RENDERER_MAX_INPUT_LFE_CHANNELS; ++i )
    2697             :     {
    2698        1908 :         set32_fx( routing.lfePanMtx_fx[i], 0, IVAS_MAX_OUTPUT_CHANNELS );
    2699             :     }
    2700         477 :     routing.pan_lfe = false;
    2701         477 :     move16();
    2702         477 :     routing.lfeInputGain_fx = ONE_IN_Q31;
    2703         477 :     move32();
    2704             : 
    2705         477 :     SWITCH( inConfig )
    2706             :     {
    2707         196 :         case IVAS_AUDIO_CONFIG_5_1:
    2708             :         case IVAS_AUDIO_CONFIG_5_1_2:
    2709             :         case IVAS_AUDIO_CONFIG_5_1_4:
    2710             :         case IVAS_AUDIO_CONFIG_7_1:
    2711             :         case IVAS_AUDIO_CONFIG_7_1_4:
    2712         196 :             routing.numLfeChannels = 1;
    2713         196 :             move16();
    2714         196 :             BREAK;
    2715         210 :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
    2716         210 :             routing.numLfeChannels = customLsIn.num_lfe;
    2717         210 :             move16();
    2718         210 :             BREAK;
    2719          71 :         default:
    2720          71 :             routing.numLfeChannels = 0;
    2721          71 :             move16();
    2722             :     }
    2723             : 
    2724         477 :     SWITCH( outConfig )
    2725             :     {
    2726         150 :         case IVAS_AUDIO_CONFIG_5_1:
    2727             :         case IVAS_AUDIO_CONFIG_5_1_2:
    2728             :         case IVAS_AUDIO_CONFIG_5_1_4:
    2729             :         case IVAS_AUDIO_CONFIG_7_1:
    2730             :         case IVAS_AUDIO_CONFIG_7_1_4:
    2731         150 :             routing.lfePanMtx_fx[0][LFE_CHANNEL] = ONE_IN_Q31;
    2732         150 :             move32();
    2733         150 :             BREAK;
    2734          39 :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
    2735          39 :             FOR( i = 0; i < routing.numLfeChannels && i < customLsOut.num_lfe; ++i )
    2736             :             {
    2737           0 :                 test();
    2738           0 :                 routing.lfePanMtx_fx[i][customLsOut.lfe_idx[i]] = ONE_IN_Q31;
    2739           0 :                 move32();
    2740             :             }
    2741          39 :             BREAK;
    2742         288 :         default:
    2743             :             /* Do nothing */
    2744         288 :             BREAK;
    2745             :     }
    2746             : 
    2747         477 :     return routing;
    2748             : }
    2749         372 : static ivas_error setRendInputActiveMc(
    2750             :     void *input,
    2751             :     const AUDIO_CONFIG inConfig,
    2752             :     const IVAS_REND_InputId id,
    2753             :     RENDER_CONFIG_DATA *hRendCfg,
    2754             :     hrtf_handles *hrtfs )
    2755             : {
    2756             :     Word16 i;
    2757             :     ivas_error error;
    2758             :     rendering_context rendCtx;
    2759             :     AUDIO_CONFIG outConfig;
    2760             :     input_mc *inputMc;
    2761             :     Word16 pos_idx;
    2762             : 
    2763         372 :     inputMc = (input_mc *) input;
    2764         372 :     rendCtx = inputMc->base.ctx;
    2765         372 :     outConfig = *rendCtx.pOutConfig;
    2766             : 
    2767         372 :     IF( !isIoConfigPairSupported( inConfig, outConfig ) )
    2768             :     {
    2769           0 :         return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED;
    2770             :     }
    2771         372 :     IF( NE_32( ( error = allocateMcLfeDelayBuffer_fx( &inputMc->lfeDelayBuffer_fx, MAX_BIN_DELAY_SAMPLES ) ), IVAS_ERR_OK ) )
    2772             :     {
    2773           0 :         return error;
    2774             :     }
    2775             : 
    2776         372 :     IF( NE_32( ( error = allocateInputBaseBufferData_fx( &inputMc->bufferData_fx, MAX_BUFFER_LENGTH ) ), IVAS_ERR_OK ) )
    2777             :     {
    2778           0 :         return error;
    2779             :     }
    2780         372 :     initRendInputBase_fx( &inputMc->base, inConfig, id, rendCtx, inputMc->bufferData_fx, MAX_BUFFER_LENGTH );
    2781             : 
    2782         372 :     setZeroPanMatrix_fx( inputMc->panGains_fx );
    2783             : 
    2784         372 :     inputMc->customLsInput = defaultCustomLs();
    2785         372 :     inputMc->tdRendWrapper = defaultTdRendWrapper();
    2786             : 
    2787         372 :     if ( hrtfs->hHrtfTD )
    2788             :     {
    2789           0 :         inputMc->tdRendWrapper.binaural_latency_ns = Mult_32_32( hrtfs->hHrtfTD->latency_s_fx, 1000000000 );
    2790             :     }
    2791         372 :     inputMc->tdRendWrapper.hHrtfTD = &hrtfs->hHrtfTD;
    2792         372 :     inputMc->crendWrapper = NULL;
    2793         372 :     inputMc->hReverb = NULL;
    2794         372 :     inputMc->hMcMasa = NULL;
    2795             : 
    2796        3348 :     FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
    2797             :     {
    2798        2976 :         initRotGainsWord32_fx( inputMc->rot_gains_prev_fx[pos_idx] );
    2799             :     }
    2800         372 :     inputMc->lfeRouting = defaultLfeRouting( inConfig, inputMc->customLsInput, outConfig, *inputMc->base.ctx.pCustomLsOut );
    2801         372 :     set32_fx( inputMc->lfeDelayBuffer_fx, 0, MAX_BIN_DELAY_SAMPLES );
    2802         372 :     inputMc->binauralDelaySmp = 0;
    2803         372 :     move16();
    2804             : 
    2805         372 :     test();
    2806         372 :     test();
    2807        2976 :     FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    2808             :     {
    2809        2604 :         if ( hrtfs->hHrtfTD )
    2810             :         {
    2811           0 :             inputMc->splitTdRendWrappers[i].binaural_latency_ns = Mult_32_32( hrtfs->hHrtfTD->latency_s_fx, 1000000000 );
    2812             :         }
    2813        2604 :         inputMc->splitTdRendWrappers[i].hHrtfTD = &hrtfs->hHrtfTD;
    2814             :     }
    2815             : 
    2816         372 :     IF( EQ_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) )
    2817             :     {
    2818             : 
    2819          96 :         IF( NE_32( ( error = initMcBinauralRendering( inputMc, inConfig, outConfig, hRendCfg, hrtfs->hSetOfHRTF, hrtfs->hHrtfStatistics, FALSE ) ), IVAS_ERR_OK ) )
    2820             :         {
    2821           0 :             return error;
    2822             :         }
    2823             :     }
    2824             : 
    2825         372 :     test();
    2826         372 :     IF( EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_16( outConfig, IVAS_AUDIO_CONFIG_MASA2 ) )
    2827             :     {
    2828           1 :         IF( NE_32( ( error = initMcMasaRendering( inputMc, inConfig, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    2829             :         {
    2830           0 :             return error;
    2831             :         }
    2832             :     }
    2833             : 
    2834         372 :     IF( NE_32( ( error = updateMcPanGains( inputMc, outConfig ) ), IVAS_ERR_OK ) )
    2835             :     {
    2836           0 :         return error;
    2837             :     }
    2838             : 
    2839         372 :     return IVAS_ERR_OK;
    2840             : }
    2841             : 
    2842         666 : static void clearInputMc(
    2843             :     input_mc *inputMc )
    2844             : {
    2845             :     rendering_context rendCtx;
    2846             :     Word16 i, num_poses;
    2847             : 
    2848         666 :     num_poses = 1;
    2849         666 :     move16();
    2850         666 :     if ( inputMc->base.ctx.pSplitRendWrapper != NULL )
    2851             :     {
    2852           0 :         num_poses = inputMc->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    2853           0 :         move16();
    2854             :     }
    2855             : 
    2856         666 :     rendCtx = inputMc->base.ctx;
    2857         666 :     freeMcLfeDelayBuffer_fx( &inputMc->lfeDelayBuffer_fx );
    2858         666 :     freeInputBaseBufferData_fx( &inputMc->bufferData_fx );
    2859         666 :     initRendInputBase_fx( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 );
    2860             : 
    2861             :     /* Free input's internal handles */
    2862         666 :     IF( inputMc->efapInWrapper.hEfap != NULL )
    2863             :     {
    2864          99 :         efap_free_data_fx( &inputMc->efapInWrapper.hEfap );
    2865             :     }
    2866             : 
    2867         666 :     ivas_rend_closeCrend( &inputMc->crendWrapper, num_poses );
    2868             : 
    2869         666 :     ivas_reverb_close( &inputMc->hReverb );
    2870             : 
    2871         666 :     IF( inputMc->tdRendWrapper.hBinRendererTd != NULL )
    2872             :     {
    2873          20 :         ivas_td_binaural_close_fx( &inputMc->tdRendWrapper.hBinRendererTd );
    2874             :     }
    2875             : 
    2876        5328 :     FOR( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i )
    2877             :     {
    2878        4662 :         IF( inputMc->splitTdRendWrappers[i].hBinRendererTd != NULL )
    2879             :         {
    2880           0 :             ivas_td_binaural_close_fx( &inputMc->splitTdRendWrappers[i].hBinRendererTd );
    2881           0 :             inputMc->splitTdRendWrappers[i].hHrtfTD = NULL;
    2882             :         }
    2883             :     }
    2884             : 
    2885         666 :     ivas_mcmasa_ana_close( &( inputMc->hMcMasa ) );
    2886             : 
    2887         666 :     return;
    2888             : }
    2889             : 
    2890          77 : static ivas_error initSbaPanGainsForMcOut(
    2891             :     input_sba *inputSba,
    2892             :     const AUDIO_CONFIG outConfig,
    2893             :     const LSSETUP_CUSTOM_STRUCT *outSetupCustom )
    2894             : {
    2895             :     Word16 ambiOrderIn;
    2896             :     Word16 chInIdx, chOutIdx;
    2897             :     Word32 *tmpDecMtx, *readPtr;
    2898             :     IVAS_OUTPUT_SETUP hOutSetup;
    2899             :     ivas_error error;
    2900             : 
    2901          77 :     IF( NE_32( ( error = getAmbisonicsOrder_fx( inputSba->base.inConfig, &ambiOrderIn ) ), IVAS_ERR_OK ) )
    2902             :     {
    2903           0 :         return error;
    2904             :     }
    2905             : 
    2906          77 :     IF( NE_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    2907             :     {
    2908           0 :         assert( !"Invalid configuration" );
    2909             :         return IVAS_ERR_WRONG_PARAMS;
    2910             :     }
    2911             : 
    2912          77 :     SWITCH( outConfig )
    2913             :     {
    2914           8 :         case IVAS_AUDIO_CONFIG_MONO:
    2915           8 :             hOutSetup.ls_azimuth_fx = ls_azimuth_CICP1_fx;
    2916           8 :             hOutSetup.ls_elevation_fx = ls_elevation_CICP1_fx;
    2917           8 :             ivas_output_init( &hOutSetup, outConfig );
    2918           8 :             BREAK;
    2919          60 :         case IVAS_AUDIO_CONFIG_STEREO:
    2920             :         case IVAS_AUDIO_CONFIG_5_1:
    2921             :         case IVAS_AUDIO_CONFIG_7_1:
    2922             :         case IVAS_AUDIO_CONFIG_5_1_2:
    2923             :         case IVAS_AUDIO_CONFIG_5_1_4:
    2924             :         case IVAS_AUDIO_CONFIG_7_1_4:
    2925          60 :             ivas_output_init( &hOutSetup, outConfig );
    2926          60 :             BREAK;
    2927           9 :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
    2928             :             // ivas_ls_custom_setup( &hOutSetup, (LSSETUP_CUSTOM_STRUCT *)outSetupCustom );
    2929           9 :             ivas_ls_custom_setup_fx( &hOutSetup, outSetupCustom );
    2930           9 :             BREAK;
    2931           0 :         default:
    2932           0 :             assert( !"Invalid speaker config" );
    2933             :             return IVAS_ERR_WRONG_PARAMS;
    2934             :     }
    2935             : 
    2936             :     /* obtain and copy over HOA decoding matrix */
    2937          77 :     tmpDecMtx = NULL;
    2938          77 :     IF( NE_32( ( error = ivas_sba_get_hoa_dec_matrix_fx( hOutSetup, &tmpDecMtx, ambiOrderIn ) ), IVAS_ERR_OK ) )
    2939             :     {
    2940           0 :         return error;
    2941             :     }
    2942             : 
    2943          77 :     readPtr = &tmpDecMtx[0];
    2944         705 :     FOR( chOutIdx = 0; chOutIdx < hOutSetup.nchan_out_woLFE + hOutSetup.num_lfe; ++chOutIdx )
    2945             :     {
    2946       10676 :         FOR( chInIdx = 0; chInIdx < SBA_NHARM_HOA3; ++chInIdx )
    2947             :         {
    2948       10048 :             test();
    2949       10048 :             IF( hOutSetup.num_lfe > 0 && EQ_16( chOutIdx, hOutSetup.index_lfe[0] ) )
    2950             :             {
    2951         832 :                 CONTINUE; /* nothing to be rendered to LFE */
    2952             :             }
    2953        9216 :             inputSba->hoaDecMtx_fx[chInIdx][chOutIdx] = L_shl_sat( *readPtr++, Q2 ); /* Q29 + Q2 = Q31 */
    2954        9216 :             move32();
    2955             :         }
    2956             :     }
    2957          77 :     free( tmpDecMtx );
    2958             : 
    2959          77 :     return IVAS_ERR_OK;
    2960             : }
    2961             : 
    2962          24 : static ivas_error initSbaPanGainsForSbaOut(
    2963             :     input_sba *inputSba,
    2964             :     const AUDIO_CONFIG outConfig )
    2965             : {
    2966             :     ivas_error error;
    2967          24 :     error = IVAS_ERR_OK;
    2968          24 :     move32();
    2969             : 
    2970          24 :     IF( NE_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) )
    2971             :     {
    2972           0 :         assert( !"Invalid configuration" );
    2973             :         return IVAS_ERR_WRONG_PARAMS;
    2974             :     }
    2975             : 
    2976          24 :     fillIdentityPanMatrix_fx( inputSba->hoaDecMtx_fx );
    2977             : 
    2978          24 :     return error;
    2979             : }
    2980             : 
    2981         126 : static ivas_error updateSbaPanGains(
    2982             :     input_sba *inputSba,
    2983             :     const AUDIO_CONFIG outConfig,
    2984             :     RENDER_CONFIG_DATA *hRendCfg,
    2985             :     IVAS_DEC_HRTF_CREND_HANDLE hMixconv,
    2986             :     IVAS_DEC_HRTF_STATISTICS_HANDLE hHrtfStatistics )
    2987             : {
    2988             :     ivas_error error;
    2989             :     AUDIO_CONFIG inConfig;
    2990             :     rendering_context rendCtx;
    2991             :     Word16 num_poses;
    2992             : 
    2993             :     /* Reset to all zeros - some functions below only write non-zero elements. */
    2994         126 :     setZeroPanMatrix_fx( inputSba->hoaDecMtx_fx );
    2995             : 
    2996         126 :     inConfig = inputSba->base.inConfig;
    2997         126 :     rendCtx = inputSba->base.ctx;
    2998             : 
    2999         126 :     num_poses = 1;
    3000         126 :     move16();
    3001         126 :     if ( rendCtx.pSplitRendWrapper != NULL )
    3002             :     {
    3003           0 :         num_poses = rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses;
    3004           0 :         move16();
    3005             :     }
    3006             : 
    3007         126 :     SWITCH( getAudioConfigType( outConfig ) )
    3008             :     {
    3009          65 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    3010          65 :             error = initSbaPanGainsForMcOut( inputSba, outConfig, inputSba->base.ctx.pCustomLsOut );
    3011          65 :             BREAK;
    3012          24 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    3013          24 :             error = initSbaPanGainsForSbaOut( inputSba, outConfig );
    3014          24 :             BREAK;
    3015          36 :         case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL:
    3016             :             SWITCH( outConfig )
    3017             :             {
    3018           0 :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
    3019             :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
    3020             :                 {
    3021           0 :                     IF( EQ_32( hRendCfg->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) )
    3022             : 
    3023             :                     {
    3024           0 :                         assert( inConfig == IVAS_AUDIO_CONFIG_HOA3 && ( *rendCtx.pOutSampleRate == 48000 ) && "split binaural fast conv mode is currently supported with HOA3 input and 48k sampling rate only" );
    3025           0 :                         if ( ( error = ivas_rend_openCldfbRend( &inputSba->cldfbRendWrapper, inConfig, outConfig, &rendCtx.pSplitRendWrapper->multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK )
    3026             :                         {
    3027           0 :                             return error;
    3028             :                         }
    3029             :                     }
    3030             :                     else
    3031             :                     {
    3032           0 :                         assert( ( *rendCtx.pOutSampleRate == 48000 ) && "split binaural crend mode is currently supported with 48k sampling rate only" );
    3033           0 :                         if ( ( error = ivas_rend_openMultiBinCrend( &inputSba->crendWrapper, inConfig, outConfig, &rendCtx.pSplitRendWrapper->multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK )
    3034             :                         {
    3035           0 :                             return error;
    3036             :                         }
    3037             :                     }
    3038           0 :                     break;
    3039             :                 }
    3040          24 :                 case IVAS_AUDIO_CONFIG_BINAURAL:
    3041             : #ifdef FIX_1129_EXT_REND_OUTPUT_HIGH
    3042             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    3043             : #endif
    3044             :                 {
    3045          24 :                     if ( hRendCfg->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV )
    3046             :                     {
    3047           0 :                         if ( ( error = ivas_rend_openCldfbRend( &inputSba->cldfbRendWrapper, inConfig, outConfig, &rendCtx.pSplitRendWrapper->multiBinPoseData, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK )
    3048             :                         {
    3049           0 :                             return error;
    3050             :                         }
    3051             :                     }
    3052             :                     else
    3053             :                     {
    3054          24 :                         IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, hMixconv, hHrtfStatistics, *rendCtx.pOutSampleRate, num_poses ) ), IVAS_ERR_OK ) )
    3055             :                         {
    3056           0 :                             return error;
    3057             :                         }
    3058             :                     }
    3059             :                 }
    3060          24 :                     BREAK;
    3061          12 :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
    3062             : #ifndef FIX_1129_EXT_REND_OUTPUT_HIGH
    3063             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    3064             : #endif
    3065          12 :                     IF( NE_32( ( error = initSbaPanGainsForMcOut( inputSba, IVAS_AUDIO_CONFIG_7_1_4, NULL ) ), IVAS_ERR_OK ) )
    3066             :                     {
    3067           0 :                         return error;
    3068             :                     }
    3069          12 :                     IF( NE_32( ( error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, hMixconv, hHrtfStatistics, *rendCtx.pOutSampleRate, num_poses ) ), IVAS_ERR_OK ) )
    3070             :                     {
    3071           0 :                         return error;
    3072             :                     }
    3073          12 :                     BREAK;
    3074           0 :                 default:
    3075           0 :                     return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    3076             :             }
    3077          36 :             BREAK;
    3078           1 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    3079           1 :             error = IVAS_ERR_OK;
    3080           1 :             move32();
    3081           1 :             BREAK; /* Do nothing */
    3082           0 :         default:
    3083           0 :             return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    3084             :     }
    3085             : 
    3086             :     /* Check error here to keep switch statement more compact */
    3087         126 :     IF( NE_32( error, IVAS_ERR_OK ) )
    3088             :     {
    3089           0 :         return error;
    3090             :     }
    3091             : 
    3092         126 :     return IVAS_ERR_OK;
    3093             : }
    3094             : 
    3095           1 : static ivas_error initSbaMasaRendering(
    3096             :     input_sba *inputSba,
    3097             :     Word32 inSampleRate )
    3098             : {
    3099             :     ivas_error error;
    3100             :     Word16 num_poses;
    3101             : 
    3102           1 :     num_poses = 1;
    3103           1 :     move16();
    3104           1 :     if ( inputSba->base.ctx.pSplitRendWrapper != NULL )
    3105             :     {
    3106           0 :         num_poses = inputSba->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    3107           0 :         move16();
    3108             :     }
    3109             : 
    3110           1 :     ivas_rend_closeCrend( &inputSba->crendWrapper, num_poses );
    3111             : 
    3112           1 :     IF( NE_32( ( error = ivas_dirac_ana_open_fx( &inputSba->hDirAC, inSampleRate ) ), IVAS_ERR_OK ) )
    3113             :     {
    3114           0 :         return error;
    3115             :     }
    3116             : 
    3117           1 :     return IVAS_ERR_OK;
    3118             : }
    3119             : 
    3120         126 : static ivas_error setRendInputActiveSba(
    3121             :     void *input,
    3122             :     const AUDIO_CONFIG inConfig,
    3123             :     const IVAS_REND_InputId id,
    3124             :     RENDER_CONFIG_DATA *hRendCfg,
    3125             :     hrtf_handles *hrtfs )
    3126             : {
    3127             :     ivas_error error;
    3128             :     rendering_context rendCtx;
    3129             :     AUDIO_CONFIG outConfig;
    3130             :     input_sba *inputSba;
    3131             :     Word16 pos_idx;
    3132             : 
    3133         126 :     inputSba = (input_sba *) input;
    3134         126 :     rendCtx = inputSba->base.ctx;
    3135         126 :     outConfig = *rendCtx.pOutConfig;
    3136         126 :     move32();
    3137             : 
    3138         126 :     IF( !isIoConfigPairSupported( inConfig, outConfig ) )
    3139             :     {
    3140           0 :         return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED;
    3141             :     }
    3142             : 
    3143         126 :     IF( NE_32( ( error = allocateInputBaseBufferData_fx( &inputSba->bufferData_fx, MAX_CLDFB_BUFFER_LENGTH ) ), IVAS_ERR_OK ) )
    3144             :     {
    3145           0 :         return error;
    3146             :     }
    3147             : 
    3148         126 :     initRendInputBase_fx( &inputSba->base, inConfig, id, rendCtx, inputSba->bufferData_fx, MAX_CLDFB_BUFFER_LENGTH );
    3149             : 
    3150         126 :     setZeroPanMatrix_fx( inputSba->hoaDecMtx_fx );
    3151             : 
    3152         126 :     inputSba->crendWrapper = NULL;
    3153         126 :     inputSba->hDirAC = NULL;
    3154        1134 :     FOR( pos_idx = 0; pos_idx < MAX_HEAD_ROT_POSES; pos_idx++ )
    3155             :     {
    3156        1008 :         initRotGains_fx( inputSba->rot_gains_prev_fx[pos_idx] );
    3157             :     }
    3158         126 :     inputSba->cldfbRendWrapper.hHrtfFastConv = hrtfs->hHrtfFastConv;
    3159             : 
    3160         126 :     test();
    3161         126 :     IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_MASA2 ) )
    3162             :     {
    3163           1 :         IF( NE_32( ( error = initSbaMasaRendering( inputSba, *rendCtx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    3164             :         {
    3165           0 :             return error;
    3166             :         }
    3167             :     }
    3168         126 :     IF( NE_32( ( error = updateSbaPanGains( inputSba, outConfig, hRendCfg, hrtfs->hSetOfHRTF, hrtfs->hHrtfStatistics ) ), IVAS_ERR_OK ) )
    3169             :     {
    3170           0 :         return error;
    3171             :     }
    3172             : 
    3173         126 :     return error;
    3174             : }
    3175             : 
    3176         666 : static void clearInputSba(
    3177             :     input_sba *inputSba )
    3178             : {
    3179             :     rendering_context rendCtx;
    3180             :     Word16 num_poses;
    3181             : 
    3182         666 :     rendCtx = inputSba->base.ctx;
    3183             : 
    3184         666 :     num_poses = 1;
    3185         666 :     move16();
    3186         666 :     if ( rendCtx.pSplitRendWrapper != NULL )
    3187             :     {
    3188           0 :         num_poses = rendCtx.pSplitRendWrapper->multiBinPoseData.num_poses;
    3189           0 :         move16();
    3190             :     }
    3191             : 
    3192         666 :     freeInputBaseBufferData_fx( &inputSba->bufferData_fx );
    3193             : 
    3194         666 :     initRendInputBase_fx( &inputSba->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 );
    3195             : 
    3196         666 :     ivas_rend_closeCrend( &inputSba->crendWrapper, num_poses );
    3197             : 
    3198         666 :     IF( inputSba->cldfbRendWrapper.hCldfbRend != NULL )
    3199             :     {
    3200           0 :         ivas_rend_closeCldfbRend( &inputSba->cldfbRendWrapper );
    3201             :     }
    3202             : 
    3203         666 :     ivas_dirac_ana_close_fx( &( inputSba->hDirAC ) );
    3204             : 
    3205         666 :     return;
    3206             : }
    3207             : 
    3208          49 : static ivas_error setRendInputActiveMasa(
    3209             :     void *input,
    3210             :     const AUDIO_CONFIG inConfig,
    3211             :     const IVAS_REND_InputId id,
    3212             :     RENDER_CONFIG_DATA *hRendCfg,
    3213             :     hrtf_handles *hrtfs )
    3214             : {
    3215             :     ivas_error error;
    3216             :     rendering_context rendCtx;
    3217             :     AUDIO_CONFIG outConfig;
    3218             :     input_masa *inputMasa;
    3219             :     Word16 numInChannels;
    3220             : 
    3221          49 :     inputMasa = (input_masa *) input;
    3222          49 :     rendCtx = inputMasa->base.ctx;
    3223          49 :     outConfig = *rendCtx.pOutConfig;
    3224          49 :     move32();
    3225             : 
    3226          49 :     IF( !isIoConfigPairSupported( inConfig, outConfig ) )
    3227             :     {
    3228           0 :         return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED;
    3229             :     }
    3230             : 
    3231          49 :     IF( NE_32( ( error = allocateInputBaseBufferData_fx( &inputMasa->bufferData_fx, MAX_BUFFER_LENGTH ) ), IVAS_ERR_OK ) )
    3232             :     {
    3233           0 :         return error;
    3234             :     }
    3235          49 :     initRendInputBase_fx( &inputMasa->base, inConfig, id, rendCtx, inputMasa->bufferData_fx, MAX_BUFFER_LENGTH );
    3236             : 
    3237          49 :     IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &numInChannels ) ), IVAS_ERR_OK ) )
    3238             :     {
    3239           0 :         return error;
    3240             :     }
    3241             : 
    3242          49 :     IF( EQ_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) )
    3243             :     {
    3244           1 :         inputMasa->metadataHasBeenFed = false;
    3245           1 :         move16();
    3246             :         Word16 temp;
    3247           1 :         IF( EQ_16( inputMasa->base.inConfig, IVAS_AUDIO_CONFIG_MASA1 ) )
    3248             :         {
    3249           0 :             temp = 1;
    3250             :         }
    3251             :         ELSE
    3252             :         {
    3253           1 :             temp = 2;
    3254             :         }
    3255           1 :         move16();
    3256           1 :         IF( NE_32( ( error = masaPrerendOpen_fx( &inputMasa->hMasaPrerend, temp, *( inputMasa->base.ctx.pOutSampleRate ) ) ), IVAS_ERR_OK ) )
    3257             :         {
    3258           0 :             return error;
    3259             :         }
    3260             :     }
    3261             :     ELSE
    3262             :     {
    3263          48 :         IF( NE_32( ( error = initMasaExtRenderer( inputMasa, outConfig, hRendCfg, hrtfs ) ), IVAS_ERR_OK ) )
    3264             :         {
    3265           0 :             return error;
    3266             :         }
    3267          48 :         inputMasa->metadataHasBeenFed = false;
    3268          48 :         move16();
    3269             :     }
    3270             : 
    3271          49 :     return IVAS_ERR_OK;
    3272             : }
    3273             : 
    3274         666 : static void clearInputMasa(
    3275             :     input_masa *inputMasa )
    3276             : {
    3277             :     rendering_context rendCtx;
    3278             : 
    3279         666 :     rendCtx = inputMasa->base.ctx;
    3280             : 
    3281         666 :     freeInputBaseBufferData_fx( &inputMasa->bufferData_fx );
    3282             : 
    3283         666 :     masaPrerendClose_fx( &inputMasa->hMasaPrerend );
    3284             : 
    3285         666 :     freeMasaExtRenderer( &inputMasa->hMasaExtRend );
    3286             : 
    3287         666 :     initRendInputBase_fx( &inputMasa->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 );
    3288             : 
    3289         666 :     return;
    3290             : }
    3291             : 
    3292             : 
    3293             : /*-------------------------------------------------------------------------
    3294             :  * IVAS_REND_Open()
    3295             :  *
    3296             :  *
    3297             :  *------------------------------------------------------------------------*/
    3298             : 
    3299         666 : ivas_error IVAS_REND_Open(
    3300             :     IVAS_REND_HANDLE *phIvasRend,      /* i/o: Pointer to renderer handle                          */
    3301             :     const Word32 outputSampleRate,     /* i  : output sampling rate                                */
    3302             :     const IVAS_AUDIO_CONFIG outConfig, /* i  : output audio config                                 */
    3303             :     const bool asHrtfBinary,           /* i  : load hrtf binary file                               */
    3304             :     const Word16 nonDiegeticPan,       /* i  : non-diegetic object flag                            */
    3305             :     const Word32 nonDiegeticPanGain,   /* i  : non-diegetic panning gain                        Q31*/
    3306             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3307             :     const Word16 Opt_Headrotation,        /* i  : indicates whether head-rotation is used             */
    3308             :     const Word16 Opt_ExternalOrientation, /* i  : indicates whether external orientations are used    */
    3309             : #endif
    3310             :     const Word16 num_subframes /* i  : number of subframes                                 */
    3311             : )
    3312             : {
    3313             :     Word16 i;
    3314             :     Word16 j;
    3315             :     IVAS_REND_HANDLE hIvasRend;
    3316             :     ivas_error error;
    3317             :     Word16 numOutChannels;
    3318             : 
    3319             :     /* Validate function arguments */
    3320         666 :     IF( phIvasRend == NULL )
    3321             :     {
    3322           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    3323             :     }
    3324             : 
    3325         666 :     IF( NE_32( ( error = validateOutputAudioConfig( outConfig ) ), IVAS_ERR_OK ) )
    3326             :     {
    3327           0 :         return error;
    3328             :     }
    3329             : 
    3330         666 :     IF( NE_32( ( error = validateOutputSampleRate( outputSampleRate, outConfig ) ), IVAS_ERR_OK ) )
    3331             :     {
    3332           0 :         return error;
    3333             :     }
    3334             : 
    3335         666 :     *phIvasRend = (IVAS_REND_HANDLE) malloc( sizeof( struct IVAS_REND ) );
    3336         666 :     IF( *phIvasRend == NULL )
    3337             :     {
    3338           0 :         return IVAS_ERR_FAILED_ALLOC;
    3339             :     }
    3340             : 
    3341         666 :     hIvasRend = *phIvasRend;
    3342         666 :     hIvasRend->sampleRateOut = outputSampleRate;
    3343         666 :     hIvasRend->outputConfig = outConfig;
    3344         666 :     hIvasRend->customLsOut = defaultCustomLs();
    3345         666 :     hIvasRend->hLimiter = NULL;
    3346         666 :     hIvasRend->efapOutWrapper.hEfap = NULL;
    3347         666 :     hIvasRend->efapOutWrapper.pCustomLsSetup = NULL;
    3348         666 :     hIvasRend->num_subframes = num_subframes;
    3349             : 
    3350             :     /* Initialize limiter */
    3351         666 :     IF( NE_32( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ), IVAS_ERR_OK ) )
    3352             :     {
    3353           0 :         return error;
    3354             :     }
    3355             : 
    3356         666 :     IF( NE_32( ( error = initLimiter( &hIvasRend->hLimiter, numOutChannels, outputSampleRate ) ), IVAS_ERR_OK ) )
    3357             :     {
    3358           0 :         return error;
    3359             :     }
    3360             : 
    3361             :     /* Initialize headrotation data */
    3362             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3363         666 :     hIvasRend->headRotData.headRotEnabled = 0;
    3364         666 :     IF( Opt_Headrotation )
    3365             :     {
    3366             : #endif
    3367          94 :         IF( NE_32( ( error = initHeadRotation_fx( hIvasRend ) ), IVAS_ERR_OK ) )
    3368             :         {
    3369           0 :             return error;
    3370             :         }
    3371             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3372             :     }
    3373             : #endif
    3374             : 
    3375             :     /* Initialize external orientation data */
    3376             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3377         666 :     hIvasRend->hExternalOrientationData = NULL;
    3378         666 :     IF( Opt_ExternalOrientation )
    3379             :     {
    3380             : #endif
    3381           0 :         IF( NE_32( ( error = ivas_external_orientation_open( &( hIvasRend->hExternalOrientationData ), num_subframes ) ), IVAS_ERR_OK ) )
    3382             :         {
    3383           0 :             return error;
    3384             :         }
    3385             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3386             :     }
    3387             : #endif
    3388             : 
    3389             :     /* Initilize combined orientation data */
    3390             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3391         666 :     hIvasRend->hCombinedOrientationData = NULL;
    3392         666 :     IF( Opt_Headrotation || Opt_ExternalOrientation )
    3393             :     {
    3394             : #endif
    3395          94 :         IF( NE_32( ( error = ivas_combined_orientation_open( &( hIvasRend->hCombinedOrientationData ), outputSampleRate, num_subframes ) ), IVAS_ERR_OK ) )
    3396             :         {
    3397           0 :             return error;
    3398             :         }
    3399             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3400             :     }
    3401             : #endif
    3402             : 
    3403             :     /* Initialize EFAP */
    3404         666 :     IF( NE_32( ( error = initEfap( &hIvasRend->efapOutWrapper, outConfig, &hIvasRend->customLsOut ) ), IVAS_ERR_OK ) )
    3405             :     {
    3406           0 :         return error;
    3407             :     }
    3408             : 
    3409             :     /* Initialize inputs */
    3410         666 :     hIvasRend->splitRendWrapper = NULL;
    3411         666 :     test();
    3412         666 :     IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    3413             :     {
    3414           0 :         if ( ( hIvasRend->splitRendWrapper = (SPLIT_REND_WRAPPER *) malloc( sizeof( SPLIT_REND_WRAPPER ) ) ) == NULL )
    3415             :         {
    3416           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Cannot allocate memory for IVAS renderer handle" );
    3417             :         }
    3418             : 
    3419           0 :         isar_init_split_rend_handles( hIvasRend->splitRendWrapper );
    3420             :     }
    3421             : 
    3422        3330 :     FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i )
    3423             :     {
    3424        2664 :         initRendInputBase_fx( &hIvasRend->inputsIsm[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 );
    3425        2664 :         hIvasRend->inputsIsm[i].crendWrapper = NULL;
    3426        2664 :         hIvasRend->inputsIsm[i].hReverb = NULL;
    3427        2664 :         hIvasRend->inputsIsm[i].tdRendWrapper.hBinRendererTd = NULL;
    3428       21312 :         FOR( j = 0; j < MAX_HEAD_ROT_POSES - 1; ++j )
    3429             :         {
    3430       18648 :             hIvasRend->inputsIsm[i].splitTdRendWrappers[j].hBinRendererTd = NULL;
    3431       18648 :             hIvasRend->inputsIsm[i].splitTdRendWrappers[j].hHrtfTD = NULL;
    3432             :         }
    3433        2664 :         hIvasRend->inputsIsm[i].nonDiegeticPan = nonDiegeticPan;
    3434        2664 :         move16();
    3435        2664 :         hIvasRend->inputsIsm[i].nonDiegeticPanGain_fx = nonDiegeticPanGain;
    3436        2664 :         move32();
    3437        2664 :         hIvasRend->inputsIsm[i].hOMasa = NULL;
    3438        2664 :         hIvasRend->inputsIsm[i].bufferData_fx = NULL;
    3439             :     }
    3440             : 
    3441        1332 :     FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
    3442             :     {
    3443         666 :         initRendInputBase_fx( &hIvasRend->inputsMc[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 );
    3444             : 
    3445         666 :         hIvasRend->inputsMc[i].efapInWrapper.hEfap = NULL;
    3446         666 :         hIvasRend->inputsMc[i].crendWrapper = NULL;
    3447         666 :         hIvasRend->inputsMc[i].hReverb = NULL;
    3448         666 :         hIvasRend->inputsMc[i].tdRendWrapper.hBinRendererTd = NULL;
    3449         666 :         hIvasRend->inputsMc[i].bufferData_fx = NULL;
    3450         666 :         hIvasRend->inputsMc[i].lfeDelayBuffer_fx = NULL;
    3451         666 :         hIvasRend->inputsMc[i].nonDiegeticPan = nonDiegeticPan;
    3452         666 :         move16();
    3453         666 :         hIvasRend->inputsMc[i].nonDiegeticPanGain_fx = nonDiegeticPanGain;
    3454         666 :         move32();
    3455         666 :         hIvasRend->inputsMc[i].hMcMasa = NULL;
    3456        5328 :         FOR( j = 0; j < MAX_HEAD_ROT_POSES - 1; ++j )
    3457             :         {
    3458        4662 :             hIvasRend->inputsMc[i].splitTdRendWrappers[j].hBinRendererTd = NULL;
    3459        4662 :             hIvasRend->inputsMc[i].splitTdRendWrappers[j].hHrtfTD = NULL;
    3460             :         }
    3461             :     }
    3462             : 
    3463        1332 :     FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i )
    3464             :     {
    3465         666 :         initRendInputBase_fx( &hIvasRend->inputsSba[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 );
    3466             : 
    3467         666 :         hIvasRend->inputsSba[i].crendWrapper = NULL;
    3468         666 :         hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend = NULL;
    3469         666 :         hIvasRend->inputsSba[i].cldfbRendWrapper.hHrtfFastConv = NULL;
    3470         666 :         hIvasRend->inputsSba[i].bufferData_fx = NULL;
    3471         666 :         hIvasRend->inputsSba[i].hDirAC = NULL;
    3472             :     }
    3473             : 
    3474        1332 :     FOR( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i )
    3475             :     {
    3476         666 :         initRendInputBase_fx( &hIvasRend->inputsMasa[i].base, IVAS_AUDIO_CONFIG_INVALID, 0, getRendCtx( hIvasRend ), NULL, 0 );
    3477             : 
    3478         666 :         hIvasRend->inputsMasa[i].metadataHasBeenFed = false;
    3479         666 :         hIvasRend->inputsMasa[i].bufferData_fx = NULL;
    3480         666 :         hIvasRend->inputsMasa[i].hMasaPrerend = NULL;
    3481         666 :         hIvasRend->inputsMasa[i].hMasaExtRend = NULL;
    3482         666 :         move16();
    3483             :     }
    3484             : 
    3485         666 :     hIvasRend->hHrtfs.hHrtfFastConv = NULL;
    3486         666 :     hIvasRend->hHrtfs.hHrtfParambin = NULL;
    3487         666 :     hIvasRend->hHrtfs.hHrtfTD = NULL;
    3488         666 :     hIvasRend->hHrtfs.hSetOfHRTF = NULL;
    3489         666 :     hIvasRend->hHrtfs.hHrtfStatistics = NULL;
    3490         666 :     IF( asHrtfBinary )
    3491             :     {
    3492           0 :         IF( NE_32( ( error = ivas_HRTF_binary_open_fx( &( hIvasRend->hHrtfs.hHrtfTD ) ) ), IVAS_ERR_OK ) )
    3493             :         {
    3494           0 :             return error;
    3495             :         }
    3496           0 :         IF( NE_32( ( error = ivas_HRTF_CRend_binary_open_fx( &( hIvasRend->hHrtfs.hSetOfHRTF ) ) ), IVAS_ERR_OK ) )
    3497             :         {
    3498           0 :             return error;
    3499             :         }
    3500           0 :         IF( NE_32( ( error = ivas_HRTF_fastconv_binary_open_fx( &( hIvasRend->hHrtfs.hHrtfFastConv ) ) ), IVAS_ERR_OK ) )
    3501             :         {
    3502           0 :             return error;
    3503             :         }
    3504           0 :         IF( NE_32( ( error = ivas_HRTF_parambin_binary_open_fx( &( hIvasRend->hHrtfs.hHrtfParambin ) ) ), IVAS_ERR_OK ) )
    3505             :         {
    3506           0 :             return error;
    3507             :         }
    3508           0 :         IF( NE_32( ( error = ivas_HRTF_statistics_binary_open( &( hIvasRend->hHrtfs.hHrtfStatistics ) ) ), IVAS_ERR_OK ) )
    3509             :         {
    3510           0 :             return error;
    3511             :         }
    3512             :     }
    3513             : 
    3514             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3515         666 :     IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) )
    3516             :     {
    3517             : #endif
    3518          60 :         IF( NE_32( ( error = ivas_HRTF_statistics_init( &( hIvasRend->hHrtfs.hHrtfStatistics ), hIvasRend->sampleRateOut ) ), IVAS_ERR_OK ) )
    3519             :         {
    3520           0 :             return error;
    3521             :         }
    3522             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    3523             :     }
    3524             : #endif
    3525             : 
    3526         666 :     return IVAS_ERR_OK;
    3527             : }
    3528             : 
    3529             : 
    3530         152 : static LSSETUP_CUSTOM_STRUCT makeCustomLsSetup(
    3531             :     const IVAS_CUSTOM_LS_DATA rendCustomLsLayout )
    3532             : {
    3533             :     Word16 i;
    3534             :     LSSETUP_CUSTOM_STRUCT customLs;
    3535             : 
    3536             :     /* Copy layout description */
    3537         152 :     customLs.num_spk = rendCustomLsLayout.num_spk;
    3538         152 :     move16();
    3539         152 :     Copy32( rendCustomLsLayout.azimuth_fx, customLs.ls_azimuth_fx, rendCustomLsLayout.num_spk );
    3540         152 :     Copy32( rendCustomLsLayout.elevation_fx, customLs.ls_elevation_fx, rendCustomLsLayout.num_spk );
    3541         152 :     customLs.is_planar_setup = 1;
    3542         152 :     move16();
    3543         776 :     FOR( i = 0; i < rendCustomLsLayout.num_spk; ++i )
    3544             :     {
    3545         776 :         IF( fabsf( rendCustomLsLayout.elevation[i] ) > EPSILON )
    3546             :         {
    3547         152 :             customLs.is_planar_setup = 0;
    3548         152 :             move16();
    3549         152 :             BREAK;
    3550             :         }
    3551             :     }
    3552             : 
    3553         152 :     customLs.num_lfe = rendCustomLsLayout.num_lfe;
    3554         152 :     move16();
    3555         152 :     Copy( rendCustomLsLayout.lfe_idx, customLs.lfe_idx, rendCustomLsLayout.num_lfe );
    3556             : 
    3557         152 :     return customLs;
    3558             : }
    3559             : 
    3560             : 
    3561         152 : static ivas_error validateCustomLsLayout_fx(
    3562             :     const IVAS_CUSTOM_LS_DATA layout )
    3563             : {
    3564             :     Word16 i;
    3565             : 
    3566             :     /* Negative number of speakers or LFEs makes no sense */
    3567         152 :     test();
    3568         152 :     IF( layout.num_spk < 0 || layout.num_lfe < 0 )
    3569             :     {
    3570           0 :         return IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT;
    3571             :     }
    3572             : 
    3573             :     /* There must be at least one speaker or LFE in the layout */
    3574         152 :     IF( add( layout.num_spk, layout.num_lfe ) <= 0 )
    3575             :     {
    3576           0 :         return IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT;
    3577             :     }
    3578             : 
    3579             :     /* LFE indices must be positive */
    3580         152 :     FOR( i = 0; i < layout.num_lfe; ++i )
    3581             :     {
    3582           0 :         IF( layout.lfe_idx[i] < 0 )
    3583             :         {
    3584           0 :             return IVAS_ERR_INVALID_CUSTOM_LS_LAYOUT;
    3585             :         }
    3586             :     }
    3587             : 
    3588         152 :     return IVAS_ERR_OK;
    3589             : }
    3590             : 
    3591             : 
    3592             : /*-------------------------------------------------------------------*
    3593             :  * IVAS_REND_ConfigureCustomOutputLoudspeakerLayout()
    3594             :  *
    3595             :  *
    3596             :  *-------------------------------------------------------------------*/
    3597             : 
    3598          47 : ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout(
    3599             :     IVAS_REND_HANDLE hIvasRend,
    3600             :     const IVAS_CUSTOM_LS_DATA layout )
    3601             : {
    3602             :     Word16 i, numOutChannels;
    3603             :     ivas_error error;
    3604             :     input_mc *inputMc;
    3605             :     input_sba *inputSba;
    3606             : 
    3607             :     /* Validate function arguments */
    3608          47 :     IF( hIvasRend == NULL )
    3609             :     {
    3610           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    3611             :     }
    3612             : 
    3613          47 :     IF( NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    3614             :     {
    3615             :         /* Specifying details of custom speaker layout only makes sense if output config is set to custom speaker layout */
    3616           0 :         return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    3617             :     }
    3618             : 
    3619          47 :     IF( NE_32( ( error = validateCustomLsLayout_fx( layout ) ), IVAS_ERR_OK ) )
    3620             :     {
    3621           0 :         return error;
    3622             :     }
    3623             : 
    3624          47 :     hIvasRend->customLsOut = makeCustomLsSetup( layout );
    3625             : 
    3626             :     /* Re-initialize limiter - number of output channels may have changed */
    3627          47 :     IF( NE_32( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ), IVAS_ERR_OK ) )
    3628             :     {
    3629           0 :         return error;
    3630             :     }
    3631             : 
    3632          47 :     IF( NE_32( ( error = initLimiter( &hIvasRend->hLimiter, numOutChannels, hIvasRend->sampleRateOut ) ), IVAS_ERR_OK ) )
    3633             :     {
    3634           0 :         return error;
    3635             :     }
    3636             : 
    3637             :     /* Re-initialize EFAP - output layout has changed or has been fully defined for the first time */
    3638          47 :     IF( NE_32( ( error = initEfap( &hIvasRend->efapOutWrapper, hIvasRend->outputConfig, &hIvasRend->customLsOut ) ), IVAS_ERR_OK ) )
    3639             :     {
    3640           0 :         return error;
    3641             :     }
    3642             : 
    3643             :     /* Re-initialize panning gains for each active MC input, This includes re-initializing
    3644             :      * LFE handling for the new output layout, which means custom LFE handling is overwritten,
    3645             :      * if previously set for any MC input. */
    3646          94 :     FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
    3647             :     {
    3648          47 :         inputMc = &hIvasRend->inputsMc[i];
    3649          47 :         IF( EQ_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    3650             :         {
    3651             :             /* Input inactive, skip. */
    3652          47 :             CONTINUE;
    3653             :         }
    3654             : 
    3655           0 :         inputMc->lfeRouting = defaultLfeRouting( inputMc->base.inConfig, inputMc->customLsInput, hIvasRend->outputConfig, *inputMc->base.ctx.pCustomLsOut );
    3656             : 
    3657           0 :         IF( NE_32( ( error = updateMcPanGains( inputMc, hIvasRend->outputConfig ) ), IVAS_ERR_OK ) )
    3658             :         {
    3659           0 :             return error;
    3660             :         }
    3661             :     }
    3662             : 
    3663             :     /* Re-initialize panning gains for each active SBA input */
    3664          94 :     FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i )
    3665             :     {
    3666          47 :         inputSba = &hIvasRend->inputsSba[i];
    3667             : 
    3668          47 :         IF( EQ_32( inputSba->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    3669             :         {
    3670             :             /* Input inactive, skip. */
    3671          47 :             CONTINUE;
    3672             :         }
    3673           0 :         IF( NE_32( ( error = updateSbaPanGains( inputSba, hIvasRend->outputConfig, hIvasRend->hRendererConfig, NULL, NULL ) ), IVAS_ERR_OK ) )
    3674             :         {
    3675           0 :             return error;
    3676             :         }
    3677             :     }
    3678             : 
    3679          47 :     return IVAS_ERR_OK;
    3680             : }
    3681             : 
    3682             : /*-------------------------------------------------------------------*
    3683             :  * IVAS_REND_NumOutChannels()
    3684             :  *
    3685             :  *
    3686             :  *-------------------------------------------------------------------*/
    3687             : 
    3688     1127519 : ivas_error IVAS_REND_NumOutChannels(
    3689             :     IVAS_REND_CONST_HANDLE hIvasRend,
    3690             :     Word16 *numOutChannels )
    3691             : {
    3692             :     ivas_error error;
    3693             : 
    3694             :     /* Validate function arguments */
    3695     1127519 :     test();
    3696     1127519 :     IF( hIvasRend == NULL || numOutChannels == NULL )
    3697             :     {
    3698           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    3699             :     }
    3700             : 
    3701             :     /* Handle special cases where additional info is needed from the renderer, otherwise use getAudioConfigNumChannels() */
    3702     1127519 :     SWITCH( hIvasRend->outputConfig )
    3703             :     {
    3704       36003 :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
    3705       36003 :             *numOutChannels = add( hIvasRend->customLsOut.num_spk, hIvasRend->customLsOut.num_lfe );
    3706       36003 :             move16();
    3707       36003 :             BREAK;
    3708     1091516 :         default:
    3709     1091516 :             IF( NE_32( ( error = getAudioConfigNumChannels( hIvasRend->outputConfig, numOutChannels ) ), IVAS_ERR_OK ) )
    3710             :             {
    3711           0 :                 return error;
    3712             :             }
    3713     1091516 :             BREAK;
    3714             :     }
    3715             : 
    3716     1127519 :     return IVAS_ERR_OK;
    3717             : }
    3718             : 
    3719             : 
    3720         973 : static IVAS_REND_InputId makeInputId(
    3721             :     AUDIO_CONFIG config,
    3722             :     const Word32 inputIndex )
    3723             : {
    3724             :     /* Put config type in second byte (from LSB), put index + 1 in first byte
    3725             :      *
    3726             :      * Index is incremented here so that a valid ID can never be 0. */
    3727         973 :     return (IVAS_REND_InputId) UL_or( UL_lshl( ( (UWord32) getAudioConfigType( config ) ), 8 ), L_add( inputIndex, 1 ) );
    3728             : }
    3729             : 
    3730             : 
    3731     3133018 : static ivas_error getInputById(
    3732             :     IVAS_REND_HANDLE hIvasRend,
    3733             :     IVAS_REND_InputId inputId,
    3734             :     void **ppInput )
    3735             : {
    3736             :     Word32 inputIndex;
    3737             :     IVAS_REND_AudioConfigType configType;
    3738             :     input_base *pInputBase;
    3739             : 
    3740             :     /* Reverse makeInputId() */
    3741     3133018 :     inputIndex = L_sub( L_and( inputId, 0xFF ), 1 );
    3742     3133018 :     configType = L_shr( L_and( inputId, 0xFF00 ), 8 );
    3743             : 
    3744             :     /* Validate values derived from input ID */
    3745     3133018 :     IF( inputIndex < 0 )
    3746             :     {
    3747           0 :         return IVAS_ERR_INVALID_INPUT_ID;
    3748             :     }
    3749     3133018 :     SWITCH( configType )
    3750             :     {
    3751     2495576 :         case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED:
    3752     2495576 :             IF( GT_32( inputIndex, RENDERER_MAX_ISM_INPUTS ) )
    3753             :             {
    3754           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3755             :             }
    3756     2495576 :             pInputBase = &hIvasRend->inputsIsm[inputIndex].base;
    3757     2495576 :             BREAK;
    3758      360012 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    3759      360012 :             IF( GT_32( inputIndex, RENDERER_MAX_MC_INPUTS ) )
    3760             :             {
    3761           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3762             :             }
    3763      360012 :             pInputBase = &hIvasRend->inputsMc[inputIndex].base;
    3764      360012 :             BREAK;
    3765      251881 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    3766      251881 :             IF( GT_32( inputIndex, RENDERER_MAX_SBA_INPUTS ) )
    3767             :             {
    3768           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3769             :             }
    3770      251881 :             pInputBase = &hIvasRend->inputsSba[inputIndex].base;
    3771      251881 :             BREAK;
    3772       25549 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    3773       25549 :             IF( GT_32( inputIndex, RENDERER_MAX_MASA_INPUTS ) )
    3774             :             {
    3775           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3776             :             }
    3777       25549 :             pInputBase = &hIvasRend->inputsMasa[inputIndex].base;
    3778       25549 :             BREAK;
    3779           0 :         default:
    3780           0 :             return IVAS_ERR_INVALID_INPUT_ID;
    3781             :     }
    3782             : 
    3783             :     /* Ensure input ID matches and that input is active */
    3784     3133018 :     test();
    3785     3133018 :     IF( NE_32( pInputBase->id, inputId ) || EQ_32( pInputBase->inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    3786             :     {
    3787           0 :         return IVAS_ERR_INVALID_INPUT_ID;
    3788             :     }
    3789             : 
    3790             :     /* Validation done, set value via output parameter */
    3791     3133018 :     *ppInput = pInputBase;
    3792             : 
    3793     3133018 :     return IVAS_ERR_OK;
    3794             : }
    3795             : 
    3796             : 
    3797      630413 : static ivas_error getConstInputById(
    3798             :     IVAS_REND_CONST_HANDLE hIvasRend,
    3799             :     const IVAS_REND_InputId inputId,
    3800             :     const void **ppInput )
    3801             : {
    3802             :     Word32 inputIndex;
    3803             :     IVAS_REND_AudioConfigType configType;
    3804             :     const input_base *pInputBase;
    3805             : 
    3806             :     /* Reverse makeInputId() */
    3807      630413 :     inputIndex = L_sub( L_and( inputId, 0xFF ), 1 );
    3808      630413 :     configType = L_shr( L_and( inputId, 0xFF00 ), 8 );
    3809             : 
    3810             :     /* Validate values derived from input ID */
    3811      630413 :     IF( inputIndex < 0 )
    3812             :     {
    3813           0 :         return IVAS_ERR_INVALID_INPUT_ID;
    3814             :     }
    3815      630413 :     SWITCH( configType )
    3816             :     {
    3817         426 :         case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED:
    3818         426 :             IF( GT_32( inputIndex, RENDERER_MAX_ISM_INPUTS ) )
    3819             :             {
    3820           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3821             :             }
    3822         426 :             pInputBase = &hIvasRend->inputsIsm[inputIndex].base;
    3823         426 :             BREAK;
    3824      359907 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    3825      359907 :             IF( GT_32( inputIndex, RENDERER_MAX_MC_INPUTS ) )
    3826             :             {
    3827           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3828             :             }
    3829      359907 :             pInputBase = &hIvasRend->inputsMc[inputIndex].base;
    3830      359907 :             BREAK;
    3831      251881 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    3832      251881 :             IF( GT_32( inputIndex, RENDERER_MAX_SBA_INPUTS ) )
    3833             :             {
    3834           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3835             :             }
    3836      251881 :             pInputBase = &hIvasRend->inputsSba[inputIndex].base;
    3837      251881 :             BREAK;
    3838       18199 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    3839       18199 :             IF( GT_32( inputIndex, RENDERER_MAX_MASA_INPUTS ) )
    3840             :             {
    3841           0 :                 return IVAS_ERR_INVALID_INPUT_ID;
    3842             :             }
    3843       18199 :             pInputBase = &hIvasRend->inputsMasa[inputIndex].base;
    3844       18199 :             BREAK;
    3845           0 :         default:
    3846           0 :             return IVAS_ERR_INVALID_INPUT_ID;
    3847             :     }
    3848             : 
    3849             :     /* Ensure input ID matches and that input is active */
    3850      630413 :     test();
    3851      630413 :     IF( NE_32( pInputBase->id, inputId ) || EQ_32( pInputBase->inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    3852             :     {
    3853           0 :         return IVAS_ERR_INVALID_INPUT_ID;
    3854             :     }
    3855             : 
    3856             :     /* Validation done, set value via output parameter */
    3857      630413 :     *ppInput = pInputBase;
    3858             : 
    3859      630413 :     return IVAS_ERR_OK;
    3860             : }
    3861             : 
    3862         973 : static ivas_error findFreeInputSlot_fx(
    3863             :     const void *inputs,
    3864             :     const Word32 inputStructSize,
    3865             :     const Word32 maxInputs,
    3866             :     Word32 *inputIndex )
    3867             : {
    3868             :     /* Using a void pointer and a separately provided size is a hack for this function
    3869             :            to be reusable for arrays of any input type (input_ism, input_mc, input_sba, input_masa).
    3870             :             Assumptions:
    3871             :                 - input_base is always the first member in the input struct
    3872             :                 - provided size is correct
    3873             :         */
    3874             : 
    3875             :     Word32 i;
    3876             :     bool canAddInput;
    3877             :     const UWord8 *pByte;
    3878             :     const input_base *pInputBase;
    3879             : 
    3880         973 :     canAddInput = false;
    3881         973 :     move16();
    3882             : 
    3883             :     /* Find first unused input in array */
    3884        1353 :     FOR( ( i = 0, pByte = inputs ); i < maxInputs; ( ++i, pByte += inputStructSize ) )
    3885             :     {
    3886        1353 :         pInputBase = (const input_base *) pByte;
    3887             : 
    3888        1353 :         IF( EQ_32( pInputBase->inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    3889             :         {
    3890         973 :             *inputIndex = i;
    3891         973 :             move32();
    3892         973 :             canAddInput = true;
    3893         973 :             move16();
    3894         973 :             BREAK;
    3895             :         }
    3896             :     }
    3897             : 
    3898         973 :     IF( !canAddInput )
    3899             :     {
    3900           0 :         return IVAS_ERR_TOO_MANY_INPUTS;
    3901             :     }
    3902             : 
    3903         973 :     return IVAS_ERR_OK;
    3904             : }
    3905             : 
    3906             : 
    3907             : /*-------------------------------------------------------------------------
    3908             :  * Function getCldfbRendFlag()
    3909             :  *
    3910             :  *
    3911             :  *------------------------------------------------------------------------*/
    3912             : 
    3913           0 : static Word16 getCldfbRendFlag(
    3914             :     IVAS_REND_HANDLE hIvasRend, /* i  : Renderer handle               */
    3915             :     const IVAS_REND_AudioConfigType new_configType )
    3916             : {
    3917             :     Word16 i;
    3918           0 :     Word16 numMasaInputs = 0, numSbaInputs = 0, numIsmInputs = 0, numMcInputs = 0;
    3919             :     Word16 isCldfbRend;
    3920             : 
    3921           0 :     move16();
    3922           0 :     move16();
    3923           0 :     move16();
    3924           0 :     move16();
    3925             : 
    3926           0 :     isCldfbRend = 0;
    3927           0 :     move16();
    3928             : 
    3929           0 :     IF( hIvasRend->hRendererConfig != NULL )
    3930             :     {
    3931           0 :         FOR( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i )
    3932             :         {
    3933           0 :             numMasaInputs = add( numMasaInputs, ( hIvasRend->inputsMasa[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) ? 0 : 1 );
    3934           0 :             move16();
    3935             :         }
    3936           0 :         FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i )
    3937             :         {
    3938           0 :             numSbaInputs = add( numSbaInputs, ( hIvasRend->inputsSba[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ? 0 : 1 );
    3939           0 :             move16();
    3940             :         }
    3941           0 :         FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i )
    3942             :         {
    3943           0 :             numIsmInputs = add( numIsmInputs, ( hIvasRend->inputsIsm[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) ? 0 : 1 );
    3944           0 :             move16();
    3945             :         }
    3946           0 :         FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
    3947             :         {
    3948           0 :             numMcInputs = add( numMcInputs, ( hIvasRend->inputsMc[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ? 0 : 1 );
    3949           0 :             move16();
    3950             :         }
    3951             : 
    3952           0 :         IF( GT_16( numIsmInputs, 0 ) || GT_16( numMcInputs, 0 ) )
    3953             :         {
    3954           0 :             isCldfbRend = 0;
    3955           0 :             move16();
    3956             :         }
    3957           0 :         ELSE IF( GT_16( numMasaInputs, 0 ) || ( GT_16( numSbaInputs, 0 ) && EQ_32( hIvasRend->hRendererConfig->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) ) )
    3958             :         {
    3959           0 :             isCldfbRend = 1;
    3960           0 :             move16();
    3961             :         }
    3962             :     }
    3963             : 
    3964           0 :     return isCldfbRend;
    3965             : }
    3966             : 
    3967             : 
    3968             : /*-------------------------------------------------------------------------
    3969             :  * Function ivas_pre_rend_init()
    3970             :  *
    3971             :  *
    3972             :  *------------------------------------------------------------------------*/
    3973             : 
    3974           0 : static ivas_error ivas_pre_rend_init(
    3975             :     SPLIT_REND_WRAPPER *pSplitRendWrapper,
    3976             :     IVAS_REND_AudioBuffer *pSplitRendEncBuffer,
    3977             :     ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config,
    3978             :     IVAS_REND_HeadRotData headRotData,
    3979             :     const Word32 outputSampleRate,
    3980             :     const AUDIO_CONFIG outConfig,
    3981             :     const Word16 cldfb_in_flag,
    3982             :     const Word16 num_subframes )
    3983             : {
    3984             :     ivas_error error;
    3985             :     IVAS_REND_AudioBufferConfig bufConfig;
    3986             : 
    3987           0 :     test();
    3988           0 :     IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    3989             :     {
    3990           0 :         IF( EQ_32( pSplit_rend_config->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) )
    3991             :         {
    3992           0 :             ISAR_PRE_REND_GetMultiBinPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData, headRotData.sr_pose_pred_axis );
    3993             :         }
    3994           0 :         ELSE IF( EQ_32( pSplit_rend_config->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) )
    3995             :         {
    3996           0 :             isar_renderSplitUpdateNoCorrectionPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData );
    3997             :         }
    3998             : 
    3999           0 :         IF( ( error = ISAR_PRE_REND_open( pSplitRendWrapper, pSplit_rend_config, outputSampleRate, cldfb_in_flag, outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM, num_subframes, 0 ) ) != IVAS_ERR_OK )
    4000             :         {
    4001           0 :             return error;
    4002             :         }
    4003             : 
    4004             :         /*allocate for CLDFB in and change to TD during process if needed*/
    4005           0 :         bufConfig.numSamplesPerChannel = MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL;
    4006           0 :         bufConfig.numChannels = i_mult( BINAURAL_CHANNELS, pSplitRendWrapper->multiBinPoseData.num_poses );
    4007           0 :         bufConfig.is_cldfb = 1;
    4008           0 :         pSplitRendEncBuffer->config = bufConfig;
    4009           0 :         move16();
    4010           0 :         move16();
    4011           0 :         move16();
    4012           0 :         move32();
    4013             : 
    4014           0 :         IF( ( pSplitRendEncBuffer->data_fx = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL )
    4015             :         {
    4016           0 :             return IVAS_ERR_FAILED_ALLOC;
    4017             :         }
    4018             : 
    4019           0 :         pSplitRendEncBuffer->q_factor = 0;
    4020           0 :         pSplitRendEncBuffer->pq_fact = &pSplitRendEncBuffer->q_factor;
    4021             :     }
    4022             :     ELSE
    4023             :     {
    4024             :         IVAS_REND_AudioBufferConfig bufConfig2;
    4025             : 
    4026           0 :         bufConfig2.numSamplesPerChannel = 0;
    4027           0 :         bufConfig2.numChannels = 0;
    4028           0 :         bufConfig2.is_cldfb = 0;
    4029           0 :         pSplitRendEncBuffer->config = bufConfig2;
    4030           0 :         pSplitRendEncBuffer->data_fx = NULL;
    4031           0 :         pSplitRendEncBuffer->pq_fact = NULL;
    4032           0 :         pSplitRendEncBuffer->q_factor = 0;
    4033           0 :         move16();
    4034           0 :         move16();
    4035           0 :         move16();
    4036           0 :         move32();
    4037           0 :         move32();
    4038             :     }
    4039             : 
    4040           0 :     return IVAS_ERR_OK;
    4041             : }
    4042             : 
    4043             : 
    4044             : /*-------------------------------------------------------------------*
    4045             :  * IVAS_REND_AddInput()
    4046             :  *
    4047             :  *
    4048             :  *-------------------------------------------------------------------*/
    4049             : 
    4050         973 : ivas_error IVAS_REND_AddInput_fx(
    4051             :     IVAS_REND_HANDLE hIvasRend,  /* i/o: Renderer handle               */
    4052             :     const AUDIO_CONFIG inConfig, /* i  : audio config for a new input  */
    4053             :     IVAS_REND_InputId *inputId   /* o  : ID of the new input           */
    4054             : )
    4055             : {
    4056             :     ivas_error error;
    4057             :     Word32 maxNumInputsOfType;
    4058             :     void *inputsArray;
    4059             :     Word32 inputStructSize;
    4060             :     ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, RENDER_CONFIG_DATA *, hrtf_handles *hrtfs );
    4061             :     Word32 inputIndex;
    4062             : 
    4063             :     /* Validate function arguments */
    4064         973 :     test();
    4065         973 :     IF( hIvasRend == NULL || inputId == NULL )
    4066             :     {
    4067           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4068             :     }
    4069             : 
    4070         973 :     IF( ( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) && hIvasRend->splitRendEncBuffer.data_fx == NULL && hIvasRend->hRendererConfig != NULL )
    4071             :     {
    4072             :         Word16 cldfb_in_flag;
    4073           0 :         cldfb_in_flag = getCldfbRendFlag( hIvasRend, getAudioConfigType( inConfig ) );
    4074             : 
    4075           0 :         IF( ( error = ivas_pre_rend_init( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK )
    4076             :         {
    4077           0 :             return error;
    4078             :         }
    4079             :     }
    4080             : 
    4081             : 
    4082         973 :     SWITCH( getAudioConfigType( inConfig ) )
    4083             :     {
    4084         426 :         case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED:
    4085         426 :             maxNumInputsOfType = RENDERER_MAX_ISM_INPUTS;
    4086         426 :             inputsArray = hIvasRend->inputsIsm;
    4087         426 :             inputStructSize = sizeof( *hIvasRend->inputsIsm );
    4088         426 :             activateInput = setRendInputActiveIsm;
    4089         426 :             move32();
    4090         426 :             move32();
    4091         426 :             BREAK;
    4092         372 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    4093         372 :             maxNumInputsOfType = RENDERER_MAX_MC_INPUTS;
    4094         372 :             inputsArray = hIvasRend->inputsMc;
    4095         372 :             inputStructSize = sizeof( *hIvasRend->inputsMc );
    4096         372 :             activateInput = setRendInputActiveMc;
    4097         372 :             move32();
    4098         372 :             move32();
    4099         372 :             BREAK;
    4100         126 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    4101         126 :             maxNumInputsOfType = RENDERER_MAX_SBA_INPUTS;
    4102         126 :             inputsArray = hIvasRend->inputsSba;
    4103         126 :             inputStructSize = sizeof( *hIvasRend->inputsSba );
    4104         126 :             activateInput = setRendInputActiveSba;
    4105         126 :             move32();
    4106         126 :             move32();
    4107         126 :             BREAK;
    4108          49 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    4109          49 :             maxNumInputsOfType = RENDERER_MAX_MASA_INPUTS;
    4110          49 :             inputsArray = hIvasRend->inputsMasa;
    4111          49 :             inputStructSize = sizeof( *hIvasRend->inputsMasa );
    4112          49 :             activateInput = setRendInputActiveMasa;
    4113          49 :             move32();
    4114          49 :             move32();
    4115          49 :             BREAK;
    4116           0 :         default:
    4117           0 :             return IVAS_ERR_INVALID_INPUT_FORMAT;
    4118             :     }
    4119             : 
    4120             :     /* Find first free input in array corresponding to input type */
    4121         973 :     IF( NE_32( ( error = findFreeInputSlot_fx( inputsArray, inputStructSize, maxNumInputsOfType, &inputIndex ) ), IVAS_ERR_OK ) )
    4122             :     {
    4123           0 :         return error;
    4124             :     }
    4125             : 
    4126         973 :     *inputId = makeInputId( inConfig, inputIndex );
    4127         973 :     move16();
    4128         973 :     IF( NE_32( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, hIvasRend->hRendererConfig, &hIvasRend->hHrtfs ) ), IVAS_ERR_OK ) )
    4129             :     {
    4130           0 :         return error;
    4131             :     }
    4132             : 
    4133         973 :     return IVAS_ERR_OK;
    4134             : }
    4135             : 
    4136             : 
    4137             : /*-------------------------------------------------------------------*
    4138             :  * IVAS_REND_ConfigureCustomInputLoudspeakerLayout()
    4139             :  *
    4140             :  *
    4141             :  * Note: this will reset any custom LFE routing set for the input
    4142             :  *-------------------------------------------------------------------*/
    4143         105 : ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout(
    4144             :     IVAS_REND_HANDLE hIvasRend,      /* i/o: Renderer handle                        */
    4145             :     const IVAS_REND_InputId inputId, /* i  : ID of the input                        */
    4146             :     const IVAS_CUSTOM_LS_DATA layout /* i  : custom loudspeaker layout for input    */
    4147             : )
    4148             : {
    4149             :     input_mc *inputMc;
    4150             :     ivas_error error;
    4151             : 
    4152             :     /* Validate function arguments */
    4153         105 :     IF( hIvasRend == NULL )
    4154             :     {
    4155           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4156             :     }
    4157             : 
    4158         105 :     IF( NE_32( ( error = validateCustomLsLayout_fx( layout ) ), IVAS_ERR_OK ) )
    4159             :     {
    4160           0 :         return error;
    4161             :     }
    4162             : 
    4163         105 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &inputMc ) ), IVAS_ERR_OK ) )
    4164             :     {
    4165           0 :         return error;
    4166             :     }
    4167             : 
    4168         105 :     IF( NE_32( inputMc->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    4169             :     {
    4170             :         /* Specifying details of custom speaker layout only makes sense if input config is set to custom speaker layout */
    4171           0 :         return IVAS_ERR_INVALID_INPUT_FORMAT;
    4172             :     }
    4173             : 
    4174             :     /* Re-initialize panning gains for the MC input, This includes re-initializing LFE handling
    4175             :      * for the new input layout, which means custom LFE handling is overwritten, if previously
    4176             :      * set for the MC input. */
    4177         105 :     inputMc->customLsInput = makeCustomLsSetup( layout );
    4178             : 
    4179         105 :     inputMc->lfeRouting = defaultLfeRouting( inputMc->base.inConfig, inputMc->customLsInput, hIvasRend->outputConfig, *inputMc->base.ctx.pCustomLsOut );
    4180             : 
    4181         105 :     IF( NE_32( ( error = initEfap( &inputMc->efapInWrapper, inputMc->base.inConfig, &inputMc->customLsInput ) ), IVAS_ERR_OK ) )
    4182             :     {
    4183           0 :         return error;
    4184             :     }
    4185             : 
    4186         105 :     test();
    4187         105 :     test();
    4188             : 
    4189         105 :     IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) )
    4190             :     {
    4191          36 :         IF( NE_32( ( error = initMcBinauralRendering( inputMc, inputMc->base.inConfig, hIvasRend->outputConfig, hIvasRend->hRendererConfig, hIvasRend->hHrtfs.hSetOfHRTF, hIvasRend->hHrtfs.hHrtfStatistics, FALSE ) ), IVAS_ERR_OK ) )
    4192             :         {
    4193           0 :             return error;
    4194             :         }
    4195             :     }
    4196             : 
    4197         105 :     IF( NE_32( ( error = updateMcPanGains( inputMc, hIvasRend->outputConfig ) ), IVAS_ERR_OK ) )
    4198             :     {
    4199           0 :         return error;
    4200             :     }
    4201             : 
    4202         105 :     return IVAS_ERR_OK;
    4203             : }
    4204             : 
    4205             : /*-------------------------------------------------------------------*
    4206             :  * IVAS_REND_SetInputGain()
    4207             :  *
    4208             :  *
    4209             :  *-------------------------------------------------------------------*/
    4210         973 : ivas_error IVAS_REND_SetInputGain_fx(
    4211             :     IVAS_REND_HANDLE hIvasRend,      /* i/o: Renderer handle             */
    4212             :     const IVAS_REND_InputId inputId, /* i  : ID of the input             */
    4213             :     const Word32 gain                /* i  : linear gain (not in dB) Q30 */
    4214             : )
    4215             : {
    4216             :     input_base *inputBase;
    4217             :     ivas_error error;
    4218             : 
    4219             :     /* Validate function arguments */
    4220         973 :     IF( hIvasRend == NULL )
    4221             :     {
    4222           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4223             :     }
    4224             : 
    4225         973 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ), IVAS_ERR_OK ) )
    4226             :     {
    4227           0 :         return error;
    4228             :     }
    4229             : 
    4230         973 :     inputBase->gain_fx = gain;
    4231         973 :     move32();
    4232             : 
    4233         973 :     return IVAS_ERR_OK;
    4234             : }
    4235             : 
    4236             : /*-------------------------------------------------------------------*
    4237             :  * IVAS_REND_SetInputLfeMtx()
    4238             :  *
    4239             :  *
    4240             :  *-------------------------------------------------------------------*/
    4241           0 : ivas_error IVAS_REND_SetInputLfeMtx_fx(
    4242             :     IVAS_REND_HANDLE hIvasRend,             /* i/o: Renderer handle        */
    4243             :     const IVAS_REND_InputId inputId,        /* i  : ID of the input        */
    4244             :     const IVAS_REND_LfePanMtx_fx *lfePanMtx /* i  : LFE panning matrix     */
    4245             : )
    4246             : {
    4247             :     Word16 i;
    4248             :     input_base *pInputBase;
    4249             :     input_mc *pInputMc;
    4250             :     ivas_error error;
    4251             : 
    4252             :     /* Validate function arguments */
    4253           0 :     IF( hIvasRend == NULL )
    4254             :     {
    4255           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4256             :     }
    4257             : 
    4258           0 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ), IVAS_ERR_OK ) )
    4259             :     {
    4260           0 :         return error;
    4261             :     }
    4262             : 
    4263           0 :     IF( NE_32( getAudioConfigType( pInputBase->inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    4264             :     {
    4265             :         /* Custom LFE panning matrix only makes sense with channel-based input */
    4266           0 :         return IVAS_ERR_INVALID_INPUT_FORMAT;
    4267             :     }
    4268           0 :     pInputMc = (input_mc *) pInputBase;
    4269             : 
    4270             :     /* copy LFE panning matrix */
    4271           0 :     FOR( i = 0; i < RENDERER_MAX_INPUT_LFE_CHANNELS; i++ )
    4272             :     {
    4273           0 :         Copy32( ( *lfePanMtx )[i], pInputMc->lfeRouting.lfePanMtx_fx[i], IVAS_MAX_OUTPUT_CHANNELS );
    4274             :     }
    4275             : 
    4276           0 :     IF( NE_32( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ), IVAS_ERR_OK ) )
    4277             :     {
    4278           0 :         return error;
    4279             :     }
    4280             : 
    4281           0 :     return IVAS_ERR_OK;
    4282             : }
    4283             : 
    4284             : /*-------------------------------------------------------------------*
    4285             :  * IVAS_REND_SetInputLfePos()
    4286             :  *
    4287             :  *
    4288             :  *-------------------------------------------------------------------*/
    4289             : 
    4290           0 : ivas_error IVAS_REND_SetInputLfePos_fx(
    4291             :     IVAS_REND_HANDLE hIvasRend,      /* i/o: Renderer handle                                    */
    4292             :     const IVAS_REND_InputId inputId, /* i  : ID of the input                                    */
    4293             :     const Word32 inputGain,          /* i  : Input gain to be applied to the LFE channel(s) Q31 */
    4294             :     const Word16 outputAzimuth,      /* i  : Output azimuth position                         Q0 */
    4295             :     const Word16 outputElevation     /* i  : Output elevation position                       Q0 */
    4296             : )
    4297             : {
    4298             :     input_base *pInputBase;
    4299             :     input_mc *pInputMc;
    4300             :     ivas_error error;
    4301             : 
    4302             :     /* Validate function arguments */
    4303           0 :     IF( hIvasRend == NULL )
    4304             :     {
    4305           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4306             :     }
    4307             : 
    4308           0 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &pInputBase ) ), IVAS_ERR_OK ) )
    4309             :     {
    4310           0 :         return error;
    4311             :     }
    4312             : 
    4313           0 :     IF( NE_32( getAudioConfigType( pInputBase->inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    4314             :     {
    4315             :         /* Custom LFE routing only makes sense with channel-based input */
    4316           0 :         return IVAS_ERR_INVALID_INPUT_FORMAT;
    4317             :     }
    4318           0 :     pInputMc = (input_mc *) pInputBase;
    4319             : 
    4320           0 :     pInputMc->lfeRouting.pan_lfe = true;
    4321           0 :     move16();
    4322           0 :     pInputMc->lfeRouting.lfeInputGain_fx = inputGain; /* Q31 */
    4323           0 :     move32();
    4324           0 :     pInputMc->lfeRouting.lfeOutputAzimuth_fx = outputAzimuth; /* Q0 */
    4325           0 :     move16();
    4326           0 :     pInputMc->lfeRouting.lfeOutputElevation_fx = outputElevation; /* Q0 */
    4327           0 :     move16();
    4328             : 
    4329           0 :     IF( NE_32( ( error = updateMcPanGains( pInputMc, hIvasRend->outputConfig ) ), IVAS_ERR_OK ) )
    4330             :     {
    4331           0 :         return error;
    4332             :     }
    4333             : 
    4334           0 :     return IVAS_ERR_OK;
    4335             : }
    4336             : 
    4337             : /*-------------------------------------------------------------------*
    4338             :  * IVAS_REND_RemoveInput()
    4339             :  *
    4340             :  *
    4341             :  *-------------------------------------------------------------------*/
    4342             : /* ToDo; unused function */
    4343           0 : ivas_error IVAS_REND_RemoveInput(
    4344             :     IVAS_REND_HANDLE hIvasRend,     /* i/o: Renderer handle     */
    4345             :     const IVAS_REND_InputId inputId /* i  : ID of the input     */
    4346             : )
    4347             : {
    4348             :     ivas_error error;
    4349             :     input_base *inputBase;
    4350             : 
    4351             :     /* Validate function arguments */
    4352           0 :     IF( hIvasRend == NULL )
    4353             :     {
    4354           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4355             :     }
    4356             : 
    4357           0 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ), IVAS_ERR_OK ) )
    4358             :     {
    4359           0 :         return error;
    4360             :     }
    4361             : 
    4362           0 :     SWITCH( getAudioConfigType( inputBase->inConfig ) )
    4363             :     {
    4364           0 :         case IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED:
    4365           0 :             clearInputIsm( (input_ism *) inputBase );
    4366           0 :             BREAK;
    4367           0 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    4368           0 :             clearInputMc( (input_mc *) inputBase );
    4369           0 :             BREAK;
    4370           0 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    4371           0 :             clearInputSba( (input_sba *) inputBase );
    4372           0 :             BREAK;
    4373           0 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    4374           0 :             clearInputMasa( (input_masa *) inputBase );
    4375           0 :             BREAK;
    4376           0 :         default:
    4377           0 :             return IVAS_ERR_INVALID_INPUT_FORMAT;
    4378             :     }
    4379             : 
    4380           0 :     return IVAS_ERR_OK;
    4381             : }
    4382             : 
    4383             : 
    4384             : /*-------------------------------------------------------------------*
    4385             :  * IVAS_REND_GetInputNumChannels()
    4386             :  *
    4387             :  *
    4388             :  *-------------------------------------------------------------------*/
    4389      630413 : ivas_error IVAS_REND_GetInputNumChannels(
    4390             :     IVAS_REND_CONST_HANDLE hIvasRend, /* i  : Renderer handle                   */
    4391             :     const IVAS_REND_InputId inputId,  /* i  : ID of the input                   */
    4392             :     Word16 *numChannels               /* o  : number of channels of the input   */
    4393             : )
    4394             : {
    4395             :     ivas_error error;
    4396             :     const input_base *pInput;
    4397             : 
    4398             :     /* Validate function arguments */
    4399      630413 :     test();
    4400      630413 :     IF( hIvasRend == NULL || numChannels == NULL )
    4401             :     {
    4402           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4403             :     }
    4404             : 
    4405      630413 :     IF( NE_32( ( error = getConstInputById( hIvasRend, inputId, (const void **) &pInput ) ), IVAS_ERR_OK ) )
    4406             :     {
    4407           0 :         return error;
    4408             :     }
    4409             : 
    4410      630413 :     IF( NE_32( ( error = getRendInputNumChannels( pInput, numChannels ) ), IVAS_ERR_OK ) )
    4411             :     {
    4412           0 :         return error;
    4413             :     }
    4414             : 
    4415      630413 :     return IVAS_ERR_OK;
    4416             : }
    4417             : 
    4418             : /*-------------------------------------------------------------------*
    4419             :  * IVAS_REND_GetNumAllObjects()
    4420             :  *
    4421             :  *
    4422             :  *-------------------------------------------------------------------*/
    4423         426 : ivas_error IVAS_REND_GetNumAllObjects(
    4424             :     IVAS_REND_CONST_HANDLE hIvasRend, /* i  : Renderer handle       */
    4425             :     Word16 *numChannels               /* o  : number of all objects */
    4426             : )
    4427             : {
    4428         426 :     test();
    4429         426 :     IF( hIvasRend == NULL || numChannels == NULL )
    4430             :     {
    4431           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4432             :     }
    4433             : 
    4434         426 :     test();
    4435         426 :     IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA2 ) )
    4436             :     {
    4437           1 :         *numChannels = (Word16) hIvasRend->inputsIsm[0].total_num_objects;
    4438           1 :         move16();
    4439             :     }
    4440             : 
    4441         426 :     return IVAS_ERR_OK;
    4442             : }
    4443             : 
    4444             : 
    4445             : /*-------------------------------------------------------------------*
    4446             :  * IVAS_REND_GetDelay()
    4447             :  *
    4448             :  *
    4449             :  *-------------------------------------------------------------------*/
    4450             : 
    4451           0 : ivas_error IVAS_REND_GetDelay_fx(
    4452             :     IVAS_REND_CONST_HANDLE hIvasRend, /* i  : Renderer state                                                    */
    4453             :     Word16 *nSamples,                 /* o  : Renderer delay in samples                                         */
    4454             :     Word32 *timeScale                 /* o  : Time scale of the delay, equal to renderer output sampling rate   */
    4455             : )
    4456             : {
    4457             :     /* TODO tmu : this function only returns the maximum delay across all inputs
    4458             :      * Ideally each input has its own delay buffer and everything is aligned (binaural and LFE filtering delays are nonuniform)
    4459             :      */
    4460             :     Word16 i;
    4461             :     Word32 latency_ns;
    4462             :     Word32 max_latency_ns;
    4463             : 
    4464           0 :     Word32 timescale_by_ns[7] = { 0, 17180, 34360, 0, 68719, 0, 103079 };
    4465           0 :     move32();
    4466           0 :     move32();
    4467           0 :     move32();
    4468           0 :     move32();
    4469           0 :     move32();
    4470           0 :     move32();
    4471           0 :     move32();
    4472             : 
    4473             :     /* Validate function arguments */
    4474           0 :     test();
    4475           0 :     test();
    4476           0 :     IF( hIvasRend == NULL || nSamples == NULL || timeScale == NULL )
    4477             :     {
    4478           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4479             :     }
    4480             : 
    4481           0 :     *timeScale = hIvasRend->sampleRateOut;
    4482           0 :     move32();
    4483           0 :     assert( *timeScale == 8000 || *timeScale == 16000 || *timeScale == 32000 || *timeScale == 48000 );
    4484           0 :     *nSamples = 0;
    4485           0 :     move16();
    4486           0 :     max_latency_ns = 0;
    4487           0 :     move32();
    4488             : 
    4489             :     /* Compute the maximum delay across all inputs */
    4490           0 :     FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ )
    4491             :     {
    4492           0 :         IF( NE_32( hIvasRend->inputsIsm[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    4493             :         {
    4494           0 :             IF( hIvasRend->inputsIsm[i].crendWrapper != NULL )
    4495             :             {
    4496           0 :                 latency_ns = hIvasRend->inputsIsm[i].crendWrapper->binaural_latency_ns;
    4497             :             }
    4498             :             ELSE
    4499             :             {
    4500           0 :                 latency_ns = 0;
    4501             :             }
    4502           0 :             move32();
    4503             : 
    4504           0 :             latency_ns = L_max( latency_ns, hIvasRend->inputsIsm[i].tdRendWrapper.binaural_latency_ns );
    4505           0 :             max_latency_ns = L_max( max_latency_ns, latency_ns );
    4506             :         }
    4507             :     }
    4508             : 
    4509           0 :     FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; i++ )
    4510             :     {
    4511           0 :         IF( NE_32( hIvasRend->inputsMc[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    4512             :         {
    4513           0 :             IF( ( hIvasRend->inputsMc[i].crendWrapper != NULL ) )
    4514             :             {
    4515           0 :                 latency_ns = hIvasRend->inputsMc[i].crendWrapper->binaural_latency_ns;
    4516             :             }
    4517             :             ELSE
    4518             :             {
    4519           0 :                 latency_ns = 0;
    4520             :             }
    4521             : 
    4522           0 :             move32();
    4523             : 
    4524           0 :             latency_ns = L_max( latency_ns, hIvasRend->inputsMc[i].tdRendWrapper.binaural_latency_ns );
    4525           0 :             max_latency_ns = L_max( max_latency_ns, latency_ns );
    4526             :         }
    4527             :     }
    4528             : 
    4529           0 :     FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; i++ )
    4530             :     {
    4531           0 :         IF( NE_32( hIvasRend->inputsSba[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    4532             :         {
    4533             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    4534           0 :             test();
    4535           0 :             IF( hIvasRend->splitRendWrapper != NULL && hIvasRend->splitRendWrapper->hBinHrSplitPreRend != NULL )
    4536             : #else
    4537             :             IF( hIvasRend->splitRendWrapper->hBinHrSplitPreRend != NULL )
    4538             : #endif
    4539             :             {
    4540           0 :                 IF( hIvasRend->hRendererConfig->split_rend_config.rendererSelection == ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV )
    4541             :                 {
    4542           0 :                     latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns;
    4543           0 :                     move32();
    4544             :                 }
    4545             :                 ELSE
    4546             :                 {
    4547           0 :                     IF( ( hIvasRend->inputsSba[i].crendWrapper != NULL ) )
    4548             :                     {
    4549           0 :                         latency_ns = hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns;
    4550             :                     }
    4551             :                     ELSE
    4552             :                     {
    4553           0 :                         latency_ns = 0;
    4554             :                     }
    4555           0 :                     move32();
    4556             :                 }
    4557           0 :                 max_latency_ns = L_max( max_latency_ns, latency_ns );
    4558             :             }
    4559           0 :             ELSE IF( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL )
    4560             :             {
    4561           0 :                 latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns;
    4562           0 :                 move32();
    4563           0 :                 latency_ns = L_add( latency_ns, IVAS_FB_DEC_DELAY_NS );
    4564           0 :                 max_latency_ns = L_max( max_latency_ns, latency_ns );
    4565             :             }
    4566             :             ELSE
    4567             :             {
    4568           0 :                 IF( hIvasRend->inputsSba[i].crendWrapper != NULL )
    4569             :                 {
    4570           0 :                     latency_ns = hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns;
    4571             :                 }
    4572             :                 ELSE
    4573             :                 {
    4574           0 :                     latency_ns = 0;
    4575             :                 }
    4576           0 :                 move32();
    4577           0 :                 max_latency_ns = L_max( max_latency_ns, latency_ns );
    4578             :             }
    4579             :         }
    4580             :     }
    4581             : 
    4582           0 :     FOR( i = 0; i < RENDERER_MAX_MASA_INPUTS; i++ )
    4583             :     {
    4584           0 :         IF( NE_32( hIvasRend->inputsMasa[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    4585             :         {
    4586           0 :             latency_ns = (Word32) ( IVAS_FB_DEC_DELAY_NS );
    4587           0 :             move32();
    4588           0 :             max_latency_ns = L_max( max_latency_ns, latency_ns );
    4589             :         }
    4590             :     }
    4591             : 
    4592             :     //*nSamples = (Word16) roundf( (float) max_latency_ns * *timeScale / 1000000000.f );
    4593           0 :     Word32 temp = Mpy_32_32( *timeScale, 268436 ); // Q0 + Q31 - Q31 -> Q0, ( 1 / 8000 ) * 2 ^ 31
    4594           0 :     *nSamples = extract_l( Mpy_32_32_r( max_latency_ns, timescale_by_ns[temp] ) );
    4595           0 :     move16();
    4596             : 
    4597           0 :     return IVAS_ERR_OK;
    4598             : }
    4599             : 
    4600             : 
    4601             : /*-------------------------------------------------------------------*
    4602             :  * IVAS_REND_FeedInputAudio()
    4603             :  *
    4604             :  *
    4605             :  *-------------------------------------------------------------------*/
    4606             : 
    4607     1877090 : ivas_error IVAS_REND_FeedInputAudio_fx(
    4608             :     IVAS_REND_HANDLE hIvasRend,                    /* i/o: Renderer handle          */
    4609             :     const IVAS_REND_InputId inputId,               /* i  : ID of the input          */
    4610             :     const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i  : buffer with input audio  */
    4611             : )
    4612             : {
    4613             :     ivas_error error;
    4614             :     input_base *inputBase;
    4615             :     Word16 numInputChannels;
    4616             :     Word16 cldfb2tdShift;
    4617             : 
    4618             :     /* Validate function arguments */
    4619     1877090 :     test();
    4620     1877090 :     IF( hIvasRend == NULL || inputAudio.data_fx == NULL )
    4621             :     {
    4622           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4623             :     }
    4624             : 
    4625     1877090 :     test();
    4626     1877090 :     cldfb2tdShift = ( inputAudio.config.is_cldfb ) ? 1 : 0;
    4627             : 
    4628     1877090 :     IF( inputAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 0 ) ||
    4629             :         ( ( shl( MAX_BUFFER_LENGTH_PER_CHANNEL, cldfb2tdShift ) ) < inputAudio.config.numSamplesPerChannel && inputAudio.config.is_cldfb == 1 ) )
    4630             :     {
    4631           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Buffer size outside of supported range" );
    4632             :     }
    4633             : 
    4634     1877090 :     test();
    4635     1877090 :     IF( inputAudio.config.numChannels <= 0 || LT_16( MAX_INPUT_CHANNELS, inputAudio.config.numChannels ) )
    4636             :     {
    4637           0 :         return IVAS_ERR_WRONG_NUM_CHANNELS;
    4638             :     }
    4639             : 
    4640     1877090 :     test();
    4641     1877090 :     move32(); // move added for typecasting
    4642     1877090 :     IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) &&
    4643             :         NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) &&
    4644             :         NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) &&
    4645             :         NE_32( L_shr( L_mult0( inputAudio.config.numSamplesPerChannel, 1000 ), cldfb2tdShift ), (Word32) W_mult0_32_32( L_mult0( BINAURAL_RENDERING_FRAME_SIZE_MS, hIvasRend->num_subframes ), hIvasRend->sampleRateOut ) ) )
    4646             :     {
    4647           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" );
    4648             :     }
    4649             : 
    4650     1877090 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ), IVAS_ERR_OK ) )
    4651             :     {
    4652           0 :         return error;
    4653             :     }
    4654             : 
    4655     1877090 :     IF( NE_32( ( error = getRendInputNumChannels( inputBase, &numInputChannels ) ), IVAS_ERR_OK ) )
    4656             :     {
    4657           0 :         return error;
    4658             :     }
    4659     1877090 :     test();
    4660     1877090 :     test();
    4661     1877090 :     IF( ( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA1 ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA2 ) ) && EQ_32( inputBase->inConfig, IVAS_AUDIO_CONFIG_OBA ) )
    4662             :     {
    4663         150 :         numInputChannels = (Word16) hIvasRend->inputsIsm[0].total_num_objects;
    4664         150 :         move16();
    4665             :     }
    4666             : 
    4667     1877090 :     IF( NE_16( numInputChannels, inputAudio.config.numChannels ) )
    4668             :     {
    4669           0 :         return IVAS_ERR_WRONG_NUM_CHANNELS;
    4670             :     }
    4671             : 
    4672     1877090 :     inputBase->inputBuffer.config = inputAudio.config;
    4673             : 
    4674     1877090 :     MVR2R_WORD32( inputAudio.data_fx, inputBase->inputBuffer.data_fx, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels );
    4675             : 
    4676     1877090 :     inputBase->numNewSamplesPerChannel = shr( inputAudio.config.numSamplesPerChannel, cldfb2tdShift );
    4677     1877090 :     move32();
    4678             : 
    4679     1877090 :     return IVAS_ERR_OK;
    4680             : }
    4681             : 
    4682             : 
    4683             : /*-------------------------------------------------------------------*
    4684             :  * IVAS_REND_FeedInputObjectMetadata()
    4685             :  *
    4686             :  *
    4687             :  *-------------------------------------------------------------------*/
    4688             : 
    4689     1247500 : ivas_error IVAS_REND_FeedInputObjectMetadata(
    4690             :     IVAS_REND_HANDLE hIvasRend,            /* i/o: Renderer handle          */
    4691             :     const IVAS_REND_InputId inputId,       /* i  : ID of the input          */
    4692             :     const IVAS_ISM_METADATA objectPosition /* i  : object position struct   */
    4693             : )
    4694             : {
    4695             :     input_base *inputBase;
    4696             :     input_ism *inputIsm;
    4697             :     ivas_error error;
    4698             : 
    4699             :     /* Validate function arguments */
    4700     1247500 :     IF( hIvasRend == NULL )
    4701             :     {
    4702           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4703             :     }
    4704             : 
    4705     1247500 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ), IVAS_ERR_OK ) )
    4706             :     {
    4707           0 :         return error;
    4708             :     }
    4709             : 
    4710     1247500 :     IF( NE_32( inputBase->inConfig, IVAS_AUDIO_CONFIG_OBA ) )
    4711             :     {
    4712             :         /* Object metadata should only be fed for object inputs */
    4713           0 :         return IVAS_ERR_METADATA_NOT_EXPECTED;
    4714             :     }
    4715             : 
    4716     1247500 :     inputIsm = (input_ism *) inputBase;
    4717     1247500 :     inputIsm->previousPos = inputIsm->currentPos;
    4718     1247500 :     inputIsm->currentPos = objectPosition;
    4719             : 
    4720     1247500 :     return IVAS_ERR_OK;
    4721             : }
    4722             : 
    4723             : 
    4724             : /*-------------------------------------------------------------------*
    4725             :  * IVAS_REND_FeedInputObjectMetadataToOMasa()
    4726             :  *
    4727             :  *
    4728             :  *-------------------------------------------------------------------*/
    4729         600 : ivas_error IVAS_REND_FeedInputObjectMetadataToOMasa(
    4730             :     IVAS_REND_HANDLE hIvasRend,            /* i/o: Renderer handle          */
    4731             :     const Word16 inputIndex,               /* i  : Index of the input       */
    4732             :     const IVAS_ISM_METADATA objectPosition /* i  : object position struct   */
    4733             : )
    4734             : {
    4735             :     /* Validate function arguments */
    4736         600 :     IF( hIvasRend == NULL )
    4737             :     {
    4738           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4739             :     }
    4740             : 
    4741             :     /* Set position to OMasa struct */
    4742         600 :     hIvasRend->inputsIsm->hOMasa->ism_azimuth_fx[inputIndex] = objectPosition.azimuth_fx;
    4743         600 :     move32();
    4744         600 :     hIvasRend->inputsIsm->hOMasa->ism_elevation_fx[inputIndex] = objectPosition.elevation_fx;
    4745         600 :     move32();
    4746             : 
    4747         600 :     return IVAS_ERR_OK;
    4748             : }
    4749             : 
    4750             : 
    4751             : /*-------------------------------------------------------------------*
    4752             :  * IVAS_REND_FeedInputMasaMetadata()
    4753             :  *
    4754             :  *
    4755             :  *-------------------------------------------------------------------*/
    4756             : 
    4757        7350 : ivas_error IVAS_REND_FeedInputMasaMetadata(
    4758             :     IVAS_REND_HANDLE hIvasRend,            /* i/o: Renderer handle      */
    4759             :     const IVAS_REND_InputId inputId,       /* i  : ID of the input      */
    4760             :     IVAS_MASA_METADATA_HANDLE masaMetadata /* i  : MASA metadata frame  */
    4761             : )
    4762             : {
    4763             :     ivas_error error;
    4764             :     input_base *inputBase;
    4765             :     input_masa *inputMasa;
    4766             : 
    4767             :     /* Validate function arguments */
    4768        7350 :     IF( hIvasRend == NULL )
    4769             :     {
    4770           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4771             :     }
    4772             : 
    4773        7350 :     IF( NE_32( ( error = getInputById( hIvasRend, inputId, (void **) &inputBase ) ), IVAS_ERR_OK ) )
    4774             :     {
    4775           0 :         return error;
    4776             :     }
    4777             : 
    4778        7350 :     IF( NE_32( getAudioConfigType( inputBase->inConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) )
    4779             :     {
    4780             :         /* MASA metadata should only be fed for MASA inputs */
    4781           0 :         return IVAS_ERR_METADATA_NOT_EXPECTED;
    4782             :     }
    4783             : 
    4784        7350 :     inputMasa = (input_masa *) inputBase;
    4785        7350 :     inputMasa->masaMetadata = *masaMetadata;
    4786        7350 :     inputMasa->metadataHasBeenFed = true;
    4787        7350 :     move16();
    4788             : 
    4789        7350 :     return IVAS_ERR_OK;
    4790             : }
    4791             : 
    4792             : 
    4793             : /*-------------------------------------------------------------------*
    4794             :  * IVAS_REND_InitConfig()
    4795             :  *
    4796             :  *
    4797             :  *-------------------------------------------------------------------*/
    4798             : 
    4799         666 : ivas_error IVAS_REND_InitConfig(
    4800             :     IVAS_REND_HANDLE hIvasRend,       /* i/o: Renderer handle     */
    4801             :     const AUDIO_CONFIG outAudioConfig /* i  : output audioConfig  */
    4802             : )
    4803             : {
    4804             :     ivas_error error;
    4805             :     bool rendererConfigEnabled;
    4806             : 
    4807         666 :     rendererConfigEnabled = EQ_32( getAudioConfigType( outAudioConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL );
    4808             : 
    4809         666 :     IF( rendererConfigEnabled )
    4810             :     {
    4811         188 :         hIvasRend->rendererConfigEnabled = 1;
    4812         188 :         move16();
    4813             :     }
    4814             :     ELSE
    4815             :     {
    4816         478 :         hIvasRend->rendererConfigEnabled = 0;
    4817         478 :         move16();
    4818             :     }
    4819             : 
    4820         666 :     IF( rendererConfigEnabled )
    4821             :     {
    4822         188 :         IF( NE_32( ( error = ivas_render_config_open( &( hIvasRend->hRendererConfig ) ) ), IVAS_ERR_OK ) )
    4823             :         {
    4824           0 :             return error;
    4825             :         }
    4826         188 :         IF( NE_32( ( error = ivas_render_config_init_from_rom_fx( &hIvasRend->hRendererConfig ) ), IVAS_ERR_OK ) )
    4827             :         {
    4828           0 :             return error;
    4829             :         }
    4830             :     }
    4831             :     ELSE
    4832             :     {
    4833         478 :         hIvasRend->hRendererConfig = NULL;
    4834             :     }
    4835             : 
    4836         666 :     return IVAS_ERR_OK;
    4837             : }
    4838             : 
    4839             : 
    4840             : /*-------------------------------------------------------------------*
    4841             :  * IVAS_REND_GetRenderConfig()
    4842             :  *
    4843             :  *
    4844             :  *-------------------------------------------------------------------*/
    4845             : 
    4846           0 : Word16 IVAS_REND_GetRenderConfig(
    4847             :     IVAS_REND_HANDLE hIvasRend,            /* i/o: IVAS renderer handle        */
    4848             :     const IVAS_RENDER_CONFIG_HANDLE hRCout /* o  : Render configuration handle */
    4849             : )
    4850             : {
    4851             :     RENDER_CONFIG_HANDLE hRCin;
    4852             : 
    4853           0 :     test();
    4854           0 :     test();
    4855           0 :     IF( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL || hRCout == NULL )
    4856             :     {
    4857           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4858             :     }
    4859             : 
    4860           0 :     hRCin = hIvasRend->hRendererConfig;
    4861             : #ifndef FIX_587_DEFAULT_REVERB
    4862             :     hRCout->roomAcoustics.override = hRCin->roomAcoustics.override;
    4863             : #endif
    4864           0 :     hRCout->roomAcoustics.nBands = hRCin->roomAcoustics.nBands;
    4865           0 :     hRCout->roomAcoustics.acousticPreDelay_fx = hRCin->roomAcoustics.acousticPreDelay_fx;
    4866           0 :     hRCout->roomAcoustics.inputPreDelay_fx = hRCin->roomAcoustics.inputPreDelay_fx;
    4867           0 :     Copy( hRCin->directivity_fx, hRCout->directivity_fx, 3 * MAX_NUM_OBJECTS );
    4868             : #ifndef FIX_587_DEFAULT_REVERB
    4869             :     move16();
    4870             : #endif
    4871           0 :     move16();
    4872           0 :     move32();
    4873           0 :     move32();
    4874             : 
    4875           0 :     Copy32( hRCin->roomAcoustics.pFc_input_fx, hRCout->roomAcoustics.pFc_input_fx, CLDFB_NO_CHANNELS_MAX );
    4876           0 :     Copy32( hRCin->roomAcoustics.pAcoustic_rt60_fx, hRCout->roomAcoustics.pAcoustic_rt60_fx, CLDFB_NO_CHANNELS_MAX );
    4877           0 :     Copy32( hRCin->roomAcoustics.pAcoustic_dsr_fx, hRCout->roomAcoustics.pAcoustic_dsr_fx, CLDFB_NO_CHANNELS_MAX );
    4878             : 
    4879           0 :     hRCout->split_rend_config.splitRendBitRate = ISAR_MAX_SPLIT_REND_BITRATE;
    4880           0 :     hRCout->split_rend_config.dof = 3;
    4881           0 :     hRCout->split_rend_config.hq_mode = 0;
    4882           0 :     hRCout->split_rend_config.codec_delay_ms = 0;
    4883           0 :     hRCout->split_rend_config.isar_frame_size_ms = 20;
    4884           0 :     hRCout->split_rend_config.codec_frame_size_ms = 0; /* 0 means "use default for selected codec" */
    4885           0 :     hRCout->split_rend_config.codec = ISAR_SPLIT_REND_CODEC_DEFAULT;
    4886           0 :     hRCout->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB;
    4887           0 :     hRCout->split_rend_config.rendererSelection = hRCin->split_rend_config.rendererSelection;
    4888           0 :     hRCout->split_rend_config.lc3plus_highres = 0;
    4889             : 
    4890           0 :     hRCout->roomAcoustics.use_er = hRCin->roomAcoustics.use_er;
    4891           0 :     hRCout->roomAcoustics.lowComplexity = hRCin->roomAcoustics.lowComplexity;
    4892           0 :     move16();
    4893           0 :     move32();
    4894             : 
    4895           0 :     return IVAS_ERR_OK;
    4896             : }
    4897             : 
    4898             : 
    4899             : /*-------------------------------------------------------------------*
    4900             :  * IVAS_REND_FeedRenderConfig()
    4901             :  *
    4902             :  *
    4903             :  *-------------------------------------------------------------------*/
    4904             : 
    4905           0 : Word16 IVAS_REND_FeedRenderConfig(
    4906             :     IVAS_REND_HANDLE hIvasRend,                /* i/o: IVAS renderer handle        */
    4907             :     const IVAS_RENDER_CONFIG_DATA renderConfig /* i  : Render configuration struct */
    4908             : )
    4909             : {
    4910             :     RENDER_CONFIG_HANDLE hRenderConfig;
    4911             : #ifdef FIX_1053_REVERB_RECONFIGURATION
    4912             :     UWord16 i;
    4913             :     input_ism *pIsmInput;
    4914             :     input_masa *pMasaInput;
    4915             :     input_mc *pMcInput;
    4916             :     input_sba *pSbaInput;
    4917             :     ivas_error error;
    4918             : #else
    4919             :     ivas_error error;
    4920             : #endif
    4921             : 
    4922           0 :     test();
    4923           0 :     IF( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL )
    4924             :     {
    4925           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    4926             :     }
    4927           0 :     hRenderConfig = hIvasRend->hRendererConfig;
    4928             : 
    4929             : #ifndef FIX_587_DEFAULT_REVERB
    4930             :     hRenderConfig->roomAcoustics.override = renderConfig.roomAcoustics.override;
    4931             :     move16();
    4932             : #endif
    4933           0 :     hRenderConfig->roomAcoustics.nBands = renderConfig.roomAcoustics.nBands;
    4934           0 :     move16();
    4935           0 :     hRenderConfig->roomAcoustics.acousticPreDelay_fx = renderConfig.roomAcoustics.acousticPreDelay_fx;
    4936           0 :     move32();
    4937           0 :     hRenderConfig->roomAcoustics.inputPreDelay_fx = renderConfig.roomAcoustics.inputPreDelay_fx;
    4938           0 :     move32();
    4939           0 :     Copy32( renderConfig.roomAcoustics.pFc_input_fx, hRenderConfig->roomAcoustics.pFc_input_fx, CLDFB_NO_CHANNELS_MAX );
    4940           0 :     Copy32( renderConfig.roomAcoustics.pAcoustic_rt60_fx, hRenderConfig->roomAcoustics.pAcoustic_rt60_fx, CLDFB_NO_CHANNELS_MAX );
    4941           0 :     Copy32( renderConfig.roomAcoustics.pAcoustic_dsr_fx, hRenderConfig->roomAcoustics.pAcoustic_dsr_fx, CLDFB_NO_CHANNELS_MAX );
    4942           0 :     Copy( renderConfig.directivity_fx, hRenderConfig->directivity_fx, 3 * MAX_NUM_OBJECTS );
    4943             : 
    4944           0 :     hRenderConfig->roomAcoustics.use_er = 0;
    4945           0 :     move16();
    4946           0 :     IF( EQ_16( renderConfig.roomAcoustics.use_er, 1 ) )
    4947             :     {
    4948           0 :         hRenderConfig->roomAcoustics.use_er = renderConfig.roomAcoustics.use_er;
    4949           0 :         move16();
    4950           0 :         hRenderConfig->roomAcoustics.lowComplexity = renderConfig.roomAcoustics.lowComplexity;
    4951           0 :         move32();
    4952           0 :         hRenderConfig->roomAcoustics.dimensions = renderConfig.roomAcoustics.dimensions;
    4953           0 :         hRenderConfig->roomAcoustics.ListenerOrigin = renderConfig.roomAcoustics.ListenerOrigin;
    4954             : 
    4955           0 :         Copy32( renderConfig.roomAcoustics.AbsCoeff_fx, hRenderConfig->roomAcoustics.AbsCoeff_fx, IVAS_ROOM_ABS_COEFF );
    4956             :     }
    4957             : 
    4958             : #ifdef FIX_1053_REVERB_RECONFIGURATION
    4959             :     /* Re-initialize reverb instance if already available */
    4960             :     /* ISM inputs */
    4961           0 :     for ( i = 0, pIsmInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pIsmInput )
    4962             :     {
    4963           0 :         IF( EQ_32( pIsmInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    4964             :         {
    4965             :             /* Skip inactive inputs */
    4966           0 :             continue;
    4967             :         }
    4968           0 :         if ( pIsmInput->hReverb != NULL )
    4969             :         {
    4970           0 :             IF( NE_32( ( error = ivas_reverb_open_fx( &pIsmInput->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pIsmInput->base.ctx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    4971             :             {
    4972           0 :                 return error;
    4973             :             }
    4974             :         }
    4975           0 :         if ( pIsmInput->crendWrapper != NULL && pIsmInput->crendWrapper->hCrend[0] != NULL )
    4976             :         {
    4977           0 :             IF( NE_32( ( error = ivas_reverb_open_fx( &pIsmInput->crendWrapper->hCrend[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pIsmInput->base.ctx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    4978             :             {
    4979           0 :                 return error;
    4980             :             }
    4981             :         }
    4982             :     }
    4983             : 
    4984             :     /* MASA inputs */
    4985           0 :     for ( i = 0, pMasaInput = hIvasRend->inputsMasa; i < RENDERER_MAX_MASA_INPUTS; ++i, ++pMasaInput )
    4986             :     {
    4987           0 :         IF( EQ_32( pMasaInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    4988             :         {
    4989             :             /* Skip inactive inputs */
    4990           0 :             continue;
    4991             :         }
    4992             : 
    4993           0 :         if ( pMasaInput->hMasaExtRend != NULL )
    4994             :         {
    4995           0 :             if ( pMasaInput->hMasaExtRend->hDiracDecBin[0] != NULL && pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb != NULL )
    4996             :             {
    4997           0 :                 ivas_binaural_reverb_close_fx( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb );
    4998             : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
    4999           0 :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), *pMasaInput->base.ctx.pOutSampleRate, NULL, NULL, NULL ) ), IVAS_ERR_OK ) )
    5000             : #else
    5001             :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), *pMasaInput->base.ctx.pOutSampleRate, NULL, NULL ) ), IVAS_ERR_OK ) )
    5002             : #endif
    5003             :                 {
    5004           0 :                     return error;
    5005             :                 }
    5006             :             }
    5007           0 :             if ( pMasaInput->hMasaExtRend->hReverb != NULL )
    5008             :             {
    5009           0 :                 ivas_binaural_reverb_close_fx( &pMasaInput->hMasaExtRend->hReverb );
    5010             : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
    5011           0 :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), *pMasaInput->base.ctx.pOutSampleRate, NULL, NULL, NULL ) ), IVAS_ERR_OK ) )
    5012             : #else
    5013             :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRenderConfig->roomAcoustics ), *pMasaInput->base.ctx.pOutSampleRate, NULL, NULL ) ), IVAS_ERR_OK ) )
    5014             : #endif
    5015             :                 {
    5016           0 :                     return error;
    5017             :                 }
    5018             :             }
    5019             :         }
    5020             :     }
    5021             : 
    5022             :     /* Multi-channel inputs */
    5023           0 :     for ( i = 0, pMcInput = hIvasRend->inputsMc; i < RENDERER_MAX_MC_INPUTS; ++i, ++pMcInput )
    5024             :     {
    5025           0 :         IF( EQ_32( pMcInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    5026             :         {
    5027             :             /* Skip inactive inputs */
    5028           0 :             continue;
    5029             :         }
    5030             : 
    5031           0 :         if ( pMcInput->hReverb != NULL )
    5032             :         {
    5033           0 :             IF( NE_32( ( error = ivas_reverb_open_fx( &pMcInput->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pMcInput->base.ctx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    5034             :             {
    5035           0 :                 return error;
    5036             :             }
    5037             :         }
    5038           0 :         if ( pMcInput->crendWrapper != NULL && pMcInput->crendWrapper->hCrend[0] && pMcInput->crendWrapper->hCrend[0]->hReverb != NULL )
    5039             :         {
    5040           0 :             IF( NE_32( ( error = ivas_reverb_open_fx( &pMcInput->crendWrapper->hCrend[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pMcInput->base.ctx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    5041             :             {
    5042           0 :                 return error;
    5043             :             }
    5044             :         }
    5045             :     }
    5046             : 
    5047             :     /* SBA inputs */
    5048           0 :     for ( i = 0, pSbaInput = hIvasRend->inputsSba; i < RENDERER_MAX_SBA_INPUTS; ++i, ++pSbaInput )
    5049             :     {
    5050           0 :         IF( EQ_32( pSbaInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    5051             :         {
    5052             :             /* Skip inactive inputs */
    5053           0 :             continue;
    5054             :         }
    5055           0 :         if ( pSbaInput->crendWrapper != NULL && pSbaInput->crendWrapper->hCrend[0] != NULL && pSbaInput->crendWrapper->hCrend[0]->hReverb != NULL )
    5056             :         {
    5057           0 :             IF( NE_32( ( error = ivas_reverb_open_fx( &pSbaInput->crendWrapper->hCrend[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pSbaInput->base.ctx.pOutSampleRate ) ), IVAS_ERR_OK ) )
    5058             :             {
    5059           0 :                 return error;
    5060             :             }
    5061             :         }
    5062             :     }
    5063             : #endif
    5064             : 
    5065           0 :     hRenderConfig->split_rend_config = renderConfig.split_rend_config;
    5066             :     /* Overwrite any pose correction settings if 0 DOF (no pose correction) was selected */
    5067           0 :     IF( EQ_16( hRenderConfig->split_rend_config.dof, 0 ) )
    5068             :     {
    5069           0 :         hRenderConfig->split_rend_config.poseCorrectionMode = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE;
    5070             :     }
    5071             : 
    5072           0 :     hRenderConfig->split_rend_config.codec = renderConfig.split_rend_config.codec;
    5073             : 
    5074           0 :     IF( ( error = isar_split_rend_validate_config( &hRenderConfig->split_rend_config, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0 ) ) != IVAS_ERR_OK )
    5075             :     {
    5076           0 :         return error;
    5077             :     }
    5078             : 
    5079             :     /* Must re-initialize split rendering config in case renderer config is updated after adding renderer inputs */
    5080             :     /* if its not initialized yet then no need to re-initialize, initialization will happen while adding inputs*/
    5081           0 :     IF( hIvasRend->splitRendEncBuffer.data_fx != NULL && hIvasRend->hRendererConfig != NULL )
    5082             :     {
    5083             :         Word16 cldfb_in_flag;
    5084           0 :         cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN );
    5085           0 :         IF( hIvasRend->splitRendWrapper != NULL )
    5086             :         {
    5087           0 :             ISAR_PRE_REND_close( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer );
    5088           0 :             free( hIvasRend->splitRendWrapper );
    5089           0 :             hIvasRend->splitRendWrapper = NULL;
    5090             :         }
    5091             : 
    5092           0 :         IF( ( error = ivas_pre_rend_init( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, hIvasRend->sampleRateOut, hIvasRend->outputConfig, cldfb_in_flag, hIvasRend->num_subframes ) ) != IVAS_ERR_OK )
    5093             :         {
    5094           0 :             return error;
    5095             :         }
    5096             :     }
    5097             : 
    5098           0 :     return IVAS_ERR_OK;
    5099             : }
    5100             : 
    5101             : /*-------------------------------------------------------------------*
    5102             :  * IVAS_REND_SetHeadRotation()
    5103             :  *
    5104             :  *
    5105             :  *-------------------------------------------------------------------*/
    5106      288060 : ivas_error IVAS_REND_SetHeadRotation(
    5107             :     IVAS_REND_HANDLE hIvasRend,              /* i/o: Renderer handle                            */
    5108             :     const IVAS_QUATERNION headRot,           /* i  : head orientations for next rendering call  */
    5109             :     const IVAS_VECTOR3 Pos,                  /* i  : listener positions for next rendering call */
    5110             :     const ISAR_SPLIT_REND_ROT_AXIS rot_axis, /* i  : external control for rotation axis for split rendering                  */
    5111             :     const Word16 sf_idx                      /* i  : subframe index                             */
    5112             : )
    5113             : {
    5114             :     Word16 i;
    5115             :     IVAS_QUATERNION rotQuat;
    5116             :     ivas_error error;
    5117             : 
    5118             :     /* Validate function arguments */
    5119      288060 :     IF( hIvasRend == NULL )
    5120             :     {
    5121           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    5122             :     }
    5123             : 
    5124      288060 :     IF( NE_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) )
    5125             :     {
    5126             :         /* Head rotation can be set only with binaural output */
    5127           0 :         return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    5128             :     }
    5129             : 
    5130      288060 :     hIvasRend->headRotData.headRotEnabled = 1;
    5131      288060 :     move16();
    5132             : 
    5133             :     /* reconfigure binaural rendering to allocate the necessary renderers and free unused ones */
    5134      576120 :     FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
    5135             :     {
    5136      288060 :         IF( NE_32( hIvasRend->inputsMc[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    5137             :         {
    5138       69615 :             IF( NE_32( ( error = initMcBinauralRendering( &hIvasRend->inputsMc[i], hIvasRend->inputsMc[i].base.inConfig, hIvasRend->outputConfig, hIvasRend->hRendererConfig, hIvasRend->hHrtfs.hSetOfHRTF, hIvasRend->hHrtfs.hHrtfStatistics, TRUE ) ), IVAS_ERR_OK ) )
    5139             :             {
    5140           0 :                 return error;
    5141             :             }
    5142             :         }
    5143             :     }
    5144             : 
    5145             :     /* check for Euler angle signaling */
    5146      288060 :     IF( EQ_32( headRot.w_fx, L_negate( 12582912 ) ) && EQ_16( headRot.q_fact, Q22 ) )
    5147             :     {
    5148           0 :         Euler2Quat_fx( deg2rad_fx( headRot.x_fx ), deg2rad_fx( headRot.y_fx ), deg2rad_fx( headRot.z_fx ), &rotQuat );
    5149           0 :         modify_Quat_q_fx( &rotQuat, &rotQuat, Q29 );
    5150             :     }
    5151             :     ELSE
    5152             :     {
    5153      288060 :         rotQuat = headRot;
    5154             :     }
    5155             : 
    5156      288060 :     Word32 updateRate_fx = 1677721600;                                // value is 200 in Q23
    5157      288060 :     rotQuat.w_fx = L_shl( rotQuat.w_fx, sub( Q29, rotQuat.q_fact ) ); /* Q29 */
    5158      288060 :     rotQuat.x_fx = L_shl( rotQuat.x_fx, sub( Q29, rotQuat.q_fact ) ); /* Q29 */
    5159      288060 :     rotQuat.y_fx = L_shl( rotQuat.y_fx, sub( Q29, rotQuat.q_fact ) ); /* Q29 */
    5160      288060 :     rotQuat.z_fx = L_shl( rotQuat.z_fx, sub( Q29, rotQuat.q_fact ) ); /* Q29 */
    5161             : 
    5162      288060 :     move32();
    5163      288060 :     move32();
    5164      288060 :     move32();
    5165      288060 :     move32();
    5166             : 
    5167      288060 :     hIvasRend->headRotData.hOrientationTracker->refRot.w_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->refRot.w_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->refRot.q_fact ) );          /* Q29 */
    5168      288060 :     hIvasRend->headRotData.hOrientationTracker->refRot.x_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->refRot.x_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->refRot.q_fact ) );          /* Q29 */
    5169      288060 :     hIvasRend->headRotData.hOrientationTracker->refRot.y_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->refRot.y_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->refRot.q_fact ) );          /* Q29 */
    5170      288060 :     hIvasRend->headRotData.hOrientationTracker->refRot.z_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->refRot.z_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->refRot.q_fact ) );          /* Q29 */
    5171      288060 :     hIvasRend->headRotData.hOrientationTracker->absAvgRot.w_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->absAvgRot.w_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->absAvgRot.q_fact ) ); /* Q29 */
    5172      288060 :     hIvasRend->headRotData.hOrientationTracker->absAvgRot.x_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->absAvgRot.x_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->absAvgRot.q_fact ) ); /* Q29 */
    5173      288060 :     hIvasRend->headRotData.hOrientationTracker->absAvgRot.y_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->absAvgRot.y_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->absAvgRot.q_fact ) ); /* Q29 */
    5174      288060 :     hIvasRend->headRotData.hOrientationTracker->absAvgRot.z_fx = L_shl( hIvasRend->headRotData.hOrientationTracker->absAvgRot.z_fx, sub( Q29, hIvasRend->headRotData.hOrientationTracker->absAvgRot.q_fact ) ); /* Q29 */
    5175             : 
    5176      288060 :     move32();
    5177      288060 :     move32();
    5178      288060 :     move32();
    5179      288060 :     move32();
    5180      288060 :     move32();
    5181      288060 :     move32();
    5182      288060 :     move32();
    5183      288060 :     move32();
    5184             : 
    5185      288060 :     hIvasRend->headRotData.hOrientationTracker->refRot.q_fact = Q29;
    5186      288060 :     hIvasRend->headRotData.hOrientationTracker->absAvgRot.q_fact = Q29;
    5187      288060 :     move16();
    5188      288060 :     move16();
    5189      288060 :     rotQuat.q_fact = Q29;
    5190             : 
    5191      288060 :     move16();
    5192      288060 :     IF( NE_32( ( error = ivas_orient_trk_Process_fx( hIvasRend->headRotData.hOrientationTracker, rotQuat, updateRate_fx, &hIvasRend->headRotData.headPositions[sf_idx] ) ), IVAS_ERR_OK ) )
    5193             :     {
    5194           0 :         return error;
    5195             :     }
    5196             : 
    5197      288060 :     hIvasRend->headRotData.sr_pose_pred_axis = rot_axis;
    5198             : 
    5199      288060 :     hIvasRend->headRotData.Pos[sf_idx] = Pos;
    5200             : 
    5201      288060 :     return IVAS_ERR_OK;
    5202             : }
    5203             : 
    5204             : /*-------------------------------------------------------------------*
    5205             :  * IVAS_REND_DisableHeadRotation()
    5206             :  *
    5207             :  *
    5208             :  *-------------------------------------------------------------------*/
    5209      946116 : ivas_error IVAS_REND_DisableHeadRotation(
    5210             :     IVAS_REND_HANDLE hIvasRend /* i/o: Renderer handle  */
    5211             : )
    5212             : {
    5213             :     Word16 i;
    5214             :     ivas_error error;
    5215             : 
    5216             :     /* Validate function arguments */
    5217      946116 :     IF( hIvasRend == NULL )
    5218             :     {
    5219           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    5220             :     }
    5221             : 
    5222      946116 :     hIvasRend->headRotData.headRotEnabled = 0;
    5223      946116 :     move32();
    5224             : 
    5225             :     /* reconfigure binaural rendering to allocate the necessary renderers and free unused ones */
    5226      946116 :     IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) )
    5227             :     {
    5228      360048 :         FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
    5229             :         {
    5230      180024 :             IF( NE_32( hIvasRend->inputsMc[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    5231             :             {
    5232       43506 :                 IF( NE_32( ( error = initMcBinauralRendering( &hIvasRend->inputsMc[i], hIvasRend->inputsMc[i].base.inConfig, hIvasRend->outputConfig, hIvasRend->hRendererConfig, hIvasRend->hHrtfs.hSetOfHRTF, hIvasRend->hHrtfs.hHrtfStatistics, TRUE ) ), IVAS_ERR_OK ) )
    5233             :                 {
    5234             : 
    5235           0 :                     return error;
    5236             :                 }
    5237             :             }
    5238             :         }
    5239             :     }
    5240             : 
    5241      946116 :     return IVAS_ERR_OK;
    5242             : }
    5243             : 
    5244             : 
    5245             : /*-------------------------------------------------------------------*
    5246             :  * IVAS_REND_SetSplitRendBFI()
    5247             :  *
    5248             :  *
    5249             :  *-------------------------------------------------------------------*/
    5250             : 
    5251           0 : ivas_error IVAS_REND_SetSplitRendBFI(
    5252             :     IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle      */
    5253             :     const Word16 bfi            /* i  : Bad Frame Indicator  */
    5254             : )
    5255             : {
    5256           0 :     hIvasRend->splitRendBFI = bfi;
    5257             : 
    5258           0 :     return IVAS_ERR_OK;
    5259             : }
    5260             : 
    5261             : 
    5262             : /*-------------------------------------------------------------------*
    5263             :  * IVAS_REND_SetOrientationTrackingMode()
    5264             :  *
    5265             :  *
    5266             :  *-------------------------------------------------------------------*/
    5267             : 
    5268         666 : ivas_error IVAS_REND_SetOrientationTrackingMode(
    5269             :     IVAS_REND_HANDLE hIvasRend,                       /* i/o: Renderer handle                */
    5270             :     const IVAS_HEAD_ORIENT_TRK_T orientation_tracking /* i  : Head orientation tracking type */
    5271             : )
    5272             : {
    5273             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    5274         666 :     if ( hIvasRend->headRotData.headRotEnabled == 0 )
    5275             :     {
    5276         572 :         return IVAS_ERR_OK;
    5277             :     }
    5278             : #endif
    5279             : 
    5280          94 :     return ivas_orient_trk_SetTrackingType_fx( hIvasRend->headRotData.hOrientationTracker, orientation_tracking );
    5281             : }
    5282             : 
    5283             : 
    5284             : /*-------------------------------------------------------------------*
    5285             :  * IVAS_REND_SetReferenceRotation()
    5286             :  *
    5287             :  *
    5288             :  *-------------------------------------------------------------------*/
    5289             : 
    5290           0 : ivas_error IVAS_REND_SetReferenceRotation(
    5291             :     IVAS_REND_HANDLE hIvasRend,  /* i/o: Renderer handle        */
    5292             :     const IVAS_QUATERNION refRot /* i  : Reference rotation     */
    5293             : )
    5294             : {
    5295             :     ivas_error error;
    5296             : 
    5297             :     /* Validate function arguments */
    5298           0 :     IF( hIvasRend == NULL )
    5299             :     {
    5300           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    5301             :     }
    5302             : 
    5303           0 :     error = ivas_orient_trk_SetReferenceRotation_fx( hIvasRend->headRotData.hOrientationTracker, refRot );
    5304             : 
    5305           0 :     IF( NE_32( error, IVAS_ERR_OK ) )
    5306             :     {
    5307             : 
    5308           0 :         return error;
    5309             :     }
    5310           0 :     return IVAS_ERR_OK;
    5311             : }
    5312             : 
    5313             : 
    5314             : /*-------------------------------------------------------------------*
    5315             :  * IVAS_REND_GetMainOrientation()
    5316             :  *
    5317             :  *
    5318             :  *-------------------------------------------------------------------*/
    5319             : 
    5320             : 
    5321             : /*-------------------------------------------------------------------*
    5322             :  * IVAS_REND_GetTrackedRotation()
    5323             :  *
    5324             :  *
    5325             :  *-------------------------------------------------------------------*/
    5326             : 
    5327             : 
    5328             : /*---------------------------------------------------------------------*
    5329             :  * IVAS_REND_SetReferenceVector( )
    5330             :  *
    5331             :  * Sets a reference vector spanning from listenerPos to refPos. Only
    5332             :  * available in OTR_TRACKING_REF_VEC and OTR_TRACKING_REF_VEC_LEV modes.
    5333             :  *---------------------------------------------------------------------*/
    5334             : 
    5335           0 : ivas_error IVAS_REND_SetReferenceVector(
    5336             :     IVAS_REND_HANDLE hIvasRend,     /* i/o: Renderer handle             */
    5337             :     const IVAS_VECTOR3 listenerPos, /* i  : Listener position           */
    5338             :     const IVAS_VECTOR3 refPos       /* i  : Reference position          */
    5339             : )
    5340             : {
    5341           0 :     test();
    5342           0 :     IF( hIvasRend == NULL || hIvasRend->headRotData.hOrientationTracker == NULL )
    5343             :     {
    5344           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    5345             :     }
    5346             : 
    5347           0 :     return ivas_orient_trk_SetReferenceVector_fx( hIvasRend->headRotData.hOrientationTracker, listenerPos, refPos );
    5348             : }
    5349             : 
    5350             : 
    5351             : /*---------------------------------------------------------------------*
    5352             :  * IVAS_REND_SetExternalOrientation()
    5353             :  *
    5354             :  *
    5355             :  *---------------------------------------------------------------------*/
    5356             : 
    5357           0 : ivas_error IVAS_REND_SetExternalOrientation(
    5358             :     IVAS_REND_HANDLE hIvasRend,          /* i/o: Renderer handle                                                         */
    5359             :     IVAS_QUATERNION *orientation,        /* i  : external orientation data                                               */
    5360             :     Word8 enableHeadRotation,            /* i  : flag to enable head rotation for this frame                             */
    5361             :     Word8 enableExternalOrientation,     /* i  : flag to enable external orientation for this frame                      */
    5362             :     Word8 enableRotationInterpolation,   /* i  : flag to interpolate rotations from current and previous frames          */
    5363             :     Word16 numFramesToTargetOrientation, /* i  : number of frames until target orientation is reached                    */
    5364             :     const Word16 sf_idx                  /* i  : subframe index                                                          */
    5365             : )
    5366             : {
    5367             :     /* Validate function arguments */
    5368           0 :     test();
    5369           0 :     IF( hIvasRend == NULL || hIvasRend->hExternalOrientationData == NULL )
    5370             :     {
    5371           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    5372             :     }
    5373             : 
    5374           0 :     IF( orientation == NULL )
    5375             :     {
    5376           0 :         hIvasRend->hExternalOrientationData->enableExternalOrientation[sf_idx] = 0;
    5377           0 :         move16();
    5378             :     }
    5379             :     ELSE
    5380             :     {
    5381           0 :         QuaternionInverse_fx( *orientation, &hIvasRend->hExternalOrientationData->Quaternions[sf_idx] );
    5382             : 
    5383           0 :         hIvasRend->hExternalOrientationData->enableHeadRotation[sf_idx] = enableHeadRotation;
    5384           0 :         hIvasRend->hExternalOrientationData->enableExternalOrientation[sf_idx] = enableExternalOrientation;
    5385           0 :         hIvasRend->hExternalOrientationData->enableRotationInterpolation[sf_idx] = enableRotationInterpolation;
    5386           0 :         hIvasRend->hExternalOrientationData->numFramesToTargetOrientation[sf_idx] = numFramesToTargetOrientation;
    5387           0 :         move16();
    5388           0 :         move16();
    5389           0 :         move16();
    5390           0 :         move16();
    5391             :     }
    5392             : 
    5393           0 :     return IVAS_ERR_OK;
    5394             : }
    5395             : 
    5396             : 
    5397             : /*---------------------------------------------------------------------*
    5398             :  * IVAS_REND_CombineHeadAndExternalOrientation()
    5399             :  *
    5400             :  *
    5401             :  *---------------------------------------------------------------------*/
    5402             : 
    5403     1126140 : ivas_error IVAS_REND_CombineHeadAndExternalOrientation(
    5404             :     IVAS_REND_HANDLE hIvasRend /* i/o: Renderer handle      */
    5405             : )
    5406             : {
    5407     1126140 :     IF( hIvasRend == NULL )
    5408             :     {
    5409           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    5410             :     }
    5411     1126140 :     ivas_error error = combine_external_and_head_orientations_rend( &hIvasRend->headRotData, hIvasRend->hExternalOrientationData, hIvasRend->hCombinedOrientationData );
    5412             : 
    5413     1126140 :     return error;
    5414             : }
    5415             : 
    5416             : 
    5417             : /*---------------------------------------------------------------------*
    5418             :  * IVAS_REND_GetCombinedOrientation()
    5419             :  *
    5420             :  *
    5421             :  *---------------------------------------------------------------------*/
    5422             : 
    5423             : 
    5424             : /*-------------------------------------------------------------------*
    5425             :  * Local functions
    5426             :  *-------------------------------------------------------------------*/
    5427             : /* Take one channel from input buffer and copy it to each channel
    5428             :        in output buffer, with different gain applied per output channel.
    5429             :        This function takes 2 gain vectors - one for the beginning and one
    5430             :        for the end of the buffer. Gain values are lineraly interpolated
    5431             :        for all samples in between. */
    5432             : /* Take one channel from input buffer and copy it to each channel
    5433             :        in output buffer, with different gain applied per output channel.
    5434             :        This function takes 2 gain vectors - one for the beginning and one
    5435             :        for the end of the buffer. Gain values are lineraly interpolated
    5436             :        for all samples in between. */
    5437     4992179 : static void renderBufferChannelLerp_fx(
    5438             :     const IVAS_REND_AudioBuffer inAudio,
    5439             :     const Word32 inChannelIdx,
    5440             :     const Word32 *const gainsCurrent, /* Q31 */
    5441             :     const Word32 *const gainsPrev,    /* Q31 */
    5442             :     IVAS_REND_AudioBuffer outAudio )
    5443             : {
    5444             :     const Word32 *inSmpl;
    5445             :     Word32 *outSmpl;
    5446             :     Word32 fadeIn;
    5447             :     Word32 fadeOut;
    5448             :     Word32 i;
    5449             :     const Word32 *lastInSmpl;
    5450             :     Word16 outChnlIdx;
    5451             :     Word32 currentGain;  /* Q31 */
    5452             :     Word32 previousGain; /* Q31 */
    5453             : 
    5454             :     /* Pointer to behind last input sample */
    5455     4992179 :     lastInSmpl = getSmplPtr_fx( inAudio, inChannelIdx, inAudio.config.numSamplesPerChannel );
    5456             : 
    5457    47433367 :     FOR( outChnlIdx = 0; outChnlIdx < outAudio.config.numChannels; ++outChnlIdx )
    5458             :     {
    5459    42441188 :         currentGain = gainsCurrent[outChnlIdx];
    5460    42441188 :         move32();
    5461    42441188 :         if ( gainsPrev == NULL )
    5462             :         {
    5463    39044000 :             previousGain = 0;
    5464    39044000 :             move32();
    5465             :         }
    5466             :         else
    5467             :         {
    5468     3397188 :             previousGain = gainsPrev[outChnlIdx];
    5469     3397188 :             move32();
    5470             :         }
    5471             : 
    5472             :         /* Process current output channel only if applying non-zero gains */
    5473    42441188 :         test();
    5474    42441188 :         test();
    5475    42441188 :         IF( GT_32( L_abs( currentGain ), EPSILON_FX ) || ( gainsPrev != NULL && GT_32( L_abs( previousGain ), EPSILON_FX ) ) )
    5476             :         {
    5477             :             /* Reset input pointer to the beginning of input channel */
    5478    23944469 :             inSmpl = getSmplPtr_fx( inAudio, inChannelIdx, 0 );
    5479             : 
    5480             :             /* Set output pointer to first output channel sample */
    5481    23944469 :             outSmpl = getSmplPtr_fx( outAudio, outChnlIdx, 0 );
    5482             : 
    5483    23944469 :             test();
    5484    23944469 :             IF( gainsPrev == NULL || LE_32( L_abs( L_sub( L_shr( previousGain, 1 ), L_shr( currentGain, 1 ) ) ), EPSILON_FX ) )
    5485             :             {
    5486             :                 /* If no interpolation from previous frame, apply current gain */
    5487             :                 DO
    5488             :                 {
    5489  8798392080 :                     *outSmpl = L_add( Mpy_32_32( currentGain, ( *inSmpl ) ), *outSmpl );
    5490  8798392080 :                     move32();
    5491  8798392080 :                     ++outSmpl;
    5492  8798392080 :                     ++inSmpl;
    5493             :                 }
    5494  8798392080 :                 WHILE( inSmpl != lastInSmpl );
    5495             :             }
    5496             :             ELSE
    5497             :             {
    5498     1996136 :                 i = 0;
    5499     1996136 :                 Word32 tmp = Q31_BY_SUB_FRAME_240;
    5500     1996136 :                 Word32 tmp1 = 239; /* L_SUBFRAME_48k - 1 */
    5501     1996136 :                 move32();
    5502     1996136 :                 move32();
    5503     1996136 :                 move32();
    5504     1996136 :                 SWITCH( outAudio.config.numSamplesPerChannel )
    5505             :                 {
    5506     1051037 :                     case NUM_SAMPLES_960:
    5507     1051037 :                         tmp = Q31_BY_NUM_SAMPLES_960;
    5508     1051037 :                         tmp1 = 959; /* NUM_SAMPLES_960 - 1 */
    5509     1051037 :                         move32();
    5510     1051037 :                         move32();
    5511     1051037 :                         BREAK;
    5512           0 :                     case NUM_SAMPLES_720:
    5513           0 :                         tmp = Q31_BY_NUM_SAMPLES_720;
    5514           0 :                         tmp1 = 719; /* NUM_SAMPLES_720 - 1 */
    5515           0 :                         move32();
    5516           0 :                         move32();
    5517           0 :                         BREAK;
    5518           0 :                     case NUM_SAMPLES_640:
    5519           0 :                         tmp = Q31_BY_NUM_SAMPLES_640;
    5520           0 :                         tmp1 = 639; /* NUM_SAMPLES_640 - 1 */
    5521           0 :                         move32();
    5522           0 :                         move32();
    5523           0 :                         BREAK;
    5524           0 :                     case NUM_SAMPLES_320:
    5525           0 :                         tmp = Q31_BY_NUM_SAMPLES_320;
    5526           0 :                         tmp1 = 319; /* NUM_SAMPLES_320 - 1 */
    5527           0 :                         move32();
    5528           0 :                         move32();
    5529           0 :                         BREAK;
    5530           0 :                     case L_SUBFRAME_32k:
    5531           0 :                         tmp = Q31_BY_NUM_SAMPLES_160;
    5532           0 :                         tmp1 = 159; /* NUM_SAMPLES_160 - 1 */
    5533           0 :                         move32();
    5534           0 :                         move32();
    5535           0 :                         BREAK;
    5536      945099 :                     case L_SUBFRAME_48k:
    5537      945099 :                         tmp = Q31_BY_SUB_FRAME_240;
    5538      945099 :                         tmp1 = 239; /* L_SUBFRAME_48k - 1 */
    5539      945099 :                         move32();
    5540      945099 :                         move32();
    5541      945099 :                         BREAK;
    5542           0 :                     case L_SUBFRAME_16k:
    5543           0 :                         tmp = Q31_BY_SUB_FRAME_80;
    5544           0 :                         tmp1 = 79; /* L_SUBFRAME_16k - 1 */
    5545           0 :                         move32();
    5546           0 :                         move32();
    5547           0 :                         BREAK;
    5548           0 :                     case L_SUBFRAME_8k:
    5549           0 :                         tmp = Q31_BY_SUB_FRAME_40;
    5550           0 :                         tmp1 = 39; /* L_SUBFRAME_8k - 1 */
    5551           0 :                         move32();
    5552           0 :                         move32();
    5553           0 :                         BREAK;
    5554           0 :                     default:
    5555           0 :                         BREAK;
    5556             :                 }
    5557             :                 /* Otherwise use weighted average between previous and current gain */
    5558  1233823144 :                 DO
    5559             :                 {
    5560  1235819280 :                     IF( EQ_32( i, tmp1 ) )
    5561             :                     {
    5562     1996136 :                         fadeIn = ONE_IN_Q31;
    5563     1996136 :                         move32();
    5564             :                     }
    5565             :                     ELSE
    5566             :                     {
    5567  1233823144 :                         fadeIn = UL_Mpy_32_32( i, tmp );
    5568             :                     }
    5569  1235819280 :                     fadeOut = L_sub( ONE_IN_Q31, fadeIn );
    5570             : 
    5571  1235819280 :                     *outSmpl = L_add( Mpy_32_32( L_add( Mpy_32_32( fadeIn, currentGain ), Mpy_32_32( fadeOut, previousGain ) ), ( *inSmpl ) ), *outSmpl );
    5572  1235819280 :                     move32();
    5573  1235819280 :                     ++outSmpl;
    5574  1235819280 :                     ++inSmpl;
    5575  1235819280 :                     ++i;
    5576             :                 }
    5577  1235819280 :                 WHILE( inSmpl != lastInSmpl );
    5578             :             }
    5579             :         }
    5580             :     }
    5581             : 
    5582     4992179 :     return;
    5583             : }
    5584             : 
    5585             : 
    5586             : /* Take one channel from input buffer and copy it to each channel
    5587             :        in output buffer, with different gain applied per output channel */
    5588     4044679 : static void renderBufferChannel_fx(
    5589             :     const IVAS_REND_AudioBuffer inAudio,
    5590             :     const Word32 inChannelIdx,
    5591             :     const Word32 *const outputGains, /* Q31 */
    5592             :     IVAS_REND_AudioBuffer outAudio )
    5593             : {
    5594     4044679 :     renderBufferChannelLerp_fx( inAudio, inChannelIdx, outputGains, NULL, outAudio );
    5595             : 
    5596     4044679 :     return;
    5597             : }
    5598             : 
    5599       70522 : static ivas_error chooseCrossfade_fx(
    5600             :     const IVAS_REND_HeadRotData *headRotData,
    5601             :     const Word32 **pCrossfade /* Q31 */ )
    5602             : {
    5603       70522 :     *pCrossfade = headRotData->crossfade_fx;
    5604             : 
    5605       70522 :     return IVAS_ERR_OK;
    5606             : }
    5607             : 
    5608             : 
    5609       25504 : static ivas_error rotateFrameMc_fx(
    5610             :     IVAS_REND_AudioBuffer inAudio,                               /* i  : Input Audio buffer               */
    5611             :     AUDIO_CONFIG inConfig,                                       /* i  : Input Audio config               */
    5612             :     const LSSETUP_CUSTOM_STRUCT *pInCustomLs,                    /* i  : Input Custom LS setup            */
    5613             :     const IVAS_REND_HeadRotData *headRotData,                    /* i  : Head rotation data               */
    5614             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i  : Combined head and external orientations */
    5615             :     rotation_gains_Word32 gains_prev,                            /* i/o: Previous frame rotation gains    */
    5616             :     const EFAP_HANDLE hEFAPdata,                                 /* i  : EFAP structure                   */
    5617             :     IVAS_REND_AudioBuffer outAudio                               /* o  : Output Audio buffer              */
    5618             : )
    5619             : {
    5620             :     Word16 i;
    5621             :     Word16 j;
    5622             :     const Word32 *crossfade; /* Q31 */
    5623             :     Word16 num_subframes;
    5624             :     Word16 subframe_idx, subframe_len;
    5625             :     Word32 azimuth_fx, elevation_fx; /* Q22 */
    5626             :     Word16 is_planar_setup, lfe_idx;
    5627             :     Word16 nchan;
    5628             :     Word16 ch_in, ch_out;
    5629             :     Word16 ch_in_woLFE, ch_out_woLFE;
    5630       25504 :     Word32 *readPtr, *writePtr = NULL;
    5631             :     const Word32 *ls_azimuth, *ls_elevation;
    5632             :     rotation_matrix_fx Rmat_fx;
    5633             :     rotation_gains_Word32 gains;
    5634             :     Word32 tmp_gains[MAX_INPUT_CHANNELS]; /* Q30 */
    5635             :     ivas_error error;
    5636             : 
    5637       25504 :     push_wmops( "rotateFrameMc_fx" );
    5638       25504 :     IF( NE_32( ( error = chooseCrossfade_fx( headRotData, &crossfade ) ), IVAS_ERR_OK ) )
    5639             :     {
    5640           0 :         return error;
    5641             :     }
    5642       25504 :     IF( ( hCombinedOrientationData != NULL ) )
    5643             :     {
    5644       25504 :         num_subframes = ( *hCombinedOrientationData )->num_subframes;
    5645             :     }
    5646             :     ELSE
    5647             :     {
    5648           0 :         num_subframes = MAX_PARAM_SPATIAL_SUBFRAMES;
    5649             :     }
    5650       25504 :     move16();
    5651             : 
    5652       25504 :     IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    5653             :     {
    5654       12500 :         IF( NE_32( ( error = getAudioConfigNumChannels( inConfig, &nchan ) ), IVAS_ERR_OK ) )
    5655             :         {
    5656           0 :             return error;
    5657             :         }
    5658             :     }
    5659             :     ELSE
    5660             :     {
    5661       13004 :         nchan = add( pInCustomLs->num_spk, pInCustomLs->num_lfe );
    5662             :     }
    5663             : 
    5664       25504 :     IF( NE_32( ( error = getMcConfigValues_fx( inConfig, pInCustomLs, &ls_azimuth, &ls_elevation, &lfe_idx, &is_planar_setup ) ), IVAS_ERR_OK ) )
    5665             :     {
    5666           0 :         return error;
    5667             :     }
    5668             : 
    5669             :     /* initialize gains to passthrough */
    5670      319068 :     FOR( ch_in = 0; ch_in < nchan; ch_in++ )
    5671             :     {
    5672      293564 :         set32_fx( gains[ch_in], 0, nchan );
    5673      293564 :         gains[ch_in][ch_in] = ONE_IN_Q30;
    5674      293564 :         move32();
    5675             :     }
    5676             : 
    5677             :     /* subframe loop */
    5678             :     Word16 tmp_e;
    5679       25504 :     Word16 tmp = BASOP_Util_Divide3216_Scale( inAudio.config.numSamplesPerChannel, num_subframes, &tmp_e );
    5680       25504 :     tmp = shr( tmp, negate( add( 1, tmp_e ) ) );
    5681       25504 :     subframe_len = tmp;
    5682       25504 :     move16();
    5683             : 
    5684       66314 :     FOR( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
    5685             :     {
    5686      163240 :         FOR( i = 0; i < 3; i++ )
    5687             :         {
    5688      122430 :             IF( hCombinedOrientationData != NULL )
    5689             :             {
    5690      489720 :                 FOR( j = 0; j < 3; j++ )
    5691             :                 {
    5692      367290 :                     Rmat_fx[i][j] = ( *hCombinedOrientationData )->Rmat_fx[subframe_idx][i][j];
    5693      367290 :                     move32();
    5694             :                 }
    5695             :             }
    5696             :             ELSE
    5697             :             {
    5698             :                 /* Set to identity */
    5699           0 :                 set32_fx( Rmat_fx[i], 0, 3 );
    5700           0 :                 Rmat_fx[i][i] = ONE_IN_Q30;
    5701           0 :                 move32();
    5702             :             }
    5703             :         }
    5704             : 
    5705      510570 :         FOR( ch_in = 0; ch_in < nchan; ch_in++ )
    5706             :         {
    5707             :             /* skip LFE */
    5708      469760 :             IF( EQ_16( ch_in, lfe_idx ) )
    5709             :             {
    5710       20000 :                 CONTINUE;
    5711             :             }
    5712             : 
    5713             :             /* input channel index without LFE */
    5714      449760 :             test();
    5715      449760 :             IF( ( lfe_idx > 0 ) && ( GE_16( ch_in, lfe_idx ) ) )
    5716             :             {
    5717       85600 :                 ch_in_woLFE = sub( ch_in, 1 );
    5718             :             }
    5719             :             ELSE
    5720             :             {
    5721      364160 :                 ch_in_woLFE = ch_in;
    5722      364160 :                 move16();
    5723             :             }
    5724             : 
    5725             : 
    5726             :             /* gains for current subframe rotation */
    5727      449760 :             rotateAziEle_fixed( (Word16) L_shr( ls_azimuth[ch_in_woLFE], 22 ), (Word16) L_shr( ls_elevation[ch_in_woLFE], 22 ), &azimuth_fx, &elevation_fx, Rmat_fx, is_planar_setup );
    5728             : 
    5729      449760 :             test();
    5730      449760 :             test();
    5731      449760 :             IF( hEFAPdata != NULL && ( NE_32( ls_azimuth[ch_in_woLFE], azimuth_fx ) || NE_32( ls_elevation[ch_in_woLFE], elevation_fx ) ) )
    5732             :             {
    5733      144730 :                 efap_determine_gains_fx( hEFAPdata, tmp_gains, azimuth_fx, elevation_fx, EFAP_MODE_EFAP );
    5734             : 
    5735     1444790 :                 FOR( ch_out = 0; ch_out < nchan; ch_out++ )
    5736             :                 {
    5737             :                     /* skip LFE */
    5738     1300060 :                     IF( EQ_16( ch_out, lfe_idx ) )
    5739             :                     {
    5740      144730 :                         CONTINUE;
    5741             :                     }
    5742             : 
    5743             :                     /* output channel index without LFE */
    5744     1155330 :                     test();
    5745     1155330 :                     IF( ( lfe_idx > 0 ) && ( GE_16( ch_out, lfe_idx ) ) )
    5746             :                     {
    5747      721140 :                         ch_out_woLFE = sub( ch_out, 1 );
    5748             :                     }
    5749             :                     ELSE
    5750             :                     {
    5751      434190 :                         ch_out_woLFE = ch_out;
    5752      434190 :                         move16();
    5753             :                     }
    5754             : 
    5755     1155330 :                     gains[ch_in][ch_out] = tmp_gains[ch_out_woLFE]; // Q30
    5756     1155330 :                     move32();
    5757             :                 }
    5758             :             }
    5759             :         }
    5760             : 
    5761             :         /* apply panning gains by mtx multiplication */
    5762      510570 :         FOR( ch_out = 0; ch_out < nchan; ch_out++ )
    5763             :         {
    5764     6541120 :             FOR( ch_in = 0; ch_in < nchan; ch_in++ )
    5765             :             {
    5766     6071360 :                 writePtr = getSmplPtr_fx( outAudio, ch_out, imult1616( subframe_idx, subframe_len ) ); /* Qx */
    5767     6071360 :                 readPtr = getSmplPtr_fx( inAudio, ch_in, imult1616( subframe_idx, subframe_len ) );    /* Qx */
    5768             :                 /* crossfade with previous rotation gains */
    5769  1463197760 :                 FOR( i = 0; i < subframe_len; i++ )
    5770             :                 {
    5771  1457126400 :                     *writePtr =
    5772  1457126400 :                         L_add( *writePtr, L_add( Mpy_32_32( ( *readPtr ), Mpy_32_32( L_sub( ONE_IN_Q31, crossfade[i] ), gains_prev[ch_in][ch_out] ) ),
    5773  1457126400 :                                                  Mpy_32_32( ( *readPtr ), Mpy_32_32( crossfade[i], gains[ch_in][ch_out] ) ) ) ); /* Qx - 1 */
    5774  1457126400 :                     move32();
    5775  1457126400 :                     readPtr++;
    5776  1457126400 :                     writePtr++;
    5777             :                 }
    5778             :             }
    5779             :         }
    5780             : 
    5781             :         /* move gains to gains_prev */
    5782      510570 :         FOR( i = 0; i < nchan; i++ )
    5783             :         {
    5784      469760 :             MVR2R_WORD32( gains[i], gains_prev[i], nchan );
    5785             :         }
    5786             :     }
    5787             : 
    5788       25504 :     pop_wmops();
    5789       25504 :     return IVAS_ERR_OK;
    5790             : }
    5791             : 
    5792             : 
    5793       45018 : static ivas_error rotateFrameSba_fx(
    5794             :     IVAS_REND_AudioBuffer inAudio,                               /* i  : Input Audio buffer                      */
    5795             :     const AUDIO_CONFIG inConfig,                                 /* i  : Input Audio config                      */
    5796             :     const IVAS_REND_HeadRotData *headRotData,                    /* i  : Head rotation data                      */
    5797             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData, /* i  : Combined head and external orientations */
    5798             :     Word16 gains_prev[MAX_INPUT_CHANNELS][MAX_INPUT_CHANNELS],   /* i/o: Previous frame rotation gains       Q14 */
    5799             :     IVAS_REND_AudioBuffer outAudio                               /* o  : Output Audio buffer                     */
    5800             : )
    5801             : {
    5802             :     Word16 i, l, n, m;
    5803             :     Word16 m1, m2;
    5804             :     Word16 shd_rot_max_order;
    5805             :     const Word32 *crossfade; /* Q31 */
    5806             :     Word16 num_subframes;
    5807             :     Word16 subframe_idx, subframe_len;
    5808             :     Word32 *writePtr;
    5809             :     Word32 tmpRot[2 * HEADROT_ORDER + 1];
    5810             :     Word16 gains[HEADROT_SHMAT_DIM][HEADROT_SHMAT_DIM]; /* Q14 */
    5811             :     Word32 temp;
    5812             :     Word32 Rmat[3][3]; /* Q30 */
    5813             :     ivas_error error;
    5814             :     Word16 idx, exp;
    5815             :     Word32 cf, oneminuscf; /* Q31 */
    5816             :     Word32 val;
    5817             : 
    5818       45018 :     push_wmops( "rotateFrameSba" );
    5819             : 
    5820       45018 :     IF( NE_32( ( error = chooseCrossfade_fx( headRotData, &crossfade ) ), IVAS_ERR_OK ) )
    5821             :     {
    5822           0 :         return error;
    5823             :     }
    5824       45018 :     num_subframes = ( hCombinedOrientationData != NULL ) ? ( *hCombinedOrientationData )->num_subframes : MAX_PARAM_SPATIAL_SUBFRAMES;
    5825       45018 :     move16();
    5826             : 
    5827       45018 :     IF( NE_32( ( error = getAmbisonicsOrder_fx( inConfig, &shd_rot_max_order ) ), IVAS_ERR_OK ) )
    5828             :     {
    5829           0 :         return error;
    5830             :     }
    5831             : 
    5832             :     // subframe_len = inAudio.config.numSamplesPerChannel / num_subframes;
    5833       45018 :     subframe_len = BASOP_Util_Divide1616_Scale( inAudio.config.numSamplesPerChannel, num_subframes, &exp );
    5834       45018 :     subframe_len = shr( subframe_len, sub( 15, exp ) );
    5835      117063 :     FOR( subframe_idx = 0; subframe_idx < num_subframes; subframe_idx++ )
    5836             :     {
    5837             :         /* initialize rotation matrices with zeros */
    5838     1224765 :         FOR( i = 0; i < HEADROT_SHMAT_DIM; i++ )
    5839             :         {
    5840     1152720 :             set16_fx( gains[i], 0, HEADROT_SHMAT_DIM );
    5841             :         }
    5842             : 
    5843      288180 :         FOR( i = 0; i < 3; i++ )
    5844             :         {
    5845      216135 :             IF( hCombinedOrientationData != NULL )
    5846             :             {
    5847      864540 :                 FOR( l = 0; l < 3; l++ )
    5848             :                 {
    5849      648405 :                     Rmat[i][l] = ( *hCombinedOrientationData )->Rmat_fx[subframe_idx][i][l]; /* Q30 */
    5850      648405 :                     move32();
    5851             :                 }
    5852             :             }
    5853             :             ELSE
    5854             :             {
    5855             :                 /* Set to identity */
    5856           0 :                 set32_fx( Rmat[i], 0, 3 );
    5857           0 :                 Rmat[i][i] = ONE_IN_Q30;
    5858           0 :                 move32();
    5859             :             }
    5860             :         }
    5861             :         /* calculate ambisonics rotation matrices for the previous and current frames */
    5862       72045 :         SHrotmatgen_fx( gains, Rmat, shd_rot_max_order );
    5863             : 
    5864             : #ifdef DEBUGGING
    5865             :         dbgwrite_txt( (const float *) ( gains[0] ), HEADROT_SHMAT_DIM * HEADROT_SHMAT_DIM, "Fixed_code_gains.txt", NULL );
    5866             :         dbgwrite_txt( (const float *) ( Rmat[0] ), 3 * 3, "Fixed_code_Rmat.txt", NULL );
    5867             : #endif
    5868    17362845 :         FOR( i = 0; i < subframe_len; i++ )
    5869             :         {
    5870    17290800 :             idx = add( imult1616( subframe_idx, subframe_len ), i );
    5871             :             // cf = crossfade[i];
    5872    17290800 :             cf = crossfade[i];
    5873    17290800 :             move32();
    5874    17290800 :             oneminuscf = L_sub( ONE_IN_Q31, cf );
    5875             :             /*    As the rotation matrix becomes block diagonal in a SH basis, we can*/
    5876             :             /*      apply each angular-momentum block individually to save complexity. */
    5877             : 
    5878             :             /*    loop over l blocks */
    5879    17290800 :             m1 = 1;
    5880    17290800 :             m2 = 4;
    5881    17290800 :             move16();
    5882    17290800 :             move16();
    5883    51872400 :             FOR( l = 1; l <= shd_rot_max_order; l++ )
    5884             :             {
    5885             :                 /* compute mtx-vector product for this l  */
    5886   184435200 :                 FOR( n = m1; n < m2; n++ )
    5887             :                 {
    5888   149853600 :                     tmpRot[n - m1] = 0;
    5889   149853600 :                     move32();
    5890   876067200 :                     FOR( m = m1; m < m2; m++ )
    5891             :                     {
    5892   726213600 :                         val = inAudio.data_fx[m * inAudio.config.numSamplesPerChannel + idx];
    5893             :                         /* crossfade with previous rotation gains */
    5894   726213600 :                         temp = Mpy_32_32( L_add( Mpy_32_16_r( cf, gains[n][m] ), ( Mpy_32_16_r( oneminuscf, gains_prev[n][m] ) ) ), val );
    5895   726213600 :                         tmpRot[n - m1] = L_add( L_shl( temp, 1 ), tmpRot[n - m1] );
    5896   726213600 :                         move32();
    5897   726213600 :                         move32();
    5898             :                     }
    5899             :                 }
    5900             :                 /* write back the result */
    5901   184435200 :                 FOR( n = m1; n < m2; n++ )
    5902             :                 {
    5903   149853600 :                     writePtr = getSmplPtr_fx( outAudio, n, idx );
    5904   149853600 :                     ( *writePtr ) = tmpRot[n - m1];
    5905   149853600 :                     move32();
    5906             :                 }
    5907    34581600 :                 m1 = m2;
    5908    34581600 :                 move16();
    5909    34581600 :                 m2 = add( m2, add( shl( add( l, 1 ), 1 ), 1 ) );
    5910             :             }
    5911             :         }
    5912             : 
    5913             :         /* move SHrotmat to SHrotmat_prev */
    5914     1224765 :         FOR( i = 0; i < HEADROT_SHMAT_DIM; i++ )
    5915             :         {
    5916     1152720 :             Copy( gains[i], gains_prev[i], HEADROT_SHMAT_DIM );
    5917             :         }
    5918             :     }
    5919       45018 :     pop_wmops();
    5920             : 
    5921       45018 :     return IVAS_ERR_OK;
    5922             : }
    5923             : 
    5924             : 
    5925      150000 : static ivas_error renderIsmToBinaural(
    5926             :     input_ism *ismInput,
    5927             :     IVAS_REND_AudioBuffer outAudio )
    5928             : {
    5929             :     Word32 tmpTDRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    5930             :     ivas_error error;
    5931             :     Word16 ism_md_subframe_update_ext;
    5932             :     Word16 i;
    5933      150000 :     Word16 exp = *outAudio.pq_fact;
    5934      150000 :     move16();
    5935             : 
    5936      150000 :     push_wmops( "renderIsmToBinaural" );
    5937             :     /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */
    5938      150000 :     ism_md_subframe_update_ext = extract_l( Mpy_32_32( ismInput->ism_metadata_delay_ms_fx, 429496730 /* 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES in Q31 */ ) );
    5939      150000 :     copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpTDRendBuffer );
    5940             : 
    5941     2550000 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    5942             :     {
    5943     2400000 :         Scale_sig32( tmpTDRendBuffer[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */
    5944             :     }
    5945             : 
    5946      150000 :     IF( NE_32( ( error = ivas_td_binaural_renderer_ext_fx( &ismInput->tdRendWrapper, ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, ismInput->hReverb, ism_md_subframe_update_ext,
    5947             :                                                            *ismInput->base.ctx.pOutSampleRate, outAudio.config.numSamplesPerChannel, tmpTDRendBuffer, &exp ) ),
    5948             :                IVAS_ERR_OK ) )
    5949             :     {
    5950           0 :         return error;
    5951             :     }
    5952             : 
    5953     2550000 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    5954             :     {
    5955     2400000 :         Scale_sig32( tmpTDRendBuffer[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */
    5956             :     }
    5957             : 
    5958      150000 :     IF( ismInput->hReverb != NULL )
    5959             :     {
    5960           0 :         FOR( i = 0; i < outAudio.config.numChannels; i++ )
    5961             :         {
    5962           0 :             FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel; j++ )
    5963             :             {
    5964           0 :                 tmpTDRendBuffer[i][j] = L_shl( tmpTDRendBuffer[i][j], Q2 ); /* Q(exp + 2) */
    5965           0 :                 move32();
    5966             :             }
    5967             :         }
    5968             :     }
    5969      150000 :     accumulate2dArrayToBuffer_fx( tmpTDRendBuffer, &outAudio );
    5970             : 
    5971      150000 :     pop_wmops();
    5972             : 
    5973      150000 :     return IVAS_ERR_OK;
    5974             : }
    5975             : 
    5976             : 
    5977           0 : static Word16 getNumSubframesInBuffer(
    5978             :     const IVAS_REND_AudioBuffer *buffer,
    5979             :     const Word32 sampleRate )
    5980             : {
    5981             :     Word16 cldfb2tdShift;
    5982             : 
    5983           0 :     cldfb2tdShift = buffer->config.is_cldfb ? 1 : 0;
    5984             : 
    5985           0 :     Word16 scale, temp = extract_l( Mpy_32_32( sampleRate, 10737418 /* 1 / FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES in Q31 */ ) );
    5986           0 :     temp = BASOP_Util_Divide1616_Scale( buffer->config.numSamplesPerChannel, temp, &scale );
    5987           0 :     temp = shr( temp, sub( 15, scale ) ); /* Q0 */
    5988           0 :     temp = shr( temp, cldfb2tdShift );
    5989             : 
    5990           0 :     return temp;
    5991             : }
    5992             : 
    5993             : 
    5994      150000 : static ivas_error renderIsmToBinauralRoom(
    5995             :     input_ism *ismInput,
    5996             :     IVAS_REND_AudioBuffer outAudio,
    5997             :     Word16 *exp )
    5998             : {
    5999             :     Word16 position_changed;
    6000             :     Word16 i, j;
    6001             :     Word32 azi_rot, ele_rot; /* Q22 */
    6002             :     Word16 subframe_idx;
    6003             :     Word16 tmp;
    6004             :     rotation_matrix_fx Rmat;
    6005             :     Word32 tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    6006             :     ivas_error error;
    6007             :     pan_vector_fx currentPanGains;
    6008             :     IVAS_REND_AudioBuffer tmpMcBuffer;
    6009             :     IVAS_ISM_METADATA rotatedPosPrev;
    6010             :     IVAS_ISM_METADATA rotatedPos;
    6011             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
    6012             :     Word8 combinedOrientationEnabled;
    6013             :     Word32 *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS];
    6014             : 
    6015     2550000 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    6016             :     {
    6017     2400000 :         p_tmpRendBuffer[i] = tmpRendBuffer[i];
    6018             :     }
    6019             : 
    6020      150000 :     push_wmops( "renderIsmToBinauralRoom" );
    6021             : 
    6022      150000 :     rotatedPosPrev = defaultObjectPosition();
    6023      150000 :     rotatedPos = defaultObjectPosition();
    6024             : 
    6025      150000 :     hCombinedOrientationData = ismInput->base.ctx.pCombinedOrientationData;
    6026      150000 :     combinedOrientationEnabled = 0;
    6027      150000 :     move16();
    6028             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    6029      150000 :     IF( *hCombinedOrientationData != NULL )
    6030             : #else
    6031             :     IF( hCombinedOrientationData != NULL )
    6032             : #endif
    6033             :     {
    6034       75000 :         FOR( subframe_idx = 0; subframe_idx < ( *hCombinedOrientationData )->num_subframes; subframe_idx++ )
    6035             :         {
    6036       75000 :             IF( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
    6037             :             {
    6038       75000 :                 combinedOrientationEnabled = 1;
    6039       75000 :                 move16();
    6040       75000 :                 BREAK;
    6041             :             }
    6042             :         }
    6043             :     }
    6044             : 
    6045      150000 :     IF( combinedOrientationEnabled )
    6046             :     {
    6047      150000 :         FOR( subframe_idx = 0; subframe_idx < 1; subframe_idx++ )
    6048             :         {
    6049      300000 :             FOR( i = 0; i < 3; i++ )
    6050             :             {
    6051      225000 :                 test();
    6052      225000 :                 IF( hCombinedOrientationData != NULL && ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] )
    6053             :                 {
    6054      900000 :                     FOR( j = 0; j < 3; j++ )
    6055             :                     {
    6056      675000 :                         Rmat[i][j] = ( *hCombinedOrientationData )->Rmat_fx[subframe_idx][i][j];
    6057      675000 :                         move32();
    6058             :                     }
    6059             :                 }
    6060             :                 ELSE
    6061             :                 {
    6062             :                     /* Set to identity */
    6063           0 :                     set_zero_fx( Rmat[i], 3 );
    6064           0 :                     Rmat[i][i] = ONE_IN_Q30;
    6065           0 :                     move32();
    6066             :                 }
    6067             :             }
    6068             :         }
    6069             :     }
    6070             : 
    6071             :     /* get previous position */
    6072      150000 :     IF( combinedOrientationEnabled )
    6073             :     {
    6074       75000 :         rotateAziEle_fx_frac_az_el( ismInput->previousPos.azimuth_fx, ismInput->previousPos.elevation_fx, &azi_rot, &ele_rot, ismInput->rot_mat_prev, 0 );
    6075       75000 :         rotatedPosPrev.azimuth_fx = azi_rot;
    6076       75000 :         move32();
    6077       75000 :         rotatedPosPrev.elevation_fx = ele_rot;
    6078       75000 :         move32();
    6079             :     }
    6080             :     ELSE
    6081             :     {
    6082       75000 :         rotatedPosPrev.azimuth_fx = ismInput->previousPos.azimuth_fx;
    6083       75000 :         move32();
    6084       75000 :         rotatedPosPrev.elevation_fx = ismInput->previousPos.elevation_fx;
    6085       75000 :         move32();
    6086             :     }
    6087             : 
    6088             :     /* get current position */
    6089      150000 :     IF( combinedOrientationEnabled )
    6090             :     {
    6091       75000 :         rotateAziEle_fx_frac_az_el( ismInput->currentPos.azimuth_fx, ismInput->currentPos.elevation_fx, &azi_rot, &ele_rot, Rmat, 0 );
    6092       75000 :         rotatedPos.azimuth_fx = azi_rot;
    6093       75000 :         move32();
    6094       75000 :         rotatedPos.elevation_fx = ele_rot;
    6095       75000 :         move32();
    6096             :     }
    6097             :     ELSE
    6098             :     {
    6099       75000 :         rotatedPos.azimuth_fx = ismInput->currentPos.azimuth_fx;
    6100       75000 :         move32();
    6101       75000 :         rotatedPos.elevation_fx = ismInput->currentPos.elevation_fx;
    6102       75000 :         move32();
    6103             :     }
    6104             : 
    6105      150000 :     test();
    6106      150000 :     position_changed = !ismInput->firstFrameRendered || checkObjectPositionChanged_fx( &rotatedPos, &rotatedPosPrev );
    6107      150000 :     move16();
    6108             : 
    6109             :     /* set previous gains if this is the first frame */
    6110      150000 :     IF( NE_32( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper, rotatedPosPrev.azimuth_fx, rotatedPosPrev.elevation_fx, ismInput->prev_pan_gains_fx ) ), IVAS_ERR_OK ) )
    6111             :     {
    6112           0 :         return error;
    6113             :     }
    6114             : 
    6115             :     /* compute gains only if position changed */
    6116      150000 :     IF( position_changed )
    6117             :     {
    6118       64693 :         IF( NE_32( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper, rotatedPos.azimuth_fx, rotatedPos.elevation_fx, currentPanGains ) ),
    6119             :                    IVAS_ERR_OK ) )
    6120             :         {
    6121           0 :             return error;
    6122             :         }
    6123             :     }
    6124             : 
    6125             :     /* intermediate rendering to 7_1_4 */
    6126      150000 :     tmpMcBuffer = ismInput->base.inputBuffer;
    6127             : 
    6128      150000 :     IF( NE_32( ( error = getAudioConfigNumChannels( IVAS_AUDIO_CONFIG_7_1_4, &tmp ) ), IVAS_ERR_OK ) )
    6129             :     {
    6130           0 :         return error;
    6131             :     }
    6132             : 
    6133      150000 :     tmpMcBuffer.config.numChannels = tmp;
    6134      150000 :     move16();
    6135      150000 :     tmpMcBuffer.data_fx = malloc( imult1616( tmpMcBuffer.config.numSamplesPerChannel, tmpMcBuffer.config.numChannels ) * sizeof( Word32 ) );
    6136      150000 :     set_zero_fx( tmpMcBuffer.data_fx, imult1616( tmpMcBuffer.config.numSamplesPerChannel, tmpMcBuffer.config.numChannels ) );
    6137             : 
    6138      150000 :     IF( position_changed )
    6139             :     {
    6140       64693 :         renderBufferChannelLerp_fx( ismInput->base.inputBuffer, 0, currentPanGains, ismInput->prev_pan_gains_fx, tmpMcBuffer );
    6141             :     }
    6142             :     ELSE
    6143             :     {
    6144       85307 :         renderBufferChannelLerp_fx( ismInput->base.inputBuffer, 0, ismInput->prev_pan_gains_fx, NULL, tmpMcBuffer );
    6145             :     }
    6146             : 
    6147      150000 :     copyBufferTo2dArray_fx( tmpMcBuffer, tmpRendBuffer );
    6148             : 
    6149             :     /* save gains for next frame */
    6150      600000 :     FOR( i = 0; i < 3; i++ )
    6151             :     {
    6152      450000 :         Copy32( Rmat[i], ismInput->rot_mat_prev[i], 3 );
    6153             :     }
    6154             : 
    6155      150000 :     IF( position_changed )
    6156             :     {
    6157       64693 :         Copy32( currentPanGains, ismInput->prev_pan_gains_fx, MAX_OUTPUT_CHANNELS );
    6158             :     }
    6159             : 
    6160             :     CREND_HANDLE hCrend;
    6161      150000 :     hCrend = ismInput->crendWrapper->hCrend[0];
    6162      150000 :     IF( hCrend->reflections != NULL )
    6163             :     {
    6164           0 :         test();
    6165           0 :         IF( EQ_32( hCrend->reflections->use_er, 1 ) && EQ_32( hCrend->reflections->is_ready, 1 ) )
    6166             :         {
    6167           0 :             FOR( i = 0; i < 150; i++ )
    6168             :             {
    6169           0 :                 hCrend->reflections->shoebox_data.gains.data_fx[i] = L_shl( hCrend->reflections->shoebox_data.gains.data_fx[i], Q9 );
    6170           0 :                 move32();
    6171             :             }
    6172             :         }
    6173             :     }
    6174             : 
    6175             : #ifdef FIX_1843_IO_QFACTOR_INIT
    6176      150000 :     *ismInput->crendWrapper->p_io_qfactor = *exp;
    6177             : #endif
    6178             :     /* render 7_1_4 with BRIRs */
    6179      150000 :     IF( NE_32( ( error = ivas_rend_crendProcessSubframe( ismInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, NULL, NULL, NULL, NULL, NULL, p_tmpRendBuffer, p_tmpRendBuffer, ismInput->base.inputBuffer.config.numSamplesPerChannel, *ismInput->base.ctx.pOutSampleRate, 0 ) ), IVAS_ERR_OK ) )
    6180             :     {
    6181           0 :         return error;
    6182             :     }
    6183             : 
    6184      150000 :     IF( hCrend->hReverb != NULL )
    6185             :     {
    6186           0 :         *exp = sub( *exp, 2 );
    6187           0 :         move16();
    6188             :     }
    6189      150000 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer, &outAudio );
    6190             : 
    6191      150000 :     free( tmpMcBuffer.data_fx );
    6192             : 
    6193      150000 :     pop_wmops();
    6194             : 
    6195      150000 :     return IVAS_ERR_OK;
    6196             : }
    6197             : 
    6198             : 
    6199      150000 : static ivas_error renderIsmToBinauralReverb(
    6200             :     input_ism *ismInput,
    6201             :     IVAS_REND_AudioBuffer outAudio )
    6202             : {
    6203             :     Word32 tmpRendBuffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    6204             :     ivas_error error;
    6205             :     Word16 ism_md_subframe_update_ext, i;
    6206      150000 :     Word16 exp = *outAudio.pq_fact;
    6207      150000 :     move16();
    6208             : 
    6209      150000 :     push_wmops( "renderIsmToBinauralRoom" );
    6210             : 
    6211             :     /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */
    6212      150000 :     ism_md_subframe_update_ext = extract_l( Mpy_32_32( ismInput->ism_metadata_delay_ms_fx, 429496730 /* 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES in Q31 */ ) );
    6213      150000 :     copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpRendBuffer_fx );
    6214             : 
    6215     2550000 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    6216             :     {
    6217     2400000 :         Scale_sig32( tmpRendBuffer_fx[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */
    6218             :     }
    6219             : 
    6220      150000 :     IF( NE_32( ( error = ivas_td_binaural_renderer_ext_fx( &ismInput->tdRendWrapper, ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, ismInput->hReverb, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, outAudio.config.numSamplesPerChannel, tmpRendBuffer_fx, &exp ) ), IVAS_ERR_OK ) )
    6221             :     {
    6222           0 :         return error;
    6223             :     }
    6224             : 
    6225     2550000 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    6226             :     {
    6227     2400000 :         Scale_sig32( tmpRendBuffer_fx[i], L_FRAME48k, negate( sub( 11, exp ) ) ); /* Q(exp) */
    6228             :     }
    6229             : 
    6230      150000 :     IF( ismInput->hReverb != NULL )
    6231             :     {
    6232      450000 :         FOR( i = 0; i < outAudio.config.numChannels; i++ )
    6233             :         {
    6234   115500000 :             FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel; j++ )
    6235             :             {
    6236   115200000 :                 tmpRendBuffer_fx[i][j] = L_shl( tmpRendBuffer_fx[i][j], 2 ); /* Q(exp + 2) */
    6237   115200000 :                 move16();
    6238             :             }
    6239             :         }
    6240             :     }
    6241      150000 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer_fx, &outAudio );
    6242      150000 :     pop_wmops();
    6243             : 
    6244      150000 :     return IVAS_ERR_OK;
    6245             : }
    6246             : 
    6247             : 
    6248      569500 : static ivas_error renderIsmToMc(
    6249             :     input_ism *ismInput,
    6250             :     const IVAS_REND_AudioBuffer outAudio )
    6251             : {
    6252             :     Word8 position_changed;
    6253             :     pan_vector_fx currentPanGains_fx; /* Q31 */
    6254             :     ivas_error error;
    6255             : 
    6256      569500 :     push_wmops( "renderIsmToMc" );
    6257             : 
    6258      569500 :     ismInput->currentPos.azimuth_fx = L_shl( L_shr( L_add( ismInput->currentPos.azimuth_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6259      569500 :     move32();
    6260      569500 :     ismInput->currentPos.elevation_fx = L_shl( L_shr( L_add( ismInput->currentPos.elevation_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6261      569500 :     move32();
    6262      569500 :     ismInput->previousPos.azimuth_fx = L_shl( L_shr( L_add( ismInput->previousPos.azimuth_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6263      569500 :     move32();
    6264      569500 :     ismInput->previousPos.elevation_fx = L_shl( L_shr( L_add( ismInput->previousPos.elevation_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6265      569500 :     move32();
    6266             : 
    6267      569500 :     test();
    6268      569500 :     position_changed = !ismInput->firstFrameRendered || checkObjectPositionChanged_fx( &ismInput->currentPos, &ismInput->previousPos );
    6269      569500 :     move16();
    6270      569500 :     IF( EQ_32( *ismInput->base.ctx.pOutConfig, IVAS_AUDIO_CONFIG_STEREO ) )
    6271             :     {
    6272       83500 :         IF( ismInput->nonDiegeticPan )
    6273             :         {
    6274        7500 :             currentPanGains_fx[0] = L_add( L_shr( ismInput->nonDiegeticPanGain_fx, 1 ), ONE_IN_Q30 ); /* Q31 */
    6275        7500 :             currentPanGains_fx[1] = L_sub( ONE_IN_Q31, currentPanGains_fx[0] );                       /* Q31 */
    6276        7500 :             ismInput->prev_pan_gains_fx[0] = currentPanGains_fx[0];                                   /* Q31 */
    6277        7500 :             ismInput->prev_pan_gains_fx[1] = currentPanGains_fx[1];                                   /* Q31 */
    6278        7500 :             move32();
    6279        7500 :             move32();
    6280        7500 :             move32();
    6281        7500 :             move32();
    6282             :         }
    6283             :         ELSE
    6284             :         {
    6285       76000 :             set32_fx( currentPanGains_fx, 0, MAX_OUTPUT_CHANNELS );
    6286             : 
    6287             :             Word16 gains_fx[2];
    6288             :             Word16 azimuth_tmp, elevation_tmp;
    6289             : 
    6290       76000 :             azimuth_tmp = extract_l( L_shr( ismInput->currentPos.azimuth_fx, Q22 ) );
    6291       76000 :             elevation_tmp = extract_l( L_shr( ismInput->currentPos.elevation_fx, Q22 ) );
    6292             : 
    6293       76000 :             ivas_ism_get_stereo_gains_fx( azimuth_tmp, elevation_tmp, &gains_fx[0], &gains_fx[1] );
    6294       76000 :             currentPanGains_fx[0] = L_deposit_h( gains_fx[0] ); /* Q31 */
    6295       76000 :             currentPanGains_fx[1] = L_deposit_h( gains_fx[1] ); /* Q31 */
    6296       76000 :             move32();
    6297       76000 :             move32();
    6298             : 
    6299       76000 :             azimuth_tmp = extract_l( L_shr( ismInput->previousPos.azimuth_fx, Q22 ) );
    6300       76000 :             elevation_tmp = extract_l( L_shr( ismInput->previousPos.elevation_fx, Q22 ) );
    6301             : 
    6302       76000 :             set32_fx( ismInput->prev_pan_gains_fx, 0, MAX_OUTPUT_CHANNELS );
    6303       76000 :             ivas_ism_get_stereo_gains_fx( azimuth_tmp, elevation_tmp, &gains_fx[0], &gains_fx[1] );
    6304       76000 :             ismInput->prev_pan_gains_fx[0] = L_deposit_h( gains_fx[0] ); /* Q31 */
    6305       76000 :             ismInput->prev_pan_gains_fx[1] = L_deposit_h( gains_fx[1] ); /* Q31 */
    6306       76000 :             move32();
    6307       76000 :             move32();
    6308             :         }
    6309             :     }
    6310             :     ELSE
    6311             :     {
    6312             :         /* compute gains only if position changed */
    6313      486000 :         IF( position_changed )
    6314             :         {
    6315             :             // TODO tmu review when #215 is resolved
    6316      207304 :             IF( NE_32( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper,
    6317             :                                                   ismInput->currentPos.azimuth_fx,
    6318             :                                                   ismInput->currentPos.elevation_fx,
    6319             :                                                   currentPanGains_fx ) ),
    6320             :                        IVAS_ERR_OK ) )
    6321             :             {
    6322           0 :                 return error;
    6323             :             }
    6324             :         }
    6325             : 
    6326             :         /* set previous gains if this is the first frame */
    6327      486000 :         IF( !ismInput->firstFrameRendered )
    6328             :         {
    6329             :             // TODO tmu review when #215 is resolved
    6330         188 :             IF( NE_32( ( error = getEfapGains_fx( *ismInput->base.ctx.pEfapOutWrapper,
    6331             :                                                   ismInput->previousPos.azimuth_fx,
    6332             :                                                   ismInput->previousPos.elevation_fx,
    6333             :                                                   ismInput->prev_pan_gains_fx ) ),
    6334             :                        IVAS_ERR_OK ) )
    6335             :             {
    6336           0 :                 return error;
    6337             :             }
    6338             :             /* fix2float to be removed */
    6339             :         }
    6340             :     }
    6341             : 
    6342             :     /* Assume num channels in audio buffer to be 1.
    6343             :      * This should have been validated in IVAS_REND_FeedInputAudio() */
    6344      569500 :     IF( position_changed )
    6345             :     {
    6346      244300 :         renderBufferChannelLerp_fx( ismInput->base.inputBuffer, 0, currentPanGains_fx, ismInput->prev_pan_gains_fx, outAudio );
    6347             :     }
    6348             :     ELSE
    6349             :     {
    6350      325200 :         renderBufferChannelLerp_fx( ismInput->base.inputBuffer, 0, ismInput->prev_pan_gains_fx, NULL, outAudio );
    6351             :     }
    6352             : 
    6353      569500 :     IF( position_changed )
    6354             :     {
    6355      244300 :         Copy32( currentPanGains_fx, ismInput->prev_pan_gains_fx, MAX_OUTPUT_CHANNELS );
    6356             :     }
    6357             : 
    6358      569500 :     pop_wmops();
    6359             : 
    6360             : 
    6361      569500 :     return IVAS_ERR_OK;
    6362             : }
    6363             : 
    6364             : 
    6365      228000 : static ivas_error renderIsmToSba(
    6366             :     input_ism *ismInput,
    6367             :     const AUDIO_CONFIG outConfig,
    6368             :     const IVAS_REND_AudioBuffer outAudio )
    6369             : {
    6370             :     Word16 i;
    6371             :     Word8 position_changed;
    6372             :     Word16 ambiOrderOut;
    6373             :     Word16 numOutChannels;
    6374             :     pan_vector_fx currentPanGains_fx;
    6375             :     ivas_error error;
    6376      228000 :     error = IVAS_ERR_OK;
    6377      228000 :     move32();
    6378             : 
    6379      228000 :     ismInput->currentPos.azimuth_fx = L_shl( L_shr( L_add( ismInput->currentPos.azimuth_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6380      228000 :     ismInput->currentPos.elevation_fx = L_shl( L_shr( L_add( ismInput->currentPos.elevation_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6381      228000 :     ismInput->previousPos.azimuth_fx = L_shl( L_shr( L_add( ismInput->previousPos.azimuth_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6382      228000 :     ismInput->previousPos.elevation_fx = L_shl( L_shr( L_add( ismInput->previousPos.elevation_fx, ONE_IN_Q21 ), Q22 ), Q22 );
    6383      228000 :     move32();
    6384      228000 :     move32();
    6385      228000 :     move32();
    6386      228000 :     move32();
    6387             : 
    6388      228000 :     push_wmops( "renderIsmToSba" );
    6389             : 
    6390      228000 :     IF( NE_32( ( error = getAudioConfigNumChannels( outConfig, &numOutChannels ) ), IVAS_ERR_OK ) )
    6391             :     {
    6392           0 :         return error;
    6393             :     }
    6394             : 
    6395      228000 :     IF( NE_32( ( error = getAmbisonicsOrder_fx( outConfig, &ambiOrderOut ) ), IVAS_ERR_OK ) )
    6396             :     {
    6397           0 :         return error;
    6398             :     }
    6399             : 
    6400      228000 :     test();
    6401      228000 :     position_changed = !ismInput->firstFrameRendered || checkObjectPositionChanged_fx( &ismInput->currentPos, &ismInput->previousPos );
    6402      228000 :     move16();
    6403             : 
    6404             :     /* set previous gains if this is the first frame */
    6405             :     Word16 azimuth_tmp, elevation_tmp;
    6406      228000 :     IF( !ismInput->firstFrameRendered )
    6407             :     {
    6408             :         // TODO tmu review when #215 is resolved
    6409          84 :         azimuth_tmp = extract_l( L_shr( ismInput->previousPos.azimuth_fx, Q22 ) );
    6410          84 :         elevation_tmp = extract_l( L_shr( ismInput->previousPos.elevation_fx, Q22 ) );
    6411          84 :         ivas_dirac_dec_get_response_fx( azimuth_tmp, elevation_tmp, ismInput->prev_pan_gains_fx, ambiOrderOut, Q29 );
    6412        1428 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    6413             :         {
    6414        1344 :             ismInput->prev_pan_gains_fx[i] = L_shl_sat( ismInput->prev_pan_gains_fx[i], Q2 ); /* Q29 + Q2 = Q31 */
    6415        1344 :             move32();
    6416             :         }
    6417             :     }
    6418             : 
    6419             :     /* compute gains only if position changed */
    6420      228000 :     IF( position_changed )
    6421             :     {
    6422             :         // TODO tmu review when #215 is resolved
    6423       88848 :         azimuth_tmp = extract_l( L_shr( ismInput->currentPos.azimuth_fx, Q22 ) );
    6424       88848 :         elevation_tmp = extract_l( L_shr( ismInput->currentPos.elevation_fx, Q22 ) );
    6425       88848 :         ivas_dirac_dec_get_response_fx( azimuth_tmp, elevation_tmp, currentPanGains_fx, ambiOrderOut, Q29 );
    6426     1510416 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    6427             :         {
    6428     1421568 :             currentPanGains_fx[i] = L_shl_sat( currentPanGains_fx[i], Q2 ); /* Q29 + Q2 = Q31 */
    6429     1421568 :             move32();
    6430             :         }
    6431             :     }
    6432             : 
    6433             :     /* Assume num channels in audio buffer to be 1.
    6434             :      * This should have been validated in IVAS_REND_FeedInputAudio() */
    6435      228000 :     IF( position_changed )
    6436             :     {
    6437       88848 :         renderBufferChannelLerp_fx( ismInput->base.inputBuffer, 0, currentPanGains_fx, ismInput->prev_pan_gains_fx, outAudio );
    6438             :     }
    6439             :     ELSE
    6440             :     {
    6441      139152 :         renderBufferChannelLerp_fx( ismInput->base.inputBuffer, 0, ismInput->prev_pan_gains_fx, NULL, outAudio );
    6442             :     }
    6443             : 
    6444      228000 :     IF( position_changed )
    6445             :     {
    6446       88848 :         Copy32( currentPanGains_fx, ismInput->prev_pan_gains_fx, MAX_OUTPUT_CHANNELS );
    6447             :     }
    6448      228000 :     pop_wmops();
    6449             : 
    6450      228000 :     return error;
    6451             : }
    6452             : 
    6453             : 
    6454           0 : static ivas_error renderIsmToSplitBinaural(
    6455             :     input_ism *ismInput,
    6456             :     const IVAS_REND_AudioBuffer outAudio )
    6457             : {
    6458             :     ivas_error error;
    6459             :     Word32 tmpProcessing[MAX_NUM_OBJECTS][L_FRAME48k];
    6460             :     Word16 pos_idx;
    6461             :     const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
    6462             :     const SPLIT_REND_WRAPPER *pSplitRendWrapper;
    6463             :     IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES];
    6464             :     IVAS_QUATERNION localHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES];
    6465             :     Word16 i;
    6466             :     Word32 tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k];
    6467           0 :     Word16 output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel;
    6468             :     COMBINED_ORIENTATION_HANDLE pCombinedOrientationData;
    6469             :     Word16 ism_md_subframe_update_ext, exp;
    6470             : 
    6471           0 :     push_wmops( "renderIsmToSplitBinaural" );
    6472             : 
    6473           0 :     pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper;
    6474           0 :     pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData;
    6475             : 
    6476           0 :     exp = *outAudio.pq_fact;
    6477             :     /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */
    6478           0 :     ism_md_subframe_update_ext = (Word16) Mpy_32_32( ismInput->ism_metadata_delay_ms_fx, ONE_BY_SUBFRAME_LEN_MS_Q31 );
    6479             : 
    6480           0 :     pCombinedOrientationData = *ismInput->base.ctx.pCombinedOrientationData;
    6481             : 
    6482           0 :     IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) )
    6483             :     {
    6484           0 :         FOR( i = 1; i < pCombinedOrientationData->num_subframes; ++i )
    6485             :         {
    6486           0 :             Copy_Quat_fx( &pCombinedOrientationData->Quaternions[0], &pCombinedOrientationData->Quaternions[i] );
    6487             :         }
    6488             :     }
    6489             : 
    6490             :     /* Save current head positions */
    6491           0 :     FOR( i = 0; i < pCombinedOrientationData->num_subframes; ++i )
    6492             :     {
    6493           0 :         Copy_Quat_fx( &pCombinedOrientationData->Quaternions[i], &originalHeadRot[i] );
    6494             :     }
    6495             : 
    6496             :     /* Copy input audio to a processing buffer. */
    6497           0 :     copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing );
    6498             : 
    6499             : 
    6500           0 :     FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
    6501             :     {
    6502             :         /* Update head positions */
    6503           0 :         IF( NE_16( pos_idx, 0 ) )
    6504             :         {
    6505             :             Word16 q_fact_orig;
    6506           0 :             FOR( i = 0; i < pCombinedOrientationData->num_subframes; ++i )
    6507             :             {
    6508           0 :                 pCombinedOrientationData->Quaternions[i].w_fx = L_negate( 12582912 ); // Q22
    6509           0 :                 q_fact_orig = originalHeadRot[i].q_fact;
    6510           0 :                 modify_Quat_q_fx( &originalHeadRot[i], &localHeadRot[i], Q22 );
    6511             :                 /*euler*/
    6512           0 :                 Quat2EulerDegree_fx( localHeadRot[i], &pCombinedOrientationData->Quaternions[i].z_fx, &pCombinedOrientationData->Quaternions[i].y_fx, &pCombinedOrientationData->Quaternions[i].x_fx );
    6513           0 :                 pCombinedOrientationData->Quaternions[i].x_fx = L_add( pCombinedOrientationData->Quaternions[i].x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
    6514           0 :                 pCombinedOrientationData->Quaternions[i].y_fx = L_add( pCombinedOrientationData->Quaternions[i].y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
    6515           0 :                 pCombinedOrientationData->Quaternions[i].z_fx = L_add( pCombinedOrientationData->Quaternions[i].z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
    6516             : 
    6517           0 :                 Euler2Quat_fx( deg2rad_fx( pCombinedOrientationData->Quaternions[i].x_fx ), deg2rad_fx( pCombinedOrientationData->Quaternions[i].y_fx ), deg2rad_fx( pCombinedOrientationData->Quaternions[i].z_fx ), &pCombinedOrientationData->Quaternions[i] );
    6518             : 
    6519           0 :                 modify_Quat_q_fx( &pCombinedOrientationData->Quaternions[i], &pCombinedOrientationData->Quaternions[i], q_fact_orig );
    6520             :             }
    6521             :         }
    6522             : 
    6523             : 
    6524           0 :         FOR( i = 0; i < MAX_NUM_OBJECTS; ++i )
    6525             :         {
    6526           0 :             Scale_sig32( tmpProcessing[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */
    6527             :         }
    6528             : 
    6529             :         /* Render */
    6530           0 :         IF( ( error = ivas_td_binaural_renderer_ext_fx( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[sub( pos_idx, 1 )], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos,
    6531             :                                                         NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing, &exp ) ) != IVAS_ERR_OK )
    6532             :         {
    6533           0 :             return error;
    6534             :         }
    6535             : 
    6536           0 :         FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
    6537             :         {
    6538           0 :             Scale_sig32( tmpProcessing[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */
    6539             :         }
    6540             : 
    6541           0 :         IF( ismInput->hReverb != NULL )
    6542             :         {
    6543           0 :             FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
    6544             :             {
    6545           0 :                 FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel; j++ )
    6546             :                 {
    6547           0 :                     tmpProcessing[i][j] = L_shl( tmpProcessing[i][j], Q2 ); /* Q(exp + 2) */
    6548           0 :                     move32();
    6549             :                 }
    6550             :             }
    6551             :         }
    6552             :         /* Copy rendered audio to tmp storage buffer. Copying directly to output would
    6553             :          * overwrite original audio, which is still needed for rendering next head pose. */
    6554           0 :         Copy32( tmpProcessing[0], tmpBinaural[i_mult( 2, pos_idx )], output_frame );
    6555           0 :         Copy32( tmpProcessing[1], tmpBinaural[add( i_mult( 2, pos_idx ), 1 )], output_frame );
    6556             : 
    6557             :         /* Overwrite processing buffer with original input audio again */
    6558           0 :         copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpProcessing );
    6559             :     }
    6560             : 
    6561             :     /* Restore original head rotation */
    6562           0 :     FOR( i = 0; i < pCombinedOrientationData->num_subframes; ++i )
    6563             :     {
    6564           0 :         Copy_Quat_fx( &originalHeadRot[i], &pCombinedOrientationData->Quaternions[i] );
    6565             :     }
    6566             : 
    6567           0 :     accumulate2dArrayToBuffer_fx( tmpBinaural, &outAudio );
    6568           0 :     pop_wmops();
    6569             : 
    6570             :     /* Encoding to split rendering bitstream done at a higher level */
    6571           0 :     return IVAS_ERR_OK;
    6572             : }
    6573             : 
    6574             : 
    6575         150 : static void renderIsmToMasa(
    6576             :     input_ism *ismInput,
    6577             :     IVAS_REND_AudioBuffer outAudio,
    6578             :     Word16 *exp )
    6579             : {
    6580             :     Word32 tmpRendBuffer_fx[MAX_NUM_OBJECTS][L_FRAME48k];
    6581             :     Word16 i, guard_bits, q_min, q_diff;
    6582             : 
    6583         150 :     push_wmops( "renderIsmToMasa" );
    6584             : 
    6585         150 :     copyBufferTo2dArray_fx( ismInput->base.inputBuffer, tmpRendBuffer_fx );
    6586             : 
    6587         150 :     q_min = MAX_16;
    6588         150 :     move16();
    6589             : 
    6590         750 :     FOR( i = 0; i < ismInput->base.inputBuffer.config.numChannels; i++ )
    6591             :     {
    6592         600 :         q_min = s_min( q_min, L_norm_arr( tmpRendBuffer_fx[i], ismInput->base.inputBuffer.config.numSamplesPerChannel ) );
    6593             :     }
    6594             : 
    6595         150 :     guard_bits = find_guarded_bits_fx( ismInput->base.inputBuffer.config.numSamplesPerChannel );
    6596         150 :     q_min = sub( add( q_min, *outAudio.pq_fact ), guard_bits );
    6597         150 :     q_diff = sub( q_min, *outAudio.pq_fact );
    6598             : 
    6599         750 :     FOR( i = 0; i < ismInput->base.inputBuffer.config.numChannels; i++ )
    6600             :     {
    6601         600 :         scale_sig32( tmpRendBuffer_fx[i], ismInput->base.inputBuffer.config.numSamplesPerChannel, q_diff ); // *outAudio.pq_fact -> q_min
    6602             :     }
    6603             : 
    6604         150 :     ivas_omasa_ana_fx( ismInput->hOMasa, tmpRendBuffer_fx, &q_min, ismInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels, ismInput->base.inputBuffer.config.numChannels );
    6605             : 
    6606         150 :     *exp = q_min;
    6607         150 :     move16();
    6608             : 
    6609         150 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer_fx, &outAudio );
    6610             : 
    6611         150 :     pop_wmops();
    6612             : 
    6613         150 :     return;
    6614             : }
    6615             : 
    6616     1247650 : static ivas_error renderInputIsm(
    6617             :     input_ism *ismInput,
    6618             :     const AUDIO_CONFIG outConfig,
    6619             :     const IVAS_REND_AudioBuffer outAudio )
    6620             : {
    6621             :     ivas_error error;
    6622             :     IVAS_REND_AudioBuffer inAudio;
    6623     1247650 :     Word16 exp = *outAudio.pq_fact;
    6624     1247650 :     move16();
    6625             : 
    6626     1247650 :     error = IVAS_ERR_OK;
    6627     1247650 :     move32();
    6628     1247650 :     inAudio = ismInput->base.inputBuffer;
    6629             : 
    6630     1247650 :     IF( NE_32( ismInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) )
    6631             :     {
    6632           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" );
    6633             :     }
    6634     1247650 :     ismInput->base.numNewSamplesPerChannel = 0;
    6635     1247650 :     move32();
    6636             : 
    6637             :     /* Apply input gain to new audio */
    6638     1247650 :     v_multc_fixed( inAudio.data_fx, ismInput->base.gain_fx, inAudio.data_fx, imult1616( inAudio.config.numSamplesPerChannel, inAudio.config.numChannels ) );
    6639     1247650 :     *outAudio.pq_fact = sub( *outAudio.pq_fact, Q1 );
    6640     1247650 :     move16();
    6641     1247650 :     exp = *outAudio.pq_fact;
    6642     1247650 :     move16();
    6643             : 
    6644             :     /* set combined orientation subframe info to start info */
    6645     1247650 :     ivas_combined_orientation_set_to_start_index( *ismInput->base.ctx.pCombinedOrientationData );
    6646             : 
    6647             : 
    6648     1247650 :     SWITCH( getAudioConfigType( outConfig ) )
    6649             :     {
    6650      569500 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    6651      569500 :             error = renderIsmToMc( ismInput, outAudio );
    6652      569500 :             BREAK;
    6653      228000 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    6654      228000 :             error = renderIsmToSba( ismInput, outConfig, outAudio );
    6655      228000 :             BREAK;
    6656      450000 :         case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL:
    6657             :             SWITCH( outConfig )
    6658             :             {
    6659      150000 :                 case IVAS_AUDIO_CONFIG_BINAURAL:
    6660      150000 :                     error = renderIsmToBinaural( ismInput, outAudio );
    6661      150000 :                     BREAK;
    6662      150000 :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
    6663      150000 :                     error = renderIsmToBinauralRoom( ismInput, outAudio, &exp );
    6664      150000 :                     BREAK;
    6665           0 :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
    6666             :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
    6667           0 :                     error = renderIsmToSplitBinaural( ismInput, outAudio );
    6668           0 :                     break;
    6669      150000 :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    6670      150000 :                     error = renderIsmToBinauralReverb( ismInput, outAudio );
    6671      150000 :                     BREAK;
    6672           0 :                 default:
    6673           0 :                     return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    6674             :             }
    6675      450000 :             BREAK;
    6676         150 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    6677         150 :             renderIsmToMasa( ismInput, outAudio, &exp );
    6678         150 :             BREAK;
    6679           0 :         default:
    6680           0 :             return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    6681             :     }
    6682             : 
    6683             :     /* Check error here to keep switch statement more compact */
    6684     1247650 :     IF( NE_32( error, IVAS_ERR_OK ) )
    6685             :     {
    6686           0 :         return error;
    6687             :     }
    6688             : 
    6689     1247650 :     ismInput->firstFrameRendered = TRUE;
    6690     1247650 :     move16();
    6691             : 
    6692     1247650 :     *outAudio.pq_fact = exp;
    6693     1247650 :     move16();
    6694             : 
    6695     1247650 :     return error;
    6696             : }
    6697             : 
    6698     1126140 : static ivas_error renderActiveInputsIsm(
    6699             :     IVAS_REND_HANDLE hIvasRend,
    6700             :     IVAS_REND_AudioBuffer outAudio )
    6701             : {
    6702             :     Word16 i;
    6703             :     input_ism *pCurrentInput;
    6704             :     ivas_error error;
    6705     1126140 :     Word16 input_q = outAudio.q_factor;
    6706     1126140 :     move16();
    6707     5630700 :     FOR( ( i = 0, pCurrentInput = hIvasRend->inputsIsm ); i < RENDERER_MAX_ISM_INPUTS; ( ++i, ++pCurrentInput ) )
    6708             :     {
    6709     4504560 :         IF( EQ_32( pCurrentInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    6710             :         {
    6711             :             /* Skip inactive inputs */
    6712     3256910 :             CONTINUE;
    6713             :         }
    6714             : 
    6715     1247650 :         *outAudio.pq_fact = input_q;
    6716     1247650 :         move16();
    6717     1247650 :         IF( NE_32( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ), IVAS_ERR_OK ) )
    6718             :         {
    6719           0 :             return error;
    6720             :         }
    6721  2925119650 :         FOR( Word16 j = 0; j < outAudio.config.numSamplesPerChannel * outAudio.config.numChannels; ++j )
    6722             :         {
    6723  2923872000 :             outAudio.data_fx[j] = L_shl( outAudio.data_fx[j], sub( sub( input_q, 1 ), ( *outAudio.pq_fact ) ) ); /* Q(input_q - 1) */
    6724  2923872000 :             move32();
    6725             :         }
    6726     1247650 :         *outAudio.pq_fact = sub( input_q, 1 );
    6727     1247650 :         move16();
    6728             :     }
    6729     1126140 :     return IVAS_ERR_OK;
    6730             : }
    6731             : 
    6732       87012 : static ivas_error renderLfeToBinaural_fx(
    6733             :     const input_mc *mcInput,
    6734             :     const AUDIO_CONFIG outConfig,
    6735             :     IVAS_REND_AudioBuffer outAudio,
    6736             :     Word16 in_q,
    6737             :     Word16 out_q )
    6738             : {
    6739             :     Word16 lfe_idx;
    6740             :     Word16 pose_idx, num_poses;
    6741             :     Word32 gain_fx;
    6742             :     Word16 ear_idx, i, r_shift;
    6743             :     Word32 tmpLfeBuffer[MAX_BUFFER_LENGTH_PER_CHANNEL];
    6744             :     Word16 frame_size, num_cpy_smpl_cur_frame, num_cpy_smpl_prev_frame;
    6745             :     const Word32 *lfeInput;
    6746             :     Word32 *writePtr;
    6747             : 
    6748       87012 :     assert( ( getAudioConfigType( outConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) && "Must be binaural output" );
    6749             : 
    6750       87012 :     push_wmops( "renderLfeToBinaural" );
    6751       87012 :     gain_fx = GAIN_LFE_WORD32; /* 1.88364911f in Q30 */
    6752       87012 :     move32();
    6753             : 
    6754       87012 :     IF( NE_32( mcInput->base.inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    6755             :     {
    6756       48000 :         lfe_idx = LFE_CHANNEL;
    6757       48000 :         move16();
    6758             :     }
    6759       39012 :     ELSE IF( mcInput->customLsInput.num_lfe > 0 )
    6760             :     {
    6761           0 :         lfe_idx = mcInput->customLsInput.lfe_idx[0];
    6762           0 :         move16();
    6763             :     }
    6764             :     ELSE
    6765             :     {
    6766             :         /* no LFE to render */
    6767       39012 :         pop_wmops();
    6768       39012 :         return IVAS_ERR_OK;
    6769             :     }
    6770             : 
    6771             :     /* --- Prepare LFE signal to be added to binaural output --- */
    6772       48000 :     lfeInput = getSmplPtr_fx( mcInput->base.inputBuffer, lfe_idx, 0 );
    6773       48000 :     frame_size = mcInput->base.inputBuffer.config.numSamplesPerChannel;
    6774       48000 :     move16();
    6775       48000 :     num_cpy_smpl_prev_frame = mcInput->binauralDelaySmp;
    6776       48000 :     move16();
    6777       48000 :     num_cpy_smpl_cur_frame = sub( frame_size, num_cpy_smpl_prev_frame );
    6778             : 
    6779             :     /* Assuming LFE should be delayed by less that the duration of one frame */
    6780       48000 :     assert( mcInput->binauralDelaySmp < frame_size );
    6781             : 
    6782             :     /* Get delayed LFE signal from previous frame, apply gain and save in tmp buffer */
    6783       48000 :     v_multc_fixed( mcInput->lfeDelayBuffer_fx, gain_fx, tmpLfeBuffer, num_cpy_smpl_prev_frame ); /* Qx - 1 */
    6784             : 
    6785             :     /* Continue filling tmp buffer, now with LFE signal from current frame */
    6786       48000 :     v_multc_fixed( lfeInput, gain_fx, tmpLfeBuffer + num_cpy_smpl_prev_frame, num_cpy_smpl_cur_frame ); /* Qx - 1 */
    6787             : 
    6788             :     /* Save remaining LFE samples of current frame for next frame */
    6789       48000 :     MVR2R_WORD32( lfeInput + num_cpy_smpl_cur_frame, mcInput->lfeDelayBuffer_fx, num_cpy_smpl_prev_frame );
    6790       48000 :     r_shift = sub( sub( in_q, 1 ), out_q );
    6791             : 
    6792       48000 :     IF( r_shift != 0 )
    6793             :     {
    6794    14533750 :         FOR( i = 0; i < add( num_cpy_smpl_prev_frame, num_cpy_smpl_cur_frame ); i++ )
    6795             :         {
    6796    14496000 :             tmpLfeBuffer[i] = L_shr( tmpLfeBuffer[i], r_shift ); /* Q(out_q) */
    6797    14496000 :             move32();
    6798             :         }
    6799             :     }
    6800             : 
    6801             :     /* Copy LFE to left and right binaural channels for all poses */
    6802       48000 :     IF( mcInput->base.ctx.pSplitRendWrapper != NULL )
    6803             :     {
    6804           0 :         num_poses = mcInput->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    6805           0 :         move16();
    6806             :     }
    6807             :     ELSE
    6808             :     {
    6809       48000 :         num_poses = 1;
    6810       48000 :         move16();
    6811             :     }
    6812             : 
    6813       96000 :     FOR( pose_idx = 0; pose_idx < num_poses; ++pose_idx )
    6814             :     {
    6815      144000 :         FOR( ear_idx = 0; ear_idx < BINAURAL_CHANNELS; ++ear_idx )
    6816             :         {
    6817       96000 :             writePtr = getSmplPtr_fx( outAudio, add( i_mult( pose_idx, BINAURAL_CHANNELS ), ear_idx ), 0 );
    6818       96000 :             move32();
    6819       96000 :             v_add_fixed_no_hdrm( writePtr, tmpLfeBuffer, writePtr, frame_size ); /* Q(out_q) */
    6820             :         }
    6821             :     }
    6822             : 
    6823       48000 :     pop_wmops();
    6824             : 
    6825       48000 :     return IVAS_ERR_OK;
    6826             : }
    6827             : 
    6828       29004 : static ivas_error renderMcToBinaural(
    6829             :     input_mc *mcInput,
    6830             :     const AUDIO_CONFIG outConfig,
    6831             :     IVAS_REND_AudioBuffer outAudio )
    6832             : {
    6833             :     Word32 tmpRendBuffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    6834             :     AUDIO_CONFIG inConfig;
    6835             :     ivas_error error;
    6836             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    6837             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
    6838             :     Word8 combinedOrientationEnabled;
    6839             :     Word16 subframe_idx;
    6840             :     Word32 *p_tmpRendBuffer_fx[MAX_OUTPUT_CHANNELS];
    6841             :     Word16 i;
    6842       29004 :     Word16 exp = *outAudio.pq_fact;
    6843       29004 :     move16();
    6844             : 
    6845      493068 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    6846             :     {
    6847      464064 :         p_tmpRendBuffer_fx[i] = tmpRendBuffer_fx[i];
    6848             :     }
    6849       29004 :     push_wmops( "renderMcToBinaural" );
    6850             : 
    6851       29004 :     inConfig = mcInput->base.inConfig;
    6852       29004 :     move32();
    6853       29004 :     hCombinedOrientationData = mcInput->base.ctx.pCombinedOrientationData;
    6854       29004 :     combinedOrientationEnabled = 0;
    6855       29004 :     move16();
    6856             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    6857       29004 :     IF( *hCombinedOrientationData != NULL )
    6858             : #else
    6859             :     IF( hCombinedOrientationData != NULL )
    6860             : #endif
    6861             :     {
    6862       14502 :         FOR( subframe_idx = 0; subframe_idx < ( *hCombinedOrientationData )->num_subframes; subframe_idx++ )
    6863             :         {
    6864       14502 :             IF( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
    6865             :             {
    6866       14502 :                 combinedOrientationEnabled = 1;
    6867       14502 :                 move16();
    6868       14502 :                 BREAK;
    6869             :             }
    6870             :         }
    6871             :     }
    6872             : 
    6873       29004 :     test();
    6874       29004 :     test();
    6875       29004 :     test();
    6876       29004 :     IF( ( EQ_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) ) || ( combinedOrientationEnabled && ( EQ_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) ) )
    6877             :     {
    6878       18754 :         copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer_fx );
    6879             : 
    6880      318818 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    6881             :         {
    6882      300064 :             Scale_sig32( tmpRendBuffer_fx[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */
    6883             :         }
    6884       18754 :         IF( NE_32( ( error = ivas_td_binaural_renderer_ext_fx( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pCombinedOrientationData, NULL, mcInput->hReverb,
    6885             :                                                                0, *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer_fx, &exp ) ),
    6886             :                    IVAS_ERR_OK ) )
    6887             :         {
    6888           0 :             return error;
    6889             :         }
    6890             : 
    6891      318818 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    6892             :         {
    6893      300064 :             Scale_sig32( tmpRendBuffer_fx[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */
    6894             :         }
    6895             :     }
    6896             :     ELSE
    6897             :     {
    6898             :         /* apply rotation */
    6899       10250 :         IF( combinedOrientationEnabled )
    6900             :         {
    6901        2250 :             tmpRotBuffer = mcInput->base.inputBuffer;
    6902        2250 :             tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) );
    6903        2250 :             set32_fx( tmpRotBuffer.data_fx, 0, imult1616( tmpRotBuffer.config.numSamplesPerChannel, tmpRotBuffer.config.numChannels ) );
    6904             : 
    6905        2250 :             IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx[0], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ), IVAS_ERR_OK ) )
    6906             :             {
    6907           0 :                 return error;
    6908             :             }
    6909             : 
    6910        2250 :             exp = sub( *outAudio.pq_fact, 1 );
    6911             : 
    6912        2250 :             copyBufferTo2dArray_fx( tmpRotBuffer, tmpRendBuffer_fx );
    6913             : 
    6914        2250 :             free( tmpRotBuffer.data_fx );
    6915             :         }
    6916             :         ELSE
    6917             :         {
    6918        8000 :             copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer_fx );
    6919             :         }
    6920             :         // Porting Crend_process function
    6921             :         CREND_HANDLE hCrend;
    6922       10250 :         hCrend = mcInput->crendWrapper->hCrend[0];
    6923             : 
    6924             : #ifdef FIX_1843_IO_QFACTOR_INIT
    6925       10250 :         *mcInput->crendWrapper->p_io_qfactor = exp;
    6926             : #endif
    6927             :         /* call CREND */
    6928       10250 :         IF( NE_32( ( error = ivas_rend_crendProcessSubframe( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, NULL, p_tmpRendBuffer_fx, p_tmpRendBuffer_fx, mcInput->base.inputBuffer.config.numSamplesPerChannel, *mcInput->base.ctx.pOutSampleRate, 0 ) ), IVAS_ERR_OK ) )
    6929             :         {
    6930           0 :             return error;
    6931             :         }
    6932             : 
    6933       10250 :         IF( hCrend->hReverb != NULL )
    6934             :         {
    6935           0 :             exp = sub( exp, 2 );
    6936             :         }
    6937             :     }
    6938             : 
    6939       29004 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer_fx, &outAudio );
    6940             : 
    6941       29004 :     IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) )
    6942             : 
    6943             :     {
    6944           0 :         return error;
    6945             :     }
    6946       29004 :     *outAudio.pq_fact = exp;
    6947       29004 :     move16();
    6948             : 
    6949       29004 :     pop_wmops();
    6950       29004 :     return IVAS_ERR_OK;
    6951             : }
    6952             : 
    6953       32000 : static ivas_error renderMcToBinauralRoom(
    6954             :     input_mc *mcInput,
    6955             :     const AUDIO_CONFIG outConfig,
    6956             :     IVAS_REND_AudioBuffer outAudio )
    6957             : {
    6958             :     Word32 tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    6959             :     AUDIO_CONFIG inConfig;
    6960             :     ivas_error error;
    6961             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    6962             :     Word32 *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS];
    6963             :     Word16 i;
    6964             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
    6965             :     Word8 combinedOrientationEnabled;
    6966             :     Word16 subframe_idx;
    6967       32000 :     Word16 exp = *outAudio.pq_fact;
    6968       32000 :     move16();
    6969             : 
    6970      544000 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    6971             :     {
    6972      512000 :         p_tmpRendBuffer[i] = tmpRendBuffer[i];
    6973             :     }
    6974             : 
    6975       32000 :     push_wmops( "renderMcToBinauralRoom" );
    6976       32000 :     inConfig = mcInput->base.inConfig;
    6977       32000 :     move32();
    6978       32000 :     hCombinedOrientationData = mcInput->base.ctx.pCombinedOrientationData;
    6979       32000 :     combinedOrientationEnabled = 0;
    6980       32000 :     move16();
    6981             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    6982       32000 :     IF( *hCombinedOrientationData != NULL )
    6983             : #else
    6984             :     IF( hCombinedOrientationData != NULL )
    6985             : #endif
    6986             :     {
    6987       16000 :         FOR( subframe_idx = 0; subframe_idx < ( *hCombinedOrientationData )->num_subframes; subframe_idx++ )
    6988             :         {
    6989       16000 :             IF( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
    6990             :             {
    6991       16000 :                 combinedOrientationEnabled = 1;
    6992       16000 :                 move16();
    6993       16000 :                 BREAK;
    6994             :             }
    6995             :         }
    6996             :     }
    6997             : 
    6998       32000 :     test();
    6999       32000 :     test();
    7000       32000 :     test();
    7001       32000 :     test();
    7002       32000 :     test();
    7003       32000 :     IF( ( mcInput->hReverb != NULL && EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) && ( EQ_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) || ( combinedOrientationEnabled && ( EQ_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) ) ) ) )
    7004             :     {
    7005        5750 :         copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer );
    7006             : 
    7007       97750 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    7008             :         {
    7009       92000 :             Scale_sig32( tmpRendBuffer[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */
    7010             :         }
    7011             : 
    7012        5750 :         IF( NE_32( ( error = ivas_td_binaural_renderer_ext_fx( &mcInput->tdRendWrapper, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pCombinedOrientationData, NULL, mcInput->hReverb,
    7013             :                                                                0, *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer, &exp ) ),
    7014             :                    IVAS_ERR_OK ) )
    7015             :         {
    7016           0 :             return error;
    7017             :         }
    7018             : 
    7019       97750 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    7020             :         {
    7021       92000 :             Scale_sig32( tmpRendBuffer[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */
    7022             :         }
    7023             :     }
    7024             :     ELSE
    7025             :     {
    7026             :         /* apply rotation */
    7027       26250 :         IF( combinedOrientationEnabled )
    7028             :         {
    7029       10250 :             tmpRotBuffer = mcInput->base.inputBuffer;
    7030       10250 :             tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) );
    7031       10250 :             set32_fx( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels );
    7032             : 
    7033       10250 :             IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx[0], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ),
    7034             :                        IVAS_ERR_OK ) )
    7035             :             {
    7036           0 :                 return error;
    7037             :             }
    7038             : 
    7039       10250 :             exp = sub( *outAudio.pq_fact, 1 );
    7040             : 
    7041       10250 :             copyBufferTo2dArray_fx( tmpRotBuffer, tmpRendBuffer );
    7042       10250 :             free( tmpRotBuffer.data_fx );
    7043             :         }
    7044             :         ELSE
    7045             :         {
    7046       16000 :             copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer );
    7047             :         }
    7048             :         // Porting Crend_process function
    7049             :         CREND_HANDLE hCrend;
    7050       26250 :         hCrend = mcInput->crendWrapper->hCrend[0];
    7051             : 
    7052             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7053       26250 :         *mcInput->crendWrapper->p_io_qfactor = exp;
    7054             : #endif
    7055             :         /* call CREND */
    7056       26250 :         IF( NE_32( ( error = ivas_rend_crendProcessSubframe( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, NULL, p_tmpRendBuffer, p_tmpRendBuffer, mcInput->base.inputBuffer.config.numSamplesPerChannel, *mcInput->base.ctx.pOutSampleRate, 0 ) ), IVAS_ERR_OK ) )
    7057             :         {
    7058           0 :             return error;
    7059             :         }
    7060             : 
    7061       26250 :         IF( hCrend->hReverb != NULL )
    7062             :         {
    7063       10250 :             exp = sub( exp, Q2 );
    7064             :         }
    7065             :     }
    7066             : 
    7067       32000 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer, &outAudio );
    7068             : 
    7069       32000 :     IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) )
    7070             :     {
    7071           0 :         return error;
    7072             :     }
    7073       32000 :     *outAudio.pq_fact = exp;
    7074       32000 :     move16();
    7075             : 
    7076       32000 :     pop_wmops();
    7077       32000 :     return IVAS_ERR_OK;
    7078             : }
    7079             : 
    7080       26008 : static ivas_error renderMcCustomLsToBinauralRoom(
    7081             :     input_mc *mcInput,
    7082             :     const AUDIO_CONFIG outConfig,
    7083             :     IVAS_REND_AudioBuffer outAudio )
    7084             : {
    7085             :     Word16 i;
    7086             :     Word16 tmp;
    7087             :     Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7088             :     ivas_error error;
    7089             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    7090             :     IVAS_REND_AudioBuffer tmpMcBuffer;
    7091             :     IVAS_REND_AudioBuffer *tmpBufPtr;
    7092             :     Word32 *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS];
    7093             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
    7094             :     Word8 combinedOrientationEnabled;
    7095             :     Word16 subframe_idx;
    7096       26008 :     Word16 exp = *outAudio.pq_fact;
    7097       26008 :     move16();
    7098       26008 :     push_wmops( "renderMcCustomLsToBinauralRoom" );
    7099       26008 :     tmpRotBuffer = outAudio; /* avoid compilation warning */
    7100             : 
    7101      442136 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    7102             :     {
    7103      416128 :         p_tmpCrendBuffer[i] = tmpCrendBuffer[i];
    7104             :     }
    7105             : 
    7106       26008 :     hCombinedOrientationData = mcInput->base.ctx.pCombinedOrientationData;
    7107       26008 :     combinedOrientationEnabled = 0;
    7108       26008 :     move16();
    7109             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    7110       26008 :     IF( *hCombinedOrientationData != NULL )
    7111             : #else
    7112             :     IF( hCombinedOrientationData != NULL )
    7113             : #endif
    7114             :     {
    7115       13004 :         FOR( subframe_idx = 0; subframe_idx < ( *hCombinedOrientationData )->num_subframes; subframe_idx++ )
    7116             :         {
    7117       13004 :             IF( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
    7118             :             {
    7119       13004 :                 combinedOrientationEnabled = 1;
    7120       13004 :                 move16();
    7121       13004 :                 BREAK;
    7122             :             }
    7123             :         }
    7124             :     }
    7125             : 
    7126             :     /* apply rotation */
    7127       26008 :     IF( combinedOrientationEnabled )
    7128             :     {
    7129       13004 :         tmpRotBuffer = mcInput->base.inputBuffer;
    7130       13004 :         tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) );
    7131       13004 :         set32_fx( tmpRotBuffer.data_fx, 0, tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels );
    7132             : 
    7133       13004 :         IF( NE_32( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, mcInput->base.ctx.pCombinedOrientationData, mcInput->rot_gains_prev_fx[0], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ),
    7134             :                    IVAS_ERR_OK ) )
    7135             :         {
    7136           0 :             return error;
    7137             :         }
    7138       13004 :         exp = sub( *outAudio.pq_fact, Q1 );
    7139             :     }
    7140             : 
    7141             :     /* intermediate conversion to 7_1_4 */
    7142       26008 :     tmpMcBuffer = mcInput->base.inputBuffer;
    7143             : 
    7144       26008 :     IF( NE_32( ( error = getAudioConfigNumChannels( IVAS_AUDIO_CONFIG_7_1_4, &tmp ) ), IVAS_ERR_OK ) )
    7145             :     {
    7146           0 :         return error;
    7147             :     }
    7148             : 
    7149       26008 :     tmpMcBuffer.config.numChannels = tmp;
    7150       26008 :     move16();
    7151       26008 :     tmpMcBuffer.data_fx = malloc( imult1616( tmpMcBuffer.config.numSamplesPerChannel, tmpMcBuffer.config.numChannels ) * sizeof( Word32 ) );
    7152       26008 :     set32_fx( tmpMcBuffer.data_fx, 0, imult1616( tmpMcBuffer.config.numSamplesPerChannel, tmpMcBuffer.config.numChannels ) );
    7153             : 
    7154       26008 :     IF( combinedOrientationEnabled )
    7155             :     {
    7156       13004 :         tmpBufPtr = &tmpRotBuffer;
    7157             :     }
    7158             :     ELSE
    7159             :     {
    7160       13004 :         tmpBufPtr = &mcInput->base.inputBuffer;
    7161             :     }
    7162      406136 :     FOR( i = 0; i < mcInput->base.inputBuffer.config.numChannels; i++ )
    7163             :     {
    7164      380128 :         renderBufferChannel_fx( *tmpBufPtr, i, mcInput->panGains_fx[i], tmpMcBuffer );
    7165             :     }
    7166       26008 :     copyBufferTo2dArray_fx( tmpMcBuffer, tmpCrendBuffer );
    7167             : 
    7168             :     CREND_HANDLE hCrend;
    7169       26008 :     hCrend = mcInput->crendWrapper->hCrend[0];
    7170             : 
    7171             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7172       26008 :     *mcInput->crendWrapper->p_io_qfactor = exp;
    7173             : #endif
    7174             :     /* call CREND */
    7175       26008 :     IF( NE_32( ( error = ivas_rend_crendProcessSubframe( mcInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, NULL, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, p_tmpCrendBuffer, mcInput->base.inputBuffer.config.numSamplesPerChannel, *mcInput->base.ctx.pOutSampleRate, 0 ) ), IVAS_ERR_OK ) )
    7176             :     {
    7177           0 :         return error;
    7178             :     }
    7179             : 
    7180       26008 :     IF( hCrend->hReverb != NULL )
    7181             :     {
    7182       13004 :         exp = sub( exp, 2 );
    7183             :     }
    7184             : 
    7185       26008 :     accumulate2dArrayToBuffer_fx( tmpCrendBuffer, &outAudio );
    7186             : 
    7187       26008 :     IF( NE_32( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ), IVAS_ERR_OK ) )
    7188             :     {
    7189           0 :         return error;
    7190             :     }
    7191       26008 :     *outAudio.pq_fact = exp;
    7192       26008 :     move16();
    7193       26008 :     IF( combinedOrientationEnabled )
    7194             :     {
    7195       13004 :         free( tmpRotBuffer.data_fx );
    7196             :     }
    7197       26008 :     free( tmpMcBuffer.data_fx );
    7198             : 
    7199       26008 :     pop_wmops();
    7200       26008 :     return IVAS_ERR_OK;
    7201             : }
    7202             : 
    7203      196617 : static void renderMcToMc(
    7204             :     const input_mc *mcInput,
    7205             :     IVAS_REND_AudioBuffer outAudio )
    7206             : {
    7207             :     Word16 i;
    7208             :     IVAS_REND_AudioBuffer inAudio;
    7209             : 
    7210      196617 :     push_wmops( "renderMcToMc" );
    7211      196617 :     inAudio = mcInput->base.inputBuffer;
    7212             : 
    7213     1507289 :     FOR( i = 0; i < inAudio.config.numChannels; ++i )
    7214             :     {
    7215     1310672 :         renderBufferChannel_fx( inAudio, i, mcInput->panGains_fx[i], outAudio );
    7216             :     }
    7217             : 
    7218      196617 :     pop_wmops();
    7219      196617 :     return;
    7220             : }
    7221             : 
    7222       75756 : static void renderMcToSba(
    7223             :     const input_mc *mcInput,
    7224             :     IVAS_REND_AudioBuffer outAudio )
    7225             : {
    7226             :     Word16 i;
    7227             :     IVAS_REND_AudioBuffer inAudio;
    7228             : 
    7229       75756 :     push_wmops( "renderMcToSba" );
    7230       75756 :     inAudio = mcInput->base.inputBuffer;
    7231             : 
    7232      591852 :     FOR( i = 0; i < inAudio.config.numChannels; ++i )
    7233             :     {
    7234      516096 :         renderBufferChannel_fx( inAudio, i, mcInput->panGains_fx[i], outAudio );
    7235             :     }
    7236       75756 :     pop_wmops();
    7237       75756 :     return;
    7238             : }
    7239             : 
    7240         150 : static void renderMcToMasa(
    7241             :     input_mc *mcInput,
    7242             :     IVAS_REND_AudioBuffer outAudio )
    7243             : {
    7244         150 :     push_wmops( "renderMcToMasa" );
    7245             :     Word32 tmpRendBuffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7246         150 :     copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer_fx );
    7247         150 :     ivas_mcmasa_ana_fx( mcInput->hMcMasa, tmpRendBuffer_fx, *( outAudio.pq_fact ), mcInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels, mcInput->base.inputBuffer.config.numChannels );
    7248         150 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer_fx, &outAudio );
    7249             : 
    7250         150 :     pop_wmops();
    7251         150 :     return;
    7252             : }
    7253             : 
    7254           0 : static ivas_error renderMcToSplitBinaural(
    7255             :     input_mc *mcInput,
    7256             :     const AUDIO_CONFIG outConfig,
    7257             :     IVAS_REND_AudioBuffer outAudio )
    7258             : {
    7259             :     Word16 i, j, pos_idx;
    7260             :     Word16 sf;
    7261             :     Word16 output_frame;
    7262             :     ivas_error error;
    7263             :     const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
    7264             :     const SPLIT_REND_WRAPPER *pSplitRendWrapper;
    7265             :     Word32 tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7266             :     Word32 *p_tmpRendBuffer[MAX_OUTPUT_CHANNELS];
    7267             :     Word32 tmpSplitBinauralBuffer[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k];
    7268             :     AUDIO_CONFIG inConfig;
    7269             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    7270             :     COMBINED_ORIENTATION_DATA combinedOrientationDataLocal;
    7271             :     COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal;
    7272           0 :     Word16 exp = *outAudio.pq_fact;
    7273           0 :     move16();
    7274             :     CREND_HANDLE hCrend;
    7275             :     IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs;
    7276             :     Word16 q_fact_orig;
    7277             : 
    7278           0 :     push_wmops( "renderMcToSplitBinaural" );
    7279           0 :     inConfig = mcInput->base.inConfig;
    7280           0 :     move32();
    7281           0 :     output_frame = mcInput->base.inputBuffer.config.numSamplesPerChannel;
    7282           0 :     move16();
    7283             : 
    7284           0 :     pSplitRendWrapper = mcInput->base.ctx.pSplitRendWrapper;
    7285           0 :     pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData;
    7286           0 :     move32();
    7287           0 :     move32();
    7288             : 
    7289           0 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    7290             :     {
    7291           0 :         p_tmpRendBuffer[i] = tmpRendBuffer[i];
    7292           0 :         move32();
    7293             :     }
    7294             : 
    7295             :     /* save current head positions */
    7296           0 :     pCombinedOrientationDataLocal = *mcInput->base.ctx.pCombinedOrientationData;
    7297           0 :     move32();
    7298           0 :     combinedOrientationDataLocal = *pCombinedOrientationDataLocal;
    7299           0 :     move32();
    7300           0 :     IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) )
    7301             :     {
    7302           0 :         FOR( sf = 1; sf < combinedOrientationDataLocal.num_subframes; ++sf )
    7303             :         {
    7304           0 :             Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[0], &combinedOrientationDataLocal.Quaternions[sf] );
    7305           0 :             FOR( i = 0; i < 3; i++ )
    7306             :             {
    7307           0 :                 FOR( j = 0; j < 3; j++ )
    7308             :                 {
    7309           0 :                     combinedOrientationDataLocal.Rmat_fx[sf][i][j] = combinedOrientationDataLocal.Rmat_fx[0][i][j];
    7310           0 :                     move32();
    7311             :                 }
    7312             :             }
    7313             :         }
    7314             :     }
    7315             : 
    7316             :     /* temporary buffer for rotation in source format for CREND */
    7317           0 :     tmpRotBuffer = mcInput->base.inputBuffer;
    7318           0 :     move32();
    7319           0 :     IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) )
    7320             :     {
    7321           0 :         tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) );
    7322             :     }
    7323             : 
    7324           0 :     FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ )
    7325             :     {
    7326           0 :         Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] );
    7327             :     }
    7328             : 
    7329           0 :     FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
    7330             :     {
    7331             :         /* Update head positions */
    7332           0 :         FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ )
    7333             :         {
    7334           0 :             Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22
    7335           0 :             q_fact_orig = Quaternions_orig[i].q_fact;
    7336           0 :             modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 );
    7337             :             /*euler*/
    7338           0 :             Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx );
    7339           0 :             Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
    7340           0 :             Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
    7341           0 :             Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
    7342             : 
    7343           0 :             Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), deg2rad_fx( Quaternions_abs.y_fx ), deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs );
    7344             : 
    7345           0 :             modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig );
    7346             : 
    7347           0 :             Copy_Quat_fx( &Quaternions_abs, &combinedOrientationDataLocal.Quaternions[i] );
    7348           0 :             QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] );
    7349           0 :             modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx[i], combinedOrientationDataLocal.Rmat_fx[i], sub( shl( q_fact_orig, 1 ), 32 ), Q30 );
    7350             :         }
    7351             : 
    7352           0 :         IF( EQ_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) )
    7353             :         {
    7354             :             /* tdrend processing overview:
    7355             :              *  1. copy from inputBuffer to tmpRendBuffer
    7356             :              *  2. td_binaural_renderer_ext: inplace processing in tmpRendBuffer
    7357             :              *  3. copy from tmpRendBuffer to tmpSplitBinBuffer
    7358             :              *  4. LFE mixing
    7359             :              *  5. tmpSplitBinBuffer accumulated to outBuffer */
    7360             : 
    7361             :             /* copy input to tdrend input/output buffer */
    7362           0 :             copyBufferTo2dArray_fx( mcInput->base.inputBuffer, tmpRendBuffer );
    7363             : 
    7364             :             /* perform rotation in source format to tmpRotBuffer */
    7365           0 :             pCombinedOrientationDataLocal = &combinedOrientationDataLocal;
    7366             : 
    7367           0 :             FOR( i = 0; i < MAX_OUTPUT_CHANNELS; ++i )
    7368             :             {
    7369           0 :                 Scale_sig32( tmpRendBuffer[i], L_FRAME48k, sub( Q11, exp ) ); /* Q11 */
    7370             :             }
    7371             :             /* Render */
    7372           0 :             IF( ( error = ivas_td_binaural_renderer_ext_fx( ( pos_idx == 0 ) ? &mcInput->tdRendWrapper : &mcInput->splitTdRendWrappers[pos_idx - 1], mcInput->base.inConfig, &mcInput->customLsInput, &pCombinedOrientationDataLocal, NULL, mcInput->hReverb, 0, /* Ism Audio Metadata Delay Sync in ms for External Renderer */ *mcInput->base.ctx.pOutSampleRate, mcInput->base.inputBuffer.config.numSamplesPerChannel, tmpRendBuffer, &exp ) ) != IVAS_ERR_OK )
    7373             :             {
    7374           0 :                 return error;
    7375             :             }
    7376           0 :             FOR( i = 0; i < BINAURAL_CHANNELS; ++i )
    7377             :             {
    7378           0 :                 Scale_sig32( tmpRendBuffer[i], L_FRAME48k, negate( sub( Q11, exp ) ) ); /* Q(exp) */
    7379             :             }
    7380             : 
    7381             :             /* Copy rendered audio to tmp storage buffer. Copying directly to output would
    7382             :              * overwrite original audio, which is still needed for rendering next head pose. */
    7383           0 :             Copy32( tmpRendBuffer[0], tmpSplitBinauralBuffer[i_mult( 2, pos_idx )], output_frame );
    7384           0 :             Copy32( tmpRendBuffer[1], tmpSplitBinauralBuffer[add( i_mult( 2, pos_idx ), 1 )], output_frame );
    7385             :         }
    7386             :         ELSE
    7387             :         {
    7388           0 :             hCrend = mcInput->crendWrapper->hCrend[0];
    7389             :             /* crend processing overview:
    7390             :              *  1. rotateFrameMc: inputBuffer to tmpRotBuffer
    7391             :              *  2. crend_process: tmpRotBuffer to tmpRendBuffer
    7392             :              *  3. copy from tmpRendBuffer to tmpSplitBinBuffer
    7393             :              *  4. LFE mixing
    7394             :              *  5. tmpSplitBinBuffer accumulated to outBuffer */
    7395             : 
    7396             : 
    7397             :             /* copy input for in-place rotation */
    7398           0 :             set32_fx( tmpRotBuffer.data_fx, 0, i_mult( tmpRotBuffer.config.numSamplesPerChannel, tmpRotBuffer.config.numChannels ) );
    7399             : 
    7400             :             /* perform rotation in source format to tmpRotBuffer */
    7401           0 :             pCombinedOrientationDataLocal = &combinedOrientationDataLocal;
    7402           0 :             IF( ( error = rotateFrameMc_fx( mcInput->base.inputBuffer, mcInput->base.inConfig, &mcInput->customLsInput, mcInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, mcInput->rot_gains_prev_fx[pos_idx], mcInput->efapInWrapper.hEfap, tmpRotBuffer ) ) != IVAS_ERR_OK )
    7403             :             {
    7404           0 :                 return error;
    7405             :             }
    7406           0 :             IF( EQ_16( pos_idx, 0 ) )
    7407             :             {
    7408           0 :                 exp = sub( *outAudio.pq_fact, 1 );
    7409             :             }
    7410             : 
    7411           0 :             copyBufferTo2dArray_fx( tmpRotBuffer, tmpRendBuffer );
    7412             : 
    7413             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7414           0 :             *mcInput->crendWrapper->p_io_qfactor = exp;
    7415             : #endif
    7416             :             /* call CREND (rotation already performed) */
    7417           0 :             IF( NE_32( ( error = ivas_rend_crendProcessSubframe( mcInput->crendWrapper, mcInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, NULL, p_tmpRendBuffer, p_tmpRendBuffer, mcInput->base.inputBuffer.config.numSamplesPerChannel, *mcInput->base.ctx.pOutSampleRate, pos_idx ) ), IVAS_ERR_OK ) )
    7418             :             {
    7419           0 :                 return error;
    7420             :             }
    7421             : 
    7422           0 :             IF( EQ_16( pos_idx, 0 ) )
    7423             :             {
    7424           0 :                 IF( hCrend->hReverb != NULL )
    7425             :                 {
    7426           0 :                     exp = sub( exp, 2 );
    7427             :                 }
    7428             :             }
    7429             : 
    7430             :             /* Copy rendererd audio to tmp storage buffer, Copying directly to output would
    7431             :              * overwrite original audio, which is still needed for rendering next head pose. */
    7432           0 :             Copy32( tmpRendBuffer[0], tmpSplitBinauralBuffer[i_mult( 2, pos_idx )], output_frame );
    7433           0 :             Copy32( tmpRendBuffer[1], tmpSplitBinauralBuffer[add( i_mult( 2, pos_idx ), 1 )], output_frame );
    7434             :         }
    7435             : 
    7436             :         /* restore original headrotation data */
    7437           0 :         FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ )
    7438             :         {
    7439           0 :             Copy_Quat_fx( &Quaternions_orig[i], &combinedOrientationDataLocal.Quaternions[i] );
    7440             :         }
    7441             :     }
    7442             : 
    7443           0 :     IF( NE_32( inConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_5_1 ) && NE_32( inConfig, IVAS_AUDIO_CONFIG_7_1 ) )
    7444             :     {
    7445             :         /* free temporary buffer for rotation in source format for CREND */
    7446           0 :         free( tmpRotBuffer.data_fx );
    7447             :     }
    7448             : 
    7449           0 :     accumulate2dArrayToBuffer_fx( tmpSplitBinauralBuffer, &outAudio );
    7450             : 
    7451           0 :     IF( ( error = renderLfeToBinaural_fx( mcInput, outConfig, outAudio, *outAudio.pq_fact, exp ) ) != IVAS_ERR_OK )
    7452             :     {
    7453           0 :         return error;
    7454             :     }
    7455           0 :     *outAudio.pq_fact = exp;
    7456             : 
    7457           0 :     pop_wmops();
    7458           0 :     return IVAS_ERR_OK;
    7459             : }
    7460             : 
    7461             : 
    7462      359535 : static ivas_error renderInputMc(
    7463             :     input_mc *mcInput,
    7464             :     const AUDIO_CONFIG outConfig,
    7465             :     IVAS_REND_AudioBuffer outAudio )
    7466             : {
    7467             :     ivas_error error;
    7468             :     IVAS_REND_AudioBuffer inAudio;
    7469      359535 :     error = IVAS_ERR_OK;
    7470      359535 :     move32();
    7471             : 
    7472      359535 :     inAudio = mcInput->base.inputBuffer;
    7473             : 
    7474      359535 :     IF( NE_32( mcInput->base.numNewSamplesPerChannel, outAudio.config.numSamplesPerChannel ) )
    7475             :     {
    7476           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" );
    7477             :     }
    7478      359535 :     mcInput->base.numNewSamplesPerChannel = 0;
    7479      359535 :     move32();
    7480      359535 :     v_multc_fixed( inAudio.data_fx, mcInput->base.gain_fx, inAudio.data_fx, inAudio.config.numSamplesPerChannel * inAudio.config.numChannels );
    7481      359535 :     *outAudio.pq_fact = sub( *outAudio.pq_fact, Q1 ); // reducing the Q by 1 compensating for the v_mult_fixed done
    7482      359535 :     move16();
    7483             :     /* set combined orientation subframe info to start info */
    7484      359535 :     ivas_combined_orientation_set_to_start_index( *( mcInput->base.ctx.pCombinedOrientationData ) );
    7485             : 
    7486      359535 :     SWITCH( getAudioConfigType( outConfig ) )
    7487             :     {
    7488      196617 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    7489      196617 :             renderMcToMc( mcInput, outAudio );
    7490      196617 :             BREAK;
    7491       75756 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    7492       75756 :             renderMcToSba( mcInput, outAudio );
    7493       75756 :             BREAK;
    7494       87012 :         case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL:
    7495             :             SWITCH( outConfig )
    7496             :             {
    7497       29004 :                 case IVAS_AUDIO_CONFIG_BINAURAL:
    7498       29004 :                     error = renderMcToBinaural( mcInput, outConfig, outAudio );
    7499       29004 :                     BREAK;
    7500       58008 :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
    7501             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    7502       58008 :                     IF( mcInput->base.inConfig == IVAS_AUDIO_CONFIG_LS_CUSTOM )
    7503             :                     {
    7504       26008 :                         error = renderMcCustomLsToBinauralRoom( mcInput, outConfig, outAudio );
    7505             :                     }
    7506             :                     ELSE
    7507             :                     {
    7508       32000 :                         error = renderMcToBinauralRoom( mcInput, outConfig, outAudio );
    7509             :                     }
    7510       58008 :                     BREAK;
    7511           0 :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
    7512             :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
    7513           0 :                     error = renderMcToSplitBinaural( mcInput, outConfig, outAudio );
    7514           0 :                     break;
    7515           0 :                 default:
    7516           0 :                     return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    7517             :             }
    7518       87012 :             BREAK;
    7519         150 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    7520         150 :             renderMcToMasa( mcInput, outAudio );
    7521         150 :             BREAK;
    7522           0 :         default:
    7523           0 :             return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    7524             :     }
    7525      359535 :     return error;
    7526             : }
    7527             : 
    7528             : 
    7529     1126140 : static ivas_error renderActiveInputsMc(
    7530             :     IVAS_REND_HANDLE hIvasRend,
    7531             :     IVAS_REND_AudioBuffer outAudio )
    7532             : {
    7533             :     Word16 i;
    7534             :     input_mc *pCurrentInput;
    7535             :     ivas_error error;
    7536     2252280 :     FOR( ( i = 0, pCurrentInput = hIvasRend->inputsMc ); i < RENDERER_MAX_MC_INPUTS; ( ++i, ++pCurrentInput ) )
    7537             :     {
    7538     1126140 :         IF( EQ_32( pCurrentInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    7539             :         {
    7540             :             /* Skip inactive inputs */
    7541      766605 :             CONTINUE;
    7542             :         }
    7543             : 
    7544      359535 :         *outAudio.pq_fact = outAudio.q_factor;
    7545      359535 :         move16();
    7546      359535 :         IF( NE_32( ( error = renderInputMc( pCurrentInput, hIvasRend->outputConfig, outAudio ) ), IVAS_ERR_OK ) )
    7547             :         {
    7548           0 :             return error;
    7549             :         }
    7550             :     }
    7551             : 
    7552     1126140 :     return IVAS_ERR_OK;
    7553             : }
    7554             : 
    7555             : 
    7556      115801 : static void renderSbaToMc(
    7557             :     const input_sba *sbaInput,
    7558             :     IVAS_REND_AudioBuffer outAudio )
    7559             : {
    7560             :     Word16 i;
    7561             :     IVAS_REND_AudioBuffer inAudio;
    7562             : 
    7563      115801 :     push_wmops( "renderSbaToMc" );
    7564      115801 :     inAudio = sbaInput->base.inputBuffer;
    7565             : 
    7566     1225294 :     FOR( i = 0; i < inAudio.config.numChannels; ++i )
    7567             :     {
    7568     1109493 :         renderBufferChannel_fx( inAudio, i, sbaInput->hoaDecMtx_fx[i], outAudio );
    7569             :     }
    7570             : 
    7571      115801 :     pop_wmops();
    7572      115801 :     return;
    7573             : }
    7574             : 
    7575             : 
    7576       45768 : static void renderSbaToSba(
    7577             :     const input_sba *sbaInput,
    7578             :     IVAS_REND_AudioBuffer outAudio )
    7579             : {
    7580             :     Word16 i;
    7581             :     IVAS_REND_AudioBuffer inAudio;
    7582             : 
    7583       45768 :     push_wmops( "renderSbaToSba" );
    7584       45768 :     inAudio = sbaInput->base.inputBuffer;
    7585             : 
    7586      483942 :     FOR( i = 0; i < inAudio.config.numChannels; ++i )
    7587             :     {
    7588      438174 :         renderBufferChannel_fx( inAudio, i, sbaInput->hoaDecMtx_fx[i], outAudio );
    7589             :     }
    7590             : 
    7591       45768 :     pop_wmops();
    7592       45768 :     return;
    7593             : }
    7594             : 
    7595             : 
    7596           0 : static ivas_error renderSbaToMultiBinaural(
    7597             :     input_sba *sbaInput,
    7598             :     const AUDIO_CONFIG outConfig,
    7599             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7600             :     Word32 out[][L_FRAME48k],
    7601             :     const Word16 *pq_fact )
    7602             : #else
    7603             :     Word32 out[][L_FRAME48k] )
    7604             : #endif
    7605             : {
    7606             :     Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7607             :     Word32 *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS];
    7608             :     Word16 sf;
    7609             :     Word16 i, j, pos_idx;
    7610             :     COMBINED_ORIENTATION_DATA combinedOrientationDataLocal;
    7611             :     COMBINED_ORIENTATION_HANDLE pCombinedOrientationDataLocal;
    7612             :     ivas_error error;
    7613             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    7614             :     const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData;
    7615             : 
    7616           0 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    7617             :     {
    7618           0 :         p_tmpCrendBuffer[i] = tmpCrendBuffer[i];
    7619           0 :         move32();
    7620             :     }
    7621           0 :     push_wmops( "renderSbaToMultiBinaural" );
    7622           0 :     pMultiBinPoseData = &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData;
    7623           0 :     move32();
    7624             : 
    7625           0 :     pCombinedOrientationDataLocal = *sbaInput->base.ctx.pCombinedOrientationData;
    7626           0 :     combinedOrientationDataLocal = *pCombinedOrientationDataLocal;
    7627           0 :     move32();
    7628           0 :     move32();
    7629             : 
    7630           0 :     IF( EQ_32( pMultiBinPoseData->poseCorrectionMode, ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) )
    7631             :     {
    7632           0 :         FOR( sf = 1; sf < combinedOrientationDataLocal.num_subframes; ++sf )
    7633             :         {
    7634           0 :             Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[0], &combinedOrientationDataLocal.Quaternions[sf] );
    7635           0 :             FOR( i = 0; i < 3; i++ )
    7636             :             {
    7637           0 :                 FOR( j = 0; j < 3; j++ )
    7638             :                 {
    7639           0 :                     combinedOrientationDataLocal.Rmat_fx[sf][i][j] = combinedOrientationDataLocal.Rmat_fx[0][i][j];
    7640           0 :                     move32();
    7641             :                 }
    7642             :             }
    7643             :         }
    7644             :     }
    7645             : 
    7646           0 :     tmpRotBuffer = sbaInput->base.inputBuffer;
    7647           0 :     tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) );
    7648             : 
    7649           0 :     FOR( pos_idx = 0; pos_idx < pMultiBinPoseData->num_poses; pos_idx++ )
    7650             :     {
    7651             :         IVAS_QUATERNION Quaternions_orig[MAX_PARAM_SPATIAL_SUBFRAMES], Quaternions_abs;
    7652             :         Word16 q_fact_orig;
    7653           0 :         FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ )
    7654             :         {
    7655           0 :             Copy_Quat_fx( &combinedOrientationDataLocal.Quaternions[i], &Quaternions_orig[i] );
    7656             : 
    7657           0 :             Quaternions_abs.w_fx = L_negate( 12582912 ); // Q22
    7658           0 :             q_fact_orig = combinedOrientationDataLocal.Quaternions[i].q_fact;
    7659           0 :             modify_Quat_q_fx( &combinedOrientationDataLocal.Quaternions[i], &combinedOrientationDataLocal.Quaternions[i], Q22 );
    7660             :             /*euler*/
    7661           0 :             Quat2EulerDegree_fx( combinedOrientationDataLocal.Quaternions[i], &Quaternions_abs.z_fx, &Quaternions_abs.y_fx, &Quaternions_abs.x_fx );
    7662           0 :             Quaternions_abs.x_fx = L_add( Quaternions_abs.x_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][0] );
    7663           0 :             Quaternions_abs.y_fx = L_add( Quaternions_abs.y_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][1] );
    7664           0 :             Quaternions_abs.z_fx = L_add( Quaternions_abs.z_fx, pMultiBinPoseData->relative_head_poses_fx[pos_idx][2] );
    7665             : 
    7666           0 :             Euler2Quat_fx( deg2rad_fx( Quaternions_abs.x_fx ), deg2rad_fx( Quaternions_abs.y_fx ), deg2rad_fx( Quaternions_abs.z_fx ), &Quaternions_abs );
    7667             : 
    7668           0 :             modify_Quat_q_fx( &Quaternions_abs, &Quaternions_abs, q_fact_orig );
    7669             : 
    7670           0 :             Copy_Quat_fx( &Quaternions_abs, &combinedOrientationDataLocal.Quaternions[i] );
    7671           0 :             QuatToRotMat_fx( combinedOrientationDataLocal.Quaternions[i], combinedOrientationDataLocal.Rmat_fx[i] );
    7672           0 :             modify_Rmat_q_fx( combinedOrientationDataLocal.Rmat_fx[i], combinedOrientationDataLocal.Rmat_fx[i], sub( shl( q_fact_orig, 1 ), 32 ), Q30 );
    7673             :         }
    7674             : 
    7675             :         /* copy input for in-place rotation */
    7676           0 :         Copy32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, tmpRotBuffer.config.numChannels * tmpRotBuffer.config.numSamplesPerChannel );
    7677             : 
    7678           0 :         pCombinedOrientationDataLocal = &combinedOrientationDataLocal;
    7679             : 
    7680           0 :         IF( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, &pCombinedOrientationDataLocal, sbaInput->rot_gains_prev_fx[pos_idx], tmpRotBuffer ) ) != IVAS_ERR_OK )
    7681             :         {
    7682           0 :             return error;
    7683             :         }
    7684             : 
    7685           0 :         copyBufferTo2dArray_fx( tmpRotBuffer, tmpCrendBuffer );
    7686             : 
    7687           0 :         assert( sbaInput->crendWrapper->hCrend[0]->hReverb == NULL );
    7688             : 
    7689             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7690           0 :         *sbaInput->crendWrapper->p_io_qfactor = *pq_fact;
    7691             : #endif
    7692             :         /* call CREND */
    7693           0 :         IF( NE_32( ( error = ivas_rend_crendProcessSubframe( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, p_tmpCrendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, *sbaInput->base.ctx.pOutSampleRate, pos_idx ) ), IVAS_ERR_OK ) )
    7694             :         {
    7695           0 :             return error;
    7696             :         }
    7697             : 
    7698           0 :         FOR( i = 0; i < combinedOrientationDataLocal.num_subframes; i++ )
    7699             :         {
    7700           0 :             Copy_Quat_fx( &Quaternions_orig[i], &combinedOrientationDataLocal.Quaternions[i] );
    7701             :         }
    7702             : 
    7703             :         /* move to output */
    7704           0 :         FOR( i = 0; i < BINAURAL_CHANNELS; i++ )
    7705             :         {
    7706           0 :             Copy32( tmpCrendBuffer[i], out[pos_idx * BINAURAL_CHANNELS + i], tmpRotBuffer.config.numSamplesPerChannel );
    7707             :         }
    7708             :     }
    7709             : 
    7710           0 :     free( tmpRotBuffer.data_fx );
    7711             : 
    7712           0 :     pop_wmops();
    7713           0 :     return IVAS_ERR_OK;
    7714             : }
    7715             : 
    7716             : 
    7717           0 : static ivas_error renderSbaToMultiBinauralCldfb(
    7718             :     input_sba *sbaInput,
    7719             :     Word32 Cldfb_Out_Real[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
    7720             :     Word32 Cldfb_Out_Imag[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX],
    7721             :     const Word16 low_res_pre_rend_rot,
    7722             :     const Word16 num_subframes,
    7723             :     const Word16 Q_in )
    7724             : {
    7725             :     Word32 Cldfb_RealBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    7726             :     Word32 Cldfb_ImagBuffer[MAX_OUTPUT_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    7727             : 
    7728           0 :     copyBufferToCLDFBarray_fx( sbaInput->base.inputBuffer, Cldfb_RealBuffer, Cldfb_ImagBuffer );
    7729             : 
    7730           0 :     ivas_rend_CldfbMultiBinRendProcess( sbaInput->cldfbRendWrapper.hCldfbRend, sbaInput->base.ctx.pCombinedOrientationData, &sbaInput->base.ctx.pSplitRendWrapper->multiBinPoseData,
    7731             :                                         Cldfb_RealBuffer, Cldfb_ImagBuffer, Cldfb_Out_Real, Cldfb_Out_Imag, low_res_pre_rend_rot, num_subframes, Q_in );
    7732             : 
    7733           0 :     return IVAS_ERR_OK;
    7734             : }
    7735             : 
    7736             : 
    7737           0 : static ivas_error renderSbaToSplitBinaural(
    7738             :     input_sba *sbaInput,
    7739             :     const AUDIO_CONFIG outConfig,
    7740             :     IVAS_REND_AudioBuffer outAudio )
    7741             : {
    7742             :     Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7743             :     ivas_error error;
    7744             :     Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    7745             :     Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    7746             :     Word16 low_res_pre_rend_rot;
    7747             : 
    7748           0 :     low_res_pre_rend_rot = 1;
    7749             : 
    7750           0 :     push_wmops( "renderSbaToSplitBinaural" );
    7751             : 
    7752           0 :     IF( EQ_32( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) )
    7753             :     {
    7754           0 :         if ( ( error = renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, low_res_pre_rend_rot,
    7755           0 :                                                       getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ), *outAudio.pq_fact ) ) != IVAS_ERR_OK )
    7756             :         {
    7757           0 :             return error;
    7758             :         }
    7759             : 
    7760           0 :         accumulateCLDFBArrayToBuffer_fx( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio );
    7761             :     }
    7762             :     else
    7763             :     {
    7764             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7765           0 :         IF( ( error = renderSbaToMultiBinaural( sbaInput, outConfig, tmpCrendBuffer, outAudio.pq_fact ) ) != IVAS_ERR_OK )
    7766             : #else
    7767             :         IF( ( error = renderSbaToMultiBinaural( sbaInput, outConfig, tmpCrendBuffer ) ) != IVAS_ERR_OK )
    7768             : #endif
    7769             :         {
    7770           0 :             return error;
    7771             :         }
    7772             : 
    7773           0 :         IF( sbaInput->crendWrapper->hCrend[0]->hReverb != NULL )
    7774             :         {
    7775           0 :             *outAudio.pq_fact = sub( *outAudio.pq_fact, Q2 );
    7776           0 :             move16();
    7777             :         }
    7778             : 
    7779           0 :         accumulate2dArrayToBuffer_fx( tmpCrendBuffer, &outAudio );
    7780             :     }
    7781             : 
    7782           0 :     pop_wmops();
    7783           0 :     return IVAS_ERR_OK;
    7784             : }
    7785             : 
    7786             : 
    7787       60024 : static ivas_error renderSbaToBinaural(
    7788             :     input_sba *sbaInput,
    7789             :     const AUDIO_CONFIG outConfig,
    7790             :     IVAS_REND_AudioBuffer outAudio )
    7791             : {
    7792             :     ivas_error error;
    7793             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    7794             :     Word16 i;
    7795             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
    7796             :     Word8 combinedOrientationEnabled;
    7797             :     Word16 subframe_idx;
    7798             :     Word32 output_buffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7799             :     Word32 *output_fx[MAX_OUTPUT_CHANNELS];
    7800             : 
    7801       60024 :     push_wmops( "renderSbaToBinaural" );
    7802             : 
    7803       60024 :     IF( EQ_32( sbaInput->base.ctx.hhRendererConfig[0]->split_rend_config.rendererSelection, ISAR_SPLIT_REND_RENDERER_SELECTION_FASTCONV ) )
    7804             :     {
    7805             :         Word32 Cldfb_RealBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    7806             :         Word32 Cldfb_ImagBuffer_Binaural[BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    7807             : 
    7808           0 :         IF( ( error = renderSbaToMultiBinauralCldfb( sbaInput, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, 0,
    7809             :                                                      getNumSubframesInBuffer( &outAudio, *sbaInput->base.ctx.pOutSampleRate ), *outAudio.pq_fact ) ) != IVAS_ERR_OK )
    7810             :         {
    7811           0 :             return error;
    7812             :         }
    7813             : 
    7814           0 :         accumulateCLDFBArrayToBuffer_fx( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio );
    7815             :     }
    7816             :     ELSE
    7817             :     {
    7818     1020408 :         FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    7819             :         {
    7820      960384 :             output_fx[i] = output_buffer_fx[i];
    7821      960384 :             move32();
    7822             :         }
    7823             : 
    7824       60024 :         hCombinedOrientationData = sbaInput->base.ctx.pCombinedOrientationData;
    7825       60024 :         combinedOrientationEnabled = 0;
    7826       60024 :         move16();
    7827             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    7828       60024 :         IF( *hCombinedOrientationData != NULL )
    7829             : #else
    7830             :         IF( hCombinedOrientationData != NULL )
    7831             : #endif
    7832             :         {
    7833       30012 :             FOR( subframe_idx = 0; subframe_idx < ( *hCombinedOrientationData )->num_subframes; subframe_idx++ )
    7834             :             {
    7835       30012 :                 IF( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
    7836             :                 {
    7837       30012 :                     combinedOrientationEnabled = 1;
    7838       30012 :                     move16();
    7839       30012 :                     BREAK;
    7840             :                 }
    7841             :             }
    7842             :         }
    7843             : 
    7844             :         /* apply rotation */
    7845       60024 :         IF( combinedOrientationEnabled )
    7846             :         {
    7847       30012 :             tmpRotBuffer = sbaInput->base.inputBuffer;
    7848             : 
    7849       30012 :             tmpRotBuffer.data_fx = malloc( tmpRotBuffer.config.numSamplesPerChannel * tmpRotBuffer.config.numChannels * sizeof( Word32 ) );
    7850             : 
    7851             :             /* copy input for in-place rotation */
    7852       30012 :             Copy32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, i_mult( tmpRotBuffer.config.numChannels, tmpRotBuffer.config.numSamplesPerChannel ) );
    7853             : 
    7854       30012 :             IF( NE_16( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->base.ctx.pCombinedOrientationData, sbaInput->rot_gains_prev_fx[0], tmpRotBuffer ) ),
    7855             :                        IVAS_ERR_OK ) )
    7856             :             {
    7857           0 :                 return error;
    7858             :             }
    7859             : 
    7860       30012 :             copyBufferTo2dArray_fx( tmpRotBuffer, output_buffer_fx );
    7861       30012 :             free( tmpRotBuffer.data_fx );
    7862             :         }
    7863             :         ELSE
    7864             :         {
    7865       30012 :             copyBufferTo2dArray_fx( sbaInput->base.inputBuffer, output_buffer_fx );
    7866             :         }
    7867             : 
    7868             :         CREND_HANDLE hCrend;
    7869       60024 :         hCrend = sbaInput->crendWrapper->hCrend[0];
    7870             : 
    7871             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7872       60024 :         *sbaInput->crendWrapper->p_io_qfactor = *outAudio.pq_fact;
    7873             : #endif
    7874             :         /* call CREND */
    7875       60024 :         IF( NE_32( ( error = ivas_rend_crendProcessSubframe( sbaInput->crendWrapper, sbaInput->base.inConfig, outConfig, NULL, NULL, NULL, NULL, NULL, output_fx, output_fx, sbaInput->base.inputBuffer.config.numSamplesPerChannel, *sbaInput->base.ctx.pOutSampleRate, 0 ) ), IVAS_ERR_OK ) )
    7876             :         {
    7877           0 :             return error;
    7878             :         }
    7879             : 
    7880       60024 :         IF( hCrend->hReverb != NULL )
    7881             :         {
    7882       30012 :             *outAudio.pq_fact = sub( *outAudio.pq_fact, Q2 );
    7883       30012 :             move16();
    7884             :         }
    7885             : 
    7886       60024 :         accumulate2dArrayToBuffer_fx( output_buffer_fx, &outAudio );
    7887             :     }
    7888             : 
    7889       60024 :     pop_wmops();
    7890       60024 :     return IVAS_ERR_OK;
    7891             : }
    7892             : 
    7893             : 
    7894       30012 : static ivas_error renderSbaToBinauralRoom(
    7895             :     input_sba *sbaInput,
    7896             :     const AUDIO_CONFIG outConfig,
    7897             :     IVAS_REND_AudioBuffer outAudio )
    7898             : {
    7899             :     Word16 i;
    7900             :     Word16 tmp;
    7901             :     Word32 tmpCrendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    7902             :     ivas_error error;
    7903             :     IVAS_REND_AudioBuffer tmpRotBuffer;
    7904             :     IVAS_REND_AudioBuffer tmpMcBuffer;
    7905             :     IVAS_REND_AudioBuffer *tmpBufPtr;
    7906             :     Word32 *p_tmpCrendBuffer[MAX_OUTPUT_CHANNELS];
    7907             :     const COMBINED_ORIENTATION_HANDLE *hCombinedOrientationData;
    7908             :     Word8 combinedOrientationEnabled;
    7909             :     Word16 subframe_idx;
    7910             : 
    7911       30012 :     tmpRotBuffer = outAudio; /* avoid compilation warning */
    7912       30012 :     push_wmops( "renderSbaToBinauralRoom" );
    7913             :     Word16 nchan_out;
    7914             :     CREND_HANDLE hCrend;
    7915       30012 :     hCrend = sbaInput->crendWrapper->hCrend[0];
    7916             : 
    7917       30012 :     IF( NE_32( ( error = getAudioConfigNumChannels( outConfig, &nchan_out ) ), IVAS_ERR_OK ) )
    7918             :     {
    7919           0 :         return error;
    7920             :     }
    7921             : 
    7922      510204 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
    7923             :     {
    7924      480192 :         p_tmpCrendBuffer[i] = tmpCrendBuffer[i];
    7925             :     }
    7926             : 
    7927       30012 :     hCombinedOrientationData = sbaInput->base.ctx.pCombinedOrientationData;
    7928       30012 :     combinedOrientationEnabled = 0;
    7929       30012 :     move16();
    7930             : #ifdef FIX_1135_EXT_RENDERER_HANDLES
    7931       30012 :     IF( *hCombinedOrientationData != NULL )
    7932             : #else
    7933             :     IF( hCombinedOrientationData != NULL )
    7934             : #endif
    7935             :     {
    7936       15006 :         FOR( subframe_idx = 0; subframe_idx < ( *hCombinedOrientationData )->num_subframes; subframe_idx++ )
    7937             :         {
    7938       15006 :             IF( ( *hCombinedOrientationData )->enableCombinedOrientation[subframe_idx] != 0 )
    7939             :             {
    7940       15006 :                 combinedOrientationEnabled = 1;
    7941       15006 :                 move16();
    7942       15006 :                 BREAK;
    7943             :             }
    7944             :         }
    7945             :     }
    7946             : 
    7947             :     /* apply rotation */
    7948       30012 :     IF( combinedOrientationEnabled )
    7949             :     {
    7950       15006 :         tmpRotBuffer = sbaInput->base.inputBuffer;
    7951       15006 :         tmpRotBuffer.data_fx = malloc( imult1616( tmpRotBuffer.config.numSamplesPerChannel, tmpRotBuffer.config.numChannels ) * sizeof( Word32 ) );
    7952             : 
    7953             :         /* copy input for in-place rotation */
    7954       15006 :         Copy32( sbaInput->base.inputBuffer.data_fx, tmpRotBuffer.data_fx, i_mult( tmpRotBuffer.config.numChannels, tmpRotBuffer.config.numSamplesPerChannel ) );
    7955             : 
    7956       15006 :         IF( NE_32( ( error = rotateFrameSba_fx( sbaInput->base.inputBuffer, sbaInput->base.inConfig, sbaInput->base.ctx.pHeadRotData, sbaInput->base.ctx.pCombinedOrientationData, sbaInput->rot_gains_prev_fx[0], tmpRotBuffer ) ),
    7957             :                    IVAS_ERR_OK ) )
    7958             :         {
    7959           0 :             return error;
    7960             :         }
    7961             :     }
    7962             : 
    7963             :     /* intermediate rendering to 7_1_4 */
    7964       30012 :     tmpMcBuffer = sbaInput->base.inputBuffer;
    7965             : 
    7966       30012 :     IF( NE_32( ( error = getAudioConfigNumChannels( IVAS_AUDIO_CONFIG_7_1_4, &tmp ) ), IVAS_ERR_OK ) )
    7967             :     {
    7968           0 :         return error;
    7969             :     }
    7970             : 
    7971       30012 :     tmpMcBuffer.config.numChannels = tmp;
    7972       30012 :     move16();
    7973       30012 :     tmpMcBuffer.data_fx = malloc( tmpMcBuffer.config.numSamplesPerChannel * tmpMcBuffer.config.numChannels * sizeof( Word32 ) );
    7974       30012 :     set32_fx( tmpMcBuffer.data_fx, 0, i_mult( tmpMcBuffer.config.numChannels, tmpMcBuffer.config.numSamplesPerChannel ) );
    7975             : 
    7976       30012 :     IF( combinedOrientationEnabled )
    7977             :     {
    7978       15006 :         tmpBufPtr = &tmpRotBuffer;
    7979             :     }
    7980             :     ELSE
    7981             :     {
    7982       15006 :         tmpBufPtr = &sbaInput->base.inputBuffer;
    7983             :     }
    7984      320128 :     FOR( i = 0; i < sbaInput->base.inputBuffer.config.numChannels; i++ )
    7985             :     {
    7986      290116 :         renderBufferChannel_fx( *tmpBufPtr, i, sbaInput->hoaDecMtx_fx[i], tmpMcBuffer );
    7987             :     }
    7988       30012 :     copyBufferTo2dArray_fx( tmpMcBuffer, tmpCrendBuffer );
    7989             : 
    7990             : #ifdef FIX_1843_IO_QFACTOR_INIT
    7991       30012 :     *sbaInput->crendWrapper->p_io_qfactor = *outAudio.pq_fact;
    7992             : #endif
    7993             :     /* call CREND */
    7994       30012 :     IF( NE_32( ( error = ivas_rend_crendProcessSubframe( sbaInput->crendWrapper, IVAS_AUDIO_CONFIG_7_1_4, outConfig, NULL, NULL, NULL, NULL, NULL, p_tmpCrendBuffer, p_tmpCrendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, *sbaInput->base.ctx.pOutSampleRate, 0 ) ), IVAS_ERR_OK ) )
    7995             :     {
    7996           0 :         return error;
    7997             :     }
    7998             : 
    7999       30012 :     IF( hCrend->hReverb != NULL )
    8000             :     {
    8001           0 :         *outAudio.pq_fact = sub( *outAudio.pq_fact, 2 );
    8002           0 :         move16();
    8003             :     }
    8004             : 
    8005       30012 :     accumulate2dArrayToBuffer_fx( tmpCrendBuffer, &outAudio );
    8006             : 
    8007       30012 :     IF( combinedOrientationEnabled )
    8008             :     {
    8009       15006 :         free( tmpRotBuffer.data_fx );
    8010             :     }
    8011       30012 :     free( tmpMcBuffer.data_fx );
    8012             : 
    8013       30012 :     pop_wmops();
    8014       30012 :     return IVAS_ERR_OK;
    8015             : }
    8016             : 
    8017             : 
    8018         150 : static void renderSbaToMasa(
    8019             :     input_sba *sbaInput,
    8020             :     IVAS_REND_AudioBuffer outAudio )
    8021             : {
    8022             :     Word32 tmpRendBuffer[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    8023             : 
    8024         150 :     push_wmops( "renderMcToMasa" );
    8025         150 :     copyBufferTo2dArray_fx( sbaInput->base.inputBuffer, tmpRendBuffer );
    8026         150 :     ivas_dirac_ana_fx( sbaInput->hDirAC, tmpRendBuffer, sbaInput->base.inputBuffer.config.numSamplesPerChannel, outAudio.config.numChannels, *outAudio.pq_fact );
    8027         150 :     accumulate2dArrayToBuffer_fx( tmpRendBuffer, &outAudio );
    8028             : 
    8029         150 :     pop_wmops();
    8030         150 :     return;
    8031             : }
    8032             : 
    8033             : 
    8034      251755 : static ivas_error renderInputSba(
    8035             :     input_sba *sbaInput,
    8036             :     const AUDIO_CONFIG outConfig,
    8037             :     IVAS_REND_AudioBuffer outAudio )
    8038             : {
    8039             :     ivas_error error;
    8040             :     IVAS_REND_AudioBuffer inAudio;
    8041             :     Word16 cldfb2tdShift;
    8042      251755 :     error = IVAS_ERR_OK;
    8043      251755 :     move32();
    8044      251755 :     inAudio = sbaInput->base.inputBuffer;
    8045             : 
    8046      251755 :     cldfb2tdShift = outAudio.config.is_cldfb ? 1 : 0;
    8047      251755 :     IF( NE_32( L_shl( sbaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) &&
    8048             :         NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    8049             :     {
    8050           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" );
    8051             :     }
    8052      251755 :     sbaInput->base.numNewSamplesPerChannel = 0;
    8053      251755 :     move32();
    8054      251755 :     *outAudio.pq_fact = outAudio.q_factor;
    8055      251755 :     move16();
    8056             :     /* Apply input gain to new audio */
    8057      251755 :     v_multc_fixed( inAudio.data_fx, sbaInput->base.gain_fx, inAudio.data_fx, i_mult( inAudio.config.numSamplesPerChannel, inAudio.config.numChannels ) );
    8058      251755 :     *outAudio.pq_fact = sub( *outAudio.pq_fact, 1 ); // to compensate for the qfactor reduction in gain multiplication.
    8059      251755 :     move16();
    8060             : 
    8061             :     /* set combined orientation subframe info to start info */
    8062      251755 :     ivas_combined_orientation_set_to_start_index( *( sbaInput->base.ctx.pCombinedOrientationData ) );
    8063             : 
    8064      251755 :     SWITCH( getAudioConfigType( outConfig ) )
    8065             :     {
    8066      115801 :         case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED:
    8067      115801 :             renderSbaToMc( sbaInput, outAudio );
    8068      115801 :             BREAK;
    8069       45768 :         case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS:
    8070       45768 :             renderSbaToSba( sbaInput, outAudio );
    8071       45768 :             BREAK;
    8072       90036 :         case IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL:
    8073             :             SWITCH( outConfig )
    8074             :             {
    8075           0 :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
    8076             :                 case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
    8077           0 :                     error = renderSbaToSplitBinaural( sbaInput, outConfig, outAudio );
    8078           0 :                     break;
    8079             : #ifdef FIX_1129_EXT_REND_OUTPUT_HIGH
    8080       60024 :                 case IVAS_AUDIO_CONFIG_BINAURAL:
    8081             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    8082       60024 :                     error = renderSbaToBinaural( sbaInput, outConfig, outAudio );
    8083       60024 :                     break;
    8084       30012 :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
    8085             : #else
    8086             :                 case IVAS_AUDIO_CONFIG_BINAURAL:
    8087             :                     error = renderSbaToBinaural( sbaInput, outConfig, outAudio );
    8088             :                     BREAK;
    8089             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
    8090             :                 case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
    8091             : #endif
    8092       30012 :                     error = renderSbaToBinauralRoom( sbaInput, outConfig, outAudio );
    8093       30012 :                     BREAK;
    8094           0 :                 default:
    8095           0 :                     return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    8096             :             }
    8097       90036 :             BREAK;
    8098         150 :         case IVAS_REND_AUDIO_CONFIG_TYPE_MASA:
    8099         150 :             renderSbaToMasa( sbaInput, outAudio );
    8100         150 :             BREAK;
    8101           0 :         default:
    8102           0 :             return IVAS_ERR_INVALID_OUTPUT_FORMAT;
    8103             :     }
    8104             : 
    8105      251755 :     return error;
    8106             : }
    8107             : 
    8108             : 
    8109     1126140 : static ivas_error renderActiveInputsSba(
    8110             :     IVAS_REND_HANDLE hIvasRend,
    8111             :     IVAS_REND_AudioBuffer outAudio )
    8112             : {
    8113             :     Word16 i;
    8114             :     input_sba *pCurrentInput;
    8115             :     ivas_error error;
    8116             : 
    8117     2252280 :     FOR( ( i = 0, pCurrentInput = hIvasRend->inputsSba ); i < RENDERER_MAX_SBA_INPUTS; ( ++i, ++pCurrentInput ) )
    8118             :     {
    8119     1126140 :         IF( EQ_32( pCurrentInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8120             :         {
    8121             :             /* Skip inactive inputs */
    8122      874385 :             CONTINUE;
    8123             :         }
    8124      251755 :         *outAudio.pq_fact = outAudio.q_factor;
    8125      251755 :         move16();
    8126      251755 :         IF( NE_32( ( error = renderInputSba( pCurrentInput, hIvasRend->outputConfig, outAudio ) ), IVAS_ERR_OK ) )
    8127             :         {
    8128           0 :             return error;
    8129             :         }
    8130             :     }
    8131             : 
    8132     1126140 :     return IVAS_ERR_OK;
    8133             : }
    8134             : 
    8135             : 
    8136       17250 : static void copyMasaMetadataToDiracRenderer_fx(
    8137             :     MASA_METADATA_FRAME *meta,
    8138             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom,
    8139             :     const Word16 maxBin )
    8140             : {
    8141             :     Word16 band, sf, bin;
    8142             :     Word16 meta_write_index;
    8143             : 
    8144       17250 :     hSpatParamRendCom->numParametricDirections = add( meta->descriptive_meta.numberOfDirections, 1 );
    8145       17250 :     hSpatParamRendCom->numSimultaneousDirections = add( meta->descriptive_meta.numberOfDirections, 1 );
    8146       17250 :     move16();
    8147       17250 :     move16();
    8148             : 
    8149       86250 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    8150             :     {
    8151       69000 :         meta_write_index = add( hSpatParamRendCom->dirac_bs_md_write_idx, sf ) % hSpatParamRendCom->dirac_md_buffer_length;
    8152             : 
    8153     1725000 :         FOR( band = 0; band < MASA_MAXIMUM_CODING_SUBBANDS; band++ )
    8154             :         {
    8155     5796000 :             FOR( bin = MASA_band_grouping_24[band]; bin < MASA_band_grouping_24[band + 1] && bin < maxBin; bin++ )
    8156             :             {
    8157     4140000 :                 hSpatParamRendCom->azimuth[meta_write_index][bin] = extract_l( L_shr( meta->directional_meta[0].azimuth_fx[sf][band], Q22 ) ); /* Q22 - Q22 = Q0 */
    8158     4140000 :                 move16();
    8159     4140000 :                 hSpatParamRendCom->elevation[meta_write_index][bin] = extract_l( L_shr( meta->directional_meta[0].elevation_fx[sf][band], Q22 ) ); /* Q22 - Q22 = Q0 */
    8160     4140000 :                 move16();
    8161     4140000 :                 hSpatParamRendCom->energy_ratio1_fx[meta_write_index][bin] = meta->directional_meta[0].energy_ratio_fx[sf][band];
    8162     4140000 :                 move32();
    8163     4140000 :                 hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][bin] = L_sub( ONE_IN_Q30, meta->directional_meta[0].energy_ratio_fx[sf][band] );
    8164     4140000 :                 move32();
    8165     4140000 :                 hSpatParamRendCom->spreadCoherence_fx[meta_write_index][bin] = meta->directional_meta[0].spread_coherence_fx[sf][band];
    8166     4140000 :                 move16();
    8167     4140000 :                 hSpatParamRendCom->surroundingCoherence_fx[meta_write_index][bin] = meta->common_meta.surround_coherence_fx[sf][band];
    8168     4140000 :                 move16();
    8169             : 
    8170     4140000 :                 IF( EQ_16( hSpatParamRendCom->numSimultaneousDirections, 2 ) )
    8171             :                 {
    8172     2160000 :                     hSpatParamRendCom->azimuth2[meta_write_index][bin] = extract_l( L_shr( meta->directional_meta[1].azimuth_fx[sf][band], Q22 ) ); /* Q22 - Q22 = Q0 */
    8173     2160000 :                     move16();
    8174     2160000 :                     hSpatParamRendCom->elevation2[meta_write_index][bin] = extract_l( L_shr( meta->directional_meta[1].elevation_fx[sf][band], Q22 ) ); /* Q22 - Q22 = Q0 */
    8175     2160000 :                     move16();
    8176     2160000 :                     hSpatParamRendCom->energy_ratio2_fx[meta_write_index][bin] = meta->directional_meta[1].energy_ratio_fx[sf][band];
    8177     2160000 :                     move32();
    8178     2160000 :                     hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][bin] = L_sub( hSpatParamRendCom->diffuseness_vector_fx[meta_write_index][bin], meta->directional_meta[1].energy_ratio_fx[sf][band] );
    8179     2160000 :                     move32();
    8180     2160000 :                     hSpatParamRendCom->spreadCoherence2_fx[meta_write_index][bin] = meta->directional_meta[1].spread_coherence_fx[sf][band];
    8181     2160000 :                     move16();
    8182             :                 }
    8183             :             }
    8184             :         }
    8185             :     }
    8186             : 
    8187       17250 :     hSpatParamRendCom->dirac_bs_md_write_idx = add( hSpatParamRendCom->dirac_bs_md_write_idx, MAX_PARAM_SPATIAL_SUBFRAMES ) % hSpatParamRendCom->dirac_md_buffer_length;
    8188       17250 :     move16();
    8189             : 
    8190       17250 :     return;
    8191             : }
    8192             : 
    8193             : 
    8194         150 : static void renderMasaToMasa(
    8195             :     input_masa *masaInput,
    8196             :     IVAS_REND_AudioBuffer outAudio )
    8197             : {
    8198             :     Word16 sf, band, dir, numDirs;
    8199             :     Word32 ratioSum_fx; /* Q30 */
    8200             :     MASA_DECODER_EXT_OUT_META_HANDLE outMeta;
    8201             :     MASA_METADATA_FRAME *inMeta;
    8202             :     Word32 tmpBuffer_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    8203             :     Word16 ts, i, j, l_ts;
    8204             :     Word32 Chan_RealBuffer_fx[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    8205             :     Word32 Chan_ImagBuffer_fx[MASA_MAX_TRANSPORT_CHANNELS][CLDFB_NO_CHANNELS_MAX];
    8206             :     Word16 band_m_idx, block_m_idx;
    8207             :     Word16 mrange[2];
    8208             :     Word16 brange[2];
    8209             :     Word16 numAnalysisChannels;
    8210         150 :     copyBufferTo2dArray_fx( masaInput->base.inputBuffer, tmpBuffer_fx );
    8211         150 :     Word16 q_cldfb = *outAudio.pq_fact;
    8212         150 :     Word16 q_cldfb_out = *outAudio.pq_fact;
    8213         150 :     Word16 scale_factor = 31;
    8214             :     Word16 scale_fac_arr[MASA_MAX_TRANSPORT_CHANNELS];
    8215         150 :     move16();
    8216         150 :     move16();
    8217         150 :     move16();
    8218             :     /* Calculate energy */
    8219             :     // l_ts = masaInput->base.inputBuffer.config.numSamplesPerChannel / CLDFB_NO_COL_MAX;
    8220         150 :     l_ts = shr( masaInput->base.inputBuffer.config.numSamplesPerChannel, 4 );
    8221         150 :     numAnalysisChannels = masaInput->hMasaPrerend->num_Cldfb_instances;
    8222         150 :     move16();
    8223             :     /* do processing over all CLDFB time slots */
    8224         750 :     FOR( block_m_idx = 0; block_m_idx < MAX_PARAM_SPATIAL_SUBFRAMES; block_m_idx++ )
    8225             :     {
    8226         600 :         mrange[0] = DirAC_block_grouping[block_m_idx];
    8227         600 :         mrange[1] = DirAC_block_grouping[block_m_idx + 1];
    8228         600 :         move16();
    8229         600 :         move16();
    8230             : 
    8231         600 :         set_zero_fx( masaInput->hMasaPrerend->energy_fx[block_m_idx], MASA_FREQUENCY_BANDS );
    8232         600 :         set16_fx( masaInput->hMasaPrerend->energy_e[block_m_idx], 0, MASA_FREQUENCY_BANDS );
    8233             : 
    8234        3000 :         FOR( ts = mrange[0]; ts < mrange[1]; ts++ )
    8235             :         {
    8236        7200 :             FOR( i = 0; i < numAnalysisChannels; i++ )
    8237             :             {
    8238        4800 :                 scale_factor = 31;
    8239        4800 :                 move16();
    8240        4800 :                 masaInput->hMasaPrerend->cldfbAnaEnc[i]->Q_cldfb_state = q_cldfb;
    8241        4800 :                 q_cldfb_out = q_cldfb;
    8242        4800 :                 move16();
    8243        4800 :                 move16();
    8244        4800 :                 cldfbAnalysis_ts_fx_fixed_q( &( tmpBuffer_fx[i][l_ts * ts] ), Chan_RealBuffer_fx[i], Chan_ImagBuffer_fx[i], l_ts, masaInput->hMasaPrerend->cldfbAnaEnc[i], &q_cldfb_out );
    8245        4800 :                 scale_factor = s_min( scale_factor, s_min( getScaleFactor32( Chan_RealBuffer_fx[i], l_ts ), getScaleFactor32( Chan_ImagBuffer_fx[i], l_ts ) ) );
    8246        4800 :                 scale_factor = sub( scale_factor, 1 );
    8247        4800 :                 scale_sig32( Chan_RealBuffer_fx[i], l_ts, scale_factor ); /* Q(q_cldfb_out + scale_factor) */
    8248        4800 :                 scale_sig32( Chan_ImagBuffer_fx[i], l_ts, scale_factor ); /* Q(q_cldfb_out + scale_factor) */
    8249        4800 :                 scale_fac_arr[i] = scale_factor;
    8250        4800 :                 move16();
    8251             :             }
    8252             : 
    8253        2400 :             scale_factor = MAX_16;
    8254        2400 :             move16();
    8255        7200 :             FOR( i = 0; i < numAnalysisChannels; i++ )
    8256             :             {
    8257        4800 :                 scale_factor = s_min( scale_factor, scale_fac_arr[i] );
    8258             :             }
    8259             : 
    8260        7200 :             FOR( i = 0; i < numAnalysisChannels; i++ )
    8261             :             {
    8262        4800 :                 IF( NE_16( scale_factor, scale_fac_arr[i] ) )
    8263             :                 {
    8264       48861 :                     FOR( j = 0; j < l_ts; j++ )
    8265             :                     {
    8266       48060 :                         Chan_RealBuffer_fx[i][j] = L_shr( Chan_RealBuffer_fx[i][j], sub( scale_fac_arr[i], scale_factor ) ); /* Q(q_cldfb_out+scale_factor) */
    8267       48060 :                         move32();
    8268       48060 :                         Chan_ImagBuffer_fx[i][j] = L_shr( Chan_ImagBuffer_fx[i][j], sub( scale_fac_arr[i], scale_factor ) ); /* Q(q_cldfb_out+scale_factor) */
    8269       48060 :                         move32();
    8270             :                     }
    8271             :                 }
    8272             :             }
    8273             : 
    8274        2400 :             Word16 q_add = sub( 31, add( scale_factor, q_cldfb_out ) );
    8275             :             /* Compute channel energy for metadata processing */
    8276       60000 :             FOR( band_m_idx = 0; band_m_idx < MASA_FREQUENCY_BANDS; band_m_idx++ )
    8277             :             {
    8278       57600 :                 brange[0] = MASA_band_grouping_24[band_m_idx];
    8279       57600 :                 move16();
    8280       57600 :                 brange[1] = MASA_band_grouping_24[band_m_idx + 1];
    8281       57600 :                 move16();
    8282      201600 :                 FOR( j = brange[0]; j < brange[1]; j++ )
    8283             :                 {
    8284      432000 :                     FOR( i = 0; i < numAnalysisChannels; i++ )
    8285             :                     {
    8286      288000 :                         Word32 temp = L_add( Mpy_32_32( Chan_RealBuffer_fx[0][j], Chan_RealBuffer_fx[0][j] ), Mpy_32_32( Chan_ImagBuffer_fx[0][j], Chan_ImagBuffer_fx[0][j] ) ); /* 2 * Q(q_cldfb_out + scale_factor) - 31 */
    8287      288000 :                         masaInput->hMasaPrerend->energy_fx[block_m_idx][band_m_idx] = BASOP_Util_Add_Mant32Exp( masaInput->hMasaPrerend->energy_fx[block_m_idx][band_m_idx], masaInput->hMasaPrerend->energy_e[block_m_idx][band_m_idx], temp, shl( q_add, 1 ), &masaInput->hMasaPrerend->energy_e[block_m_idx][band_m_idx] );
    8288      288000 :                         move32();
    8289             :                     }
    8290             :                 }
    8291             :             }
    8292             :         }
    8293             :     }
    8294             : 
    8295             :     /* Copy audio channels if mismatch in number of transports */
    8296         150 :     test();
    8297         150 :     test();
    8298         150 :     IF( EQ_16( masaInput->base.inputBuffer.config.numChannels, 1 ) && EQ_16( outAudio.config.numChannels, 2 ) )
    8299             :     {
    8300           0 :         Copy32( tmpBuffer_fx[0], tmpBuffer_fx[1], masaInput->base.inputBuffer.config.numSamplesPerChannel );
    8301             :     }
    8302         150 :     ELSE IF( EQ_16( masaInput->base.inputBuffer.config.numChannels, 2 ) && EQ_16( outAudio.config.numChannels, 1 ) )
    8303             :     {
    8304             :         //  v_add( tmpBuffer[0], tmpBuffer[1], tmpBuffer[0], masaInput->base.inputBuffer.config.numSamplesPerChannel );
    8305           0 :         v_add_fixed_no_hdrm( tmpBuffer_fx[0], tmpBuffer_fx[1], tmpBuffer_fx[0], masaInput->base.inputBuffer.config.numSamplesPerChannel );
    8306             :     }
    8307             : 
    8308             :     /* Copy metadata */
    8309         150 :     outMeta = masaInput->hMasaPrerend->hMasaOut;
    8310         150 :     inMeta = &masaInput->masaMetadata;
    8311         150 :     numDirs = add( inMeta->descriptive_meta.numberOfDirections, 1 );
    8312             : 
    8313         750 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    8314             :     {
    8315       15000 :         FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    8316             :         {
    8317             :             /* Remainder is always set to zero and energy removal is compensated in following steps
    8318             :              * to other ratios. */
    8319             :             //     inMeta->common_meta.remainder_to_total_ratio[sf][band] = 0.0f;
    8320       14400 :             inMeta->common_meta.remainder_to_total_ratio_fx[sf][band] = 0;
    8321       14400 :             move32();
    8322       14400 :             ratioSum_fx = 0;
    8323       14400 :             move32();
    8324       43200 :             FOR( dir = 0; dir < numDirs; dir++ )
    8325             :             {
    8326       28800 :                 ratioSum_fx = L_add( ratioSum_fx, inMeta->directional_meta[dir].energy_ratio_fx[sf][band] );
    8327             :             }
    8328       14400 :             ratioSum_fx = L_add( ratioSum_fx, inMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] );
    8329             : 
    8330       14400 :             IF( ratioSum_fx == 0 )
    8331             :             {
    8332           0 :                 FOR( dir = 0; dir < numDirs; dir++ )
    8333             :                 {
    8334           0 :                     inMeta->directional_meta[dir].energy_ratio_fx[sf][band] = 0;
    8335           0 :                     move32();
    8336             :                 }
    8337           0 :                 inMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = ONE_IN_Q30;
    8338           0 :                 move32();
    8339             :             }
    8340       14400 :             ELSE IF( NE_32( ratioSum_fx, ONE_IN_Q30 ) )
    8341             :             {
    8342       14400 :                 Word16 tmp_e = 0;
    8343       14400 :                 move16();
    8344       14400 :                 Word32 tmp = 0;
    8345       14400 :                 move32();
    8346       43200 :                 FOR( dir = 0; dir < numDirs; dir++ )
    8347             :                 {
    8348       28800 :                     tmp = BASOP_Util_Divide3232_Scale_newton( inMeta->directional_meta[dir].energy_ratio_fx[sf][band], ratioSum_fx, &tmp_e );
    8349       28800 :                     inMeta->directional_meta[dir].energy_ratio_fx[sf][band] = L_shl( tmp, sub( tmp_e, 1 ) ); /* Q30 */
    8350       28800 :                     move32();
    8351             :                 }
    8352       14400 :                 tmp_e = 0;
    8353       14400 :                 move16();
    8354       14400 :                 tmp = 0;
    8355       14400 :                 move32();
    8356       14400 :                 tmp = BASOP_Util_Divide3232_Scale_newton( inMeta->common_meta.diffuse_to_total_ratio_fx[sf][band], ratioSum_fx, &tmp_e );
    8357       14400 :                 inMeta->common_meta.diffuse_to_total_ratio_fx[sf][band] = L_shl( tmp, sub( tmp_e, 1 ) ); /* Q30 */
    8358       14400 :                 move32();
    8359             :             }
    8360             :         }
    8361             :     }
    8362             : 
    8363         750 :     FOR( sf = 0; sf < MAX_PARAM_SPATIAL_SUBFRAMES; sf++ )
    8364             :     {
    8365       15000 :         FOR( band = 0; band < MASA_FREQUENCY_BANDS; band++ )
    8366             :         {
    8367       14400 :             outMeta->diffuseToTotalRatio[sf][band] = UINT8_MAX;
    8368       14400 :             move16();
    8369       43200 :             FOR( dir = 0; dir < numDirs; dir++ )
    8370             :             {
    8371       28800 :                 outMeta->directionIndex[dir][sf][band] = index_theta_phi_16_fx( &inMeta->directional_meta[dir].elevation_fx[sf][band], &inMeta->directional_meta[dir].azimuth_fx[sf][band], masaInput->hMasaPrerend->sph_grid16 );
    8372       28800 :                 outMeta->directToTotalRatio[dir][sf][band] = (UWord8) L_shr( inMeta->directional_meta[dir].energy_ratio_fx[sf][band], Q22 );
    8373       28800 :                 outMeta->diffuseToTotalRatio[sf][band] = (UWord8) sub( outMeta->diffuseToTotalRatio[sf][band], outMeta->directToTotalRatio[dir][sf][band] );
    8374       28800 :                 outMeta->spreadCoherence[dir][sf][band] = (UWord8) shr( inMeta->directional_meta[dir].spread_coherence_fx[sf][band], Q7 );
    8375             : 
    8376       28800 :                 move16();
    8377       28800 :                 move16();
    8378       28800 :                 move16();
    8379       28800 :                 move16();
    8380             :             }
    8381       14400 :             outMeta->surroundCoherence[sf][band] = (UWord8) shr( inMeta->common_meta.surround_coherence_fx[sf][band], Q7 );
    8382       14400 :             move16();
    8383             :         }
    8384             :     }
    8385             : 
    8386         150 :     copy_masa_descriptive_meta_fx( &( outMeta->descriptiveMeta ), &( inMeta->descriptive_meta ) );
    8387             : 
    8388         150 :     accumulate2dArrayToBuffer_fx( tmpBuffer_fx, &outAudio );
    8389             : 
    8390         150 :     return;
    8391             : }
    8392             : 
    8393       18150 : static ivas_error renderInputMasa(
    8394             :     input_masa *masaInput,
    8395             :     const AUDIO_CONFIG outConfig,
    8396             :     IVAS_REND_AudioBuffer outAudio )
    8397             : {
    8398             :     IVAS_REND_AudioBuffer inAudio;
    8399             :     Word16 ch;
    8400             :     Word16 maxBin;
    8401             :     Word32 *tmpBuffer_fx[MAX_OUTPUT_CHANNELS];
    8402             :     Word32 tmpBuffer_buff_fx[MAX_OUTPUT_CHANNELS][L_FRAME48k];
    8403             :     Word16 cldfb2tdShift;
    8404             :     Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    8405             :     Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    8406             : 
    8407       18150 :     IF( !masaInput->metadataHasBeenFed )
    8408             :     {
    8409           0 :         return IVAS_ERR_MISSING_METADATA;
    8410             :     }
    8411             : 
    8412       18150 :     inAudio = masaInput->base.inputBuffer;
    8413             : 
    8414       18150 :     cldfb2tdShift = outAudio.config.is_cldfb ? 1 : 0;
    8415       18150 :     IF( ( NE_32( L_shl( masaInput->base.numNewSamplesPerChannel, cldfb2tdShift ), outAudio.config.numSamplesPerChannel ) ) &&
    8416             :         NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    8417             :     {
    8418           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" );
    8419             :     }
    8420       18150 :     masaInput->base.numNewSamplesPerChannel = 0;
    8421       18150 :     move32();
    8422             : 
    8423       18150 :     *outAudio.pq_fact = outAudio.q_factor;
    8424       18150 :     move16();
    8425             :     /* Apply input gain to new audio */
    8426       18150 :     v_multc_fixed( inAudio.data_fx, masaInput->base.gain_fx, inAudio.data_fx, i_mult( inAudio.config.numSamplesPerChannel, inAudio.config.numChannels ) );
    8427       18150 :     *outAudio.pq_fact = sub( *outAudio.pq_fact, 1 ); // to compensate for the qfactor reduction in gain multiplication.
    8428       18150 :     move16();
    8429             : 
    8430       18150 :     maxBin = extract_l( Mpy_32_32( *masaInput->base.ctx.pOutSampleRate, INV_CLDFB_BANDWIDTH_Q31 ) ); /* Q0 */
    8431             : 
    8432             :     /* set combined orientation subframe info to start info */
    8433       18150 :     ivas_combined_orientation_set_to_start_index( *( masaInput->base.ctx.pCombinedOrientationData ) );
    8434             : 
    8435       18150 :     IF( EQ_32( getAudioConfigType( outConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) )
    8436             :     {
    8437             :         /* MASA prerendering path for MASA -> MASA */
    8438         150 :         renderMasaToMasa( masaInput, outAudio );
    8439             :     }
    8440             :     ELSE
    8441             :     {
    8442             :         /* MASA external renderer -> other formats */
    8443             :         Word16 num_subframes, exp;
    8444      306000 :         FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ )
    8445             :         {
    8446      288000 :             tmpBuffer_fx[ch] = tmpBuffer_buff_fx[ch];
    8447             :         }
    8448       18000 :         copyBufferTo2dArray_fx( masaInput->base.inputBuffer, tmpBuffer_buff_fx );
    8449             : 
    8450       18000 :         num_subframes = BASOP_Util_Divide3232_Scale( L_mult0( masaInput->base.inputBuffer.config.numSamplesPerChannel, IVAS_NUM_FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ), *masaInput->base.ctx.pOutSampleRate, &exp );
    8451       18000 :         num_subframes = shr( num_subframes, sub( 15, exp ) ); /* Q0 */
    8452             : 
    8453       18000 :         IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) || EQ_32( outConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) )
    8454           0 :         {
    8455             :             /* split rendering. use the combined of the first subframe in all subframes */
    8456             :             Word16 sf, i, j;
    8457             :             COMBINED_ORIENTATION_HANDLE pCombinedOrientationData;
    8458           0 :             pCombinedOrientationData = *masaInput->base.ctx.pCombinedOrientationData;
    8459           0 :             FOR( sf = 1; sf < pCombinedOrientationData->num_subframes; sf++ )
    8460             :             {
    8461           0 :                 Copy_Quat_fx( &pCombinedOrientationData->Quaternions[0], &pCombinedOrientationData->Quaternions[sf] );
    8462           0 :                 FOR( i = 0; i < 3; i++ )
    8463             :                 {
    8464           0 :                     FOR( j = 0; j < 3; j++ )
    8465             :                     {
    8466           0 :                         pCombinedOrientationData->Rmat_fx[sf][i][j] = pCombinedOrientationData->Rmat_fx[0][i][j];
    8467           0 :                         move32();
    8468             :                     }
    8469             :                 }
    8470             :             }
    8471             : 
    8472           0 :             copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin );
    8473           0 :             Scale_sig32( tmpBuffer_buff_fx[0], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */
    8474           0 :             Scale_sig32( tmpBuffer_buff_fx[1], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */
    8475             :             // scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) );
    8476             : 
    8477           0 :             ivas_masa_ext_rend_parambin_render_fx( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer_fx, num_subframes, masaInput->base.ctx.pSplitRendWrapper, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural );
    8478             : 
    8479           0 :             accumulateCLDFBArrayToBuffer_fx( Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, &outAudio );
    8480             : 
    8481           0 :             *outAudio.pq_fact = Q6;
    8482           0 :             move16();
    8483             :         }
    8484             :         ELSE
    8485             :         {
    8486             :             /* non-split path */
    8487       18000 :             SWITCH( masaInput->hMasaExtRend->renderer_type )
    8488             :             {
    8489       12750 :                 case RENDERER_DIRAC:
    8490             : 
    8491       12750 :                     copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin );
    8492       12750 :                     intermidiate_ext_dirac_render( masaInput->hMasaExtRend, 1 );
    8493      123000 :                     FOR( ch = 0; ch < masaInput->hMasaExtRend->hDirACRend->hOutSetup.nchan_out_woLFE + masaInput->hMasaExtRend->hDirACRend->hOutSetup.num_lfe; ch++ )
    8494             :                     {
    8495      110250 :                         masaInput->hMasaExtRend->cldfbAnaRend[0]->Q_cldfb_state = Q11;
    8496      110250 :                         move16();
    8497             :                     }
    8498      216750 :                     FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ )
    8499             :                     {
    8500      204000 :                         Scale_sig32( tmpBuffer_buff_fx[ch], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */
    8501             :                     }
    8502             : 
    8503       12750 :                     scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) ); /* Q11 */
    8504             : 
    8505       12750 :                     ivas_masa_ext_dirac_render_fx( masaInput->hMasaExtRend, tmpBuffer_fx, num_subframes );
    8506             : 
    8507       12750 :                     *outAudio.pq_fact = Q11;
    8508       12750 :                     move16();
    8509             : 
    8510      123000 :                     FOR( ch = 0; ch < masaInput->hMasaExtRend->hDirACRend->hOutSetup.nchan_out_woLFE + masaInput->hMasaExtRend->hDirACRend->hOutSetup.num_lfe; ch++ )
    8511             :                     {
    8512      110250 :                         scale_sig32( masaInput->hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, masaInput->hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, masaInput->hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state ) ); /* Q11 */
    8513      110250 :                         masaInput->hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11;
    8514      110250 :                         move16();
    8515             :                     }
    8516             : 
    8517       12750 :                     intermidiate_ext_dirac_render( masaInput->hMasaExtRend, 0 );
    8518       12750 :                     BREAK;
    8519        4500 :                 case RENDERER_STEREO_PARAMETRIC:
    8520             :                 case RENDERER_BINAURAL_PARAMETRIC:
    8521             :                 case RENDERER_BINAURAL_PARAMETRIC_ROOM:
    8522             : 
    8523        4500 :                     copyMasaMetadataToDiracRenderer_fx( &masaInput->masaMetadata, masaInput->hMasaExtRend->hSpatParamRendCom, maxBin );
    8524             : 
    8525        4500 :                     Scale_sig32( tmpBuffer_buff_fx[0], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */
    8526        4500 :                     Scale_sig32( tmpBuffer_buff_fx[1], L_FRAME48k, sub( Q11, *outAudio.pq_fact ) ); /* Q11 */
    8527             : 
    8528        4500 :                     scale_sig32( outAudio.data_fx, i_mult( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ), sub( Q11, *outAudio.pq_fact ) );
    8529             : 
    8530        4500 :                     ivas_masa_ext_rend_parambin_render_fx( masaInput->hMasaExtRend, *masaInput->base.ctx.pCombinedOrientationData, tmpBuffer_fx, num_subframes, NULL, NULL, NULL );
    8531        4500 :                     *outAudio.pq_fact = Q11;
    8532        4500 :                     move16();
    8533        4500 :                     BREAK;
    8534         750 :                 case RENDERER_DISABLE:
    8535         750 :                     BREAK; /* This happens for 1TC MASA to MONO where we just copy input transport to output */
    8536           0 :                 default:
    8537           0 :                     return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) );
    8538             :             }
    8539       18000 :             accumulate2dArrayToBuffer_fx( tmpBuffer_buff_fx, &outAudio );
    8540             :         }
    8541             :     }
    8542             : 
    8543       18150 :     return IVAS_ERR_OK;
    8544             : }
    8545             : 
    8546             : 
    8547     1126140 : static ivas_error renderActiveInputsMasa(
    8548             :     IVAS_REND_HANDLE hIvasRend,
    8549             :     IVAS_REND_AudioBuffer outAudio )
    8550             : {
    8551             :     Word16 i;
    8552             :     input_masa *pCurrentInput;
    8553             :     ivas_error error;
    8554             : 
    8555     2252280 :     FOR( ( i = 0, pCurrentInput = hIvasRend->inputsMasa ); i < RENDERER_MAX_MASA_INPUTS; ( ++i, ++pCurrentInput ) )
    8556             :     {
    8557     1126140 :         IF( EQ_16( pCurrentInput->base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8558             :         {
    8559             :             /* Skip inactive inputs */
    8560     1107990 :             CONTINUE;
    8561             :         }
    8562             : 
    8563       18150 :         *outAudio.pq_fact = outAudio.q_factor;
    8564       18150 :         move16();
    8565             : 
    8566       18150 :         IF( NE_32( ( error = renderInputMasa( pCurrentInput, hIvasRend->outputConfig, outAudio ) ), IVAS_ERR_OK ) )
    8567             :         {
    8568           0 :             return error;
    8569             :         }
    8570             :     }
    8571             : 
    8572     1126140 :     return IVAS_ERR_OK;
    8573             : }
    8574             : 
    8575             : 
    8576             : /*---------------------------------------------------------------------*
    8577             :  * IVAS_REND_GetMasaMetadata( )
    8578             :  *
    8579             :  * Get metadata of the estimated MASA frame
    8580             :  *---------------------------------------------------------------------*/
    8581             : 
    8582           0 : ivas_error IVAS_REND_GetMasaMetadata(
    8583             :     IVAS_REND_HANDLE hIvasRend,                        /* i/o: IVAS renderer handle                                                    */
    8584             :     MASA_DECODER_EXT_OUT_META_HANDLE *hMasaExtOutMeta, /* o  : pointer to handle, which will be set to point to analyzed MASA metadata */
    8585             :     const IVAS_REND_AudioConfigType inputType          /* i  : Input type                                                              */
    8586             : )
    8587             : {
    8588           0 :     IF( hIvasRend == NULL )
    8589             :     {
    8590           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    8591             :     }
    8592             : 
    8593             :     /* Get the metadata handle */
    8594           0 :     IF( EQ_32( inputType, IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) )
    8595             :     {
    8596           0 :         *hMasaExtOutMeta = hIvasRend->inputsIsm->hOMasa->hMasaOut;
    8597             :     }
    8598           0 :     ELSE IF( EQ_32( inputType, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    8599             :     {
    8600           0 :         *hMasaExtOutMeta = hIvasRend->inputsMc->hMcMasa->hMasaOut;
    8601             :     }
    8602           0 :     ELSE IF( EQ_32( inputType, IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) )
    8603             :     {
    8604           0 :         *hMasaExtOutMeta = hIvasRend->inputsSba->hDirAC->hMasaOut;
    8605             :     }
    8606             :     ELSE
    8607             :     {
    8608           0 :         return IVAS_ERR_NOT_SUPPORTED_OPTION;
    8609             :     }
    8610             : 
    8611           0 :     return IVAS_ERR_OK;
    8612             : }
    8613             : 
    8614             : 
    8615             : /*---------------------------------------------------------------------*
    8616             :  * IVAS_REND_MergeMasaMetadata( )
    8617             :  *
    8618             :  * Merge MASA metadata from two formats
    8619             :  *---------------------------------------------------------------------*/
    8620             : 
    8621         450 : ivas_error IVAS_REND_MergeMasaMetadata(
    8622             :     IVAS_REND_HANDLE hIvasRend,                        /* i/o: IVAS renderer handle                                             */
    8623             :     MASA_DECODER_EXT_OUT_META_HANDLE *hMasaExtOutMeta, /* o  : pointer to handle, which will be set to point to merged metadata */
    8624             :     const IVAS_REND_AudioConfigType inputType1,        /* i  : Input type 1                                                     */
    8625             :     const IVAS_REND_AudioConfigType inputType2         /* i  : Input type 2                                                     */
    8626             : )
    8627             : {
    8628             :     MASA_DECODER_EXT_OUT_META_HANDLE inMeta2;
    8629             :     Word32( *inEne1_fx )[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    8630             :     Word32( *inEne2_fx )[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    8631             :     Word16( *inEne1_e )[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    8632             :     Word16( *inEne2_e )[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS];
    8633             : 
    8634         450 :     IF( hIvasRend == NULL )
    8635             :     {
    8636           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    8637             :     }
    8638             : 
    8639             :     /* Input1 metadata and energy */
    8640         450 :     IF( EQ_32( inputType1, IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) )
    8641             :     {
    8642             : 
    8643           0 :         *hMasaExtOutMeta = hIvasRend->inputsIsm->hOMasa->hMasaOut;
    8644           0 :         inEne1_fx = &( hIvasRend->inputsIsm->hOMasa->energy_fx );
    8645           0 :         inEne1_e = &( hIvasRend->inputsIsm->hOMasa->energy_e );
    8646             :     }
    8647         450 :     ELSE IF( EQ_32( inputType1, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    8648             :     {
    8649             : 
    8650           0 :         *hMasaExtOutMeta = hIvasRend->inputsMc->hMcMasa->hMasaOut;
    8651           0 :         inEne1_fx = &( hIvasRend->inputsMc->hMcMasa->energy_fx );
    8652           0 :         inEne1_e = &( hIvasRend->inputsMc->hMcMasa->energy_e );
    8653             :     }
    8654         450 :     ELSE IF( EQ_32( inputType1, IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) )
    8655             :     {
    8656             : 
    8657         450 :         *hMasaExtOutMeta = hIvasRend->inputsSba->hDirAC->hMasaOut;
    8658         450 :         inEne1_fx = &( hIvasRend->inputsSba->hDirAC->energy_fx );
    8659         450 :         inEne1_e = &( hIvasRend->inputsSba->hDirAC->energy_e );
    8660             :     }
    8661           0 :     ELSE IF( EQ_32( inputType1, IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) )
    8662             :     {
    8663             : 
    8664           0 :         *hMasaExtOutMeta = hIvasRend->inputsMasa->hMasaPrerend->hMasaOut;
    8665           0 :         inEne1_fx = &( hIvasRend->inputsMasa->hMasaPrerend->energy_fx );
    8666           0 :         inEne1_e = &( hIvasRend->inputsMasa->hMasaPrerend->energy_e );
    8667             :     }
    8668             :     ELSE
    8669             :     {
    8670           0 :         return IVAS_ERR_NOT_SUPPORTED_OPTION;
    8671             :     }
    8672             : 
    8673             :     /* Input2 metadata and energy */
    8674         450 :     IF( EQ_32( inputType2, IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) )
    8675             :     {
    8676         150 :         inMeta2 = hIvasRend->inputsIsm->hOMasa->hMasaOut;
    8677         150 :         inEne2_fx = &( hIvasRend->inputsIsm->hOMasa->energy_fx );
    8678         150 :         inEne2_e = &( hIvasRend->inputsIsm->hOMasa->energy_e );
    8679             :     }
    8680         300 :     ELSE IF( EQ_32( inputType2, IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) )
    8681             :     {
    8682         150 :         inMeta2 = hIvasRend->inputsMc->hMcMasa->hMasaOut;
    8683         150 :         inEne2_fx = &( hIvasRend->inputsMc->hMcMasa->energy_fx );
    8684         150 :         inEne2_e = &( hIvasRend->inputsMc->hMcMasa->energy_e );
    8685             :     }
    8686         150 :     ELSE IF( EQ_32( inputType2, IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) )
    8687             :     {
    8688           0 :         inMeta2 = hIvasRend->inputsSba->hDirAC->hMasaOut;
    8689           0 :         inEne2_fx = &( hIvasRend->inputsSba->hDirAC->energy_fx );
    8690           0 :         inEne2_e = &( hIvasRend->inputsSba->hDirAC->energy_e );
    8691             :     }
    8692         150 :     ELSE IF( EQ_32( inputType2, IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) )
    8693             :     {
    8694             : 
    8695         150 :         inMeta2 = hIvasRend->inputsMasa->hMasaPrerend->hMasaOut;
    8696         150 :         inEne2_fx = &( hIvasRend->inputsMasa->hMasaPrerend->energy_fx );
    8697         150 :         inEne2_e = &( hIvasRend->inputsMasa->hMasaPrerend->energy_e );
    8698             :     }
    8699             :     ELSE
    8700             :     {
    8701           0 :         return IVAS_ERR_NOT_SUPPORTED_OPTION;
    8702             :     }
    8703             : 
    8704             :     /* Merge metadata */
    8705         450 :     ivas_prerend_merge_masa_metadata_fx( *hMasaExtOutMeta, *hMasaExtOutMeta, inputType1, *inEne1_fx, *inEne1_e, inMeta2, inputType2, *inEne2_fx, *inEne2_e );
    8706             : 
    8707             : 
    8708         450 :     IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_MASA1 ) )
    8709             :     {
    8710           0 :         ( *hMasaExtOutMeta )->descriptiveMeta.numberOfChannels = 0u;
    8711           0 :         move16();
    8712             :     }
    8713             :     ELSE
    8714             :     {
    8715         450 :         ( *hMasaExtOutMeta )->descriptiveMeta.numberOfChannels = 1u;
    8716         450 :         move16();
    8717             :     }
    8718             : 
    8719         450 :     return IVAS_ERR_OK;
    8720             : }
    8721             : 
    8722             : 
    8723             : /*---------------------------------------------------------------------*
    8724             :  * IVAS_REND_SetTotalNumberOfObjects( )
    8725             :  *
    8726             :  * Set the total number of objects to the first object data
    8727             :  *---------------------------------------------------------------------*/
    8728             : 
    8729         182 : ivas_error IVAS_REND_SetTotalNumberOfObjects(
    8730             :     IVAS_REND_HANDLE hIvasRend,     /* i/o: IVAS renderer handle    */
    8731             :     const UWord16 total_num_objects /* i  : total number of objects */
    8732             : )
    8733             : {
    8734         182 :     IF( hIvasRend == NULL )
    8735             :     {
    8736           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    8737             :     }
    8738             : 
    8739         182 :     hIvasRend->inputsIsm[0].total_num_objects = total_num_objects;
    8740         182 :     move16();
    8741             : 
    8742         182 :     return IVAS_ERR_OK;
    8743             : }
    8744             : 
    8745             : 
    8746             : /*---------------------------------------------------------------------*
    8747             :  * IVAS_REND_SetIsmMetadataDelay( )
    8748             :  *
    8749             :  * Set the Metadata Delay in ms in order to sync with audio delay
    8750             :  *---------------------------------------------------------------------*/
    8751             : 
    8752         182 : ivas_error IVAS_REND_SetIsmMetadataDelay(
    8753             :     IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle                                */
    8754             :     const Word32 sync_md_delay  /* i  : ISM Metadata Delay in ms to sync with audio delay   */
    8755             : )
    8756             : {
    8757             :     Word16 i;
    8758             : 
    8759         182 :     IF( hIvasRend == NULL )
    8760             :     {
    8761           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    8762             :     }
    8763         910 :     FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i )
    8764             :     {
    8765         728 :         hIvasRend->inputsIsm[i].ism_metadata_delay_ms_fx = sync_md_delay;
    8766         728 :         move32();
    8767             :     }
    8768             : 
    8769         182 :     return IVAS_ERR_OK;
    8770             : }
    8771             : 
    8772             : 
    8773             : /*-------------------------------------------------------------------*
    8774             :  * getSamplesInternal()
    8775             :  *
    8776             :  *
    8777             :  *-------------------------------------------------------------------*/
    8778             : 
    8779     1126140 : static ivas_error getSamplesInternal(
    8780             :     IVAS_REND_HANDLE hIvasRend,      /* i/o: Renderer handle                                                */
    8781             :     IVAS_REND_AudioBuffer outAudio,  /* i/o: buffer for output audio                                        */
    8782             :     IVAS_REND_BitstreamBuffer *hBits /* i/o: buffer for input/output bitstream. Needed in split rendering   */
    8783             : )
    8784             : {
    8785             :     ivas_error error;
    8786             :     Word16 numOutChannels;
    8787             :     Word16 cldfb2tdSampleShift;
    8788             :     IVAS_REND_AudioBuffer outAudioOrig;
    8789             : 
    8790             :     /* Validate function arguments */
    8791     1126140 :     test();
    8792     1126140 :     IF( hIvasRend == NULL || outAudio.data_fx == NULL )
    8793             :     {
    8794           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    8795             :     }
    8796             : 
    8797     1126140 :     test();
    8798     1126140 :     cldfb2tdSampleShift = ( outAudio.config.is_cldfb ) ? 1 : 0;
    8799             : 
    8800     1126140 :     IF( outAudio.config.numSamplesPerChannel <= 0 || ( MAX_BUFFER_LENGTH_PER_CHANNEL < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 0 ) ||
    8801             :         ( ( shl( MAX_BUFFER_LENGTH_PER_CHANNEL, cldfb2tdSampleShift ) ) < outAudio.config.numSamplesPerChannel && outAudio.config.is_cldfb == 1 ) )
    8802             :     {
    8803           0 :         return IVAS_ERR_INVALID_BUFFER_SIZE;
    8804             :     }
    8805             : 
    8806     1126140 :     test();
    8807     1126140 :     IF( LE_16( outAudio.config.numChannels, 0 ) || LT_16( MAX_OUTPUT_CHANNELS, outAudio.config.numChannels ) )
    8808             :     {
    8809           0 :         return IVAS_ERR_WRONG_NUM_CHANNELS;
    8810             :     }
    8811             : 
    8812     1126140 :     test();
    8813     1126140 :     test();
    8814     1126140 :     test();
    8815     1126140 :     IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_BINAURAL ) &&
    8816             :         NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) &&
    8817             :         NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) &&
    8818             :         NE_32( L_shr( L_mult0( outAudio.config.numSamplesPerChannel, 1000 ), cldfb2tdSampleShift ),
    8819             :                imult3216( hIvasRend->sampleRateOut, i_mult( hIvasRend->num_subframes, BINAURAL_RENDERING_FRAME_SIZE_MS ) ) ) )
    8820             :     {
    8821           0 :         return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Binaural rendering requires specific frame size" );
    8822             :     }
    8823             : 
    8824             :     /* Check that there is allowed configuration for MASA format output */
    8825     1126140 :     IF( EQ_32( getAudioConfigType( hIvasRend->outputConfig ), IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) )
    8826             :     {
    8827             :         Word16 i;
    8828         150 :         Word16 numMasaInputs = 0;
    8829         150 :         move16();
    8830         150 :         Word16 numOtherInputs = 0;
    8831         150 :         move16();
    8832             : 
    8833         300 :         FOR( i = 0; i < RENDERER_MAX_MASA_INPUTS; i++ )
    8834             :         {
    8835             :             // numMasaInputs += hIvasRend->inputsMasa[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID ? 0 : 1;
    8836             : 
    8837         150 :             IF( EQ_32( hIvasRend->inputsMasa[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8838             :             {
    8839           0 :                 numMasaInputs = add( numMasaInputs, 0 );
    8840             :             }
    8841             :             ELSE
    8842             :             {
    8843         150 :                 numMasaInputs = add( numMasaInputs, 1 );
    8844             :             }
    8845             :         }
    8846             : 
    8847         300 :         FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; i++ )
    8848             :         {
    8849             :             // numOtherInputs += hIvasRend->inputsMc[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID ? 0 : 1;
    8850             : 
    8851         150 :             IF( EQ_32( hIvasRend->inputsMc[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8852             :             {
    8853           0 :                 numOtherInputs = add( numOtherInputs, 0 );
    8854             :             }
    8855             :             ELSE
    8856             :             {
    8857         150 :                 numOtherInputs = add( numOtherInputs, 1 );
    8858             :             }
    8859             :         }
    8860             : 
    8861         300 :         FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; i++ )
    8862             :         {
    8863             :             // numOtherInputs += hIvasRend->inputsSba[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID ? 0 : 1;
    8864             : 
    8865         150 :             IF( EQ_32( hIvasRend->inputsSba[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8866             :             {
    8867           0 :                 numOtherInputs = add( numOtherInputs, 0 );
    8868             :             }
    8869             :             ELSE
    8870             :             {
    8871         150 :                 numOtherInputs = add( numOtherInputs, 1 );
    8872             :             }
    8873             :         }
    8874             : 
    8875             :         /* For ISM, we check only first as all ISMs are handled together via OMASA when merging to MASA. */
    8876             :         // numOtherInputs += hIvasRend->inputsIsm[0].base.inConfig == IVAS_AUDIO_CONFIG_INVALID ? 0 : 1;
    8877         150 :         IF( EQ_32( hIvasRend->inputsIsm[0].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8878             :         {
    8879           0 :             numOtherInputs = add( numOtherInputs, 0 );
    8880             :         }
    8881             :         ELSE
    8882             :         {
    8883         150 :             numOtherInputs = add( numOtherInputs, 1 );
    8884             :         }
    8885             : 
    8886         150 :         test();
    8887         150 :         IF( numMasaInputs == 0 || numOtherInputs == 0 )
    8888             :         {
    8889           0 :             return IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED;
    8890             :         }
    8891             :     }
    8892             : 
    8893     1126140 :     IF( NE_32( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ), IVAS_ERR_OK ) )
    8894             :     {
    8895           0 :         return error;
    8896             :     }
    8897             : 
    8898     1126140 :     IF( NE_16( numOutChannels, outAudio.config.numChannels ) && NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    8899             :     {
    8900           0 :         return IVAS_ERR_WRONG_NUM_CHANNELS;
    8901             :     }
    8902             : 
    8903             :     /* Clear original output buffer */
    8904     1126140 :     set32_fx( outAudio.data_fx, 0, imult1616( outAudio.config.numChannels, outAudio.config.numSamplesPerChannel ) );
    8905             : 
    8906     1126140 :     outAudioOrig = outAudio;
    8907             : 
    8908             :     /* Use internal buffer if outputting split rendering bitstream */
    8909     1126140 :     test();
    8910     1126140 :     IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ||
    8911             :         EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    8912             :     {
    8913             :         Word16 num_poses_orig;
    8914           0 :         num_poses_orig = hIvasRend->splitRendWrapper->multiBinPoseData.num_poses;
    8915           0 :         move16();
    8916           0 :         outAudio.config = hIvasRend->splitRendEncBuffer.config;
    8917           0 :         outAudio.data_fx = hIvasRend->splitRendEncBuffer.data_fx;
    8918             : 
    8919           0 :         ISAR_PRE_REND_GetMultiBinPoseData( &hIvasRend->hRendererConfig->split_rend_config, &hIvasRend->splitRendWrapper->multiBinPoseData, hIvasRend->headRotData.sr_pose_pred_axis );
    8920             : 
    8921           0 :         assert( num_poses_orig == hIvasRend->splitRendWrapper->multiBinPoseData.num_poses && "number of poses should not change dynamically" );
    8922             : 
    8923             :         /* Clear output buffer for split rendering bitstream */
    8924           0 :         set32_fx( outAudio.data_fx, 0, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel );
    8925             :     }
    8926             : 
    8927     1126140 :     IF( NE_32( ( error = renderActiveInputsIsm( hIvasRend, outAudio ) ), IVAS_ERR_OK ) )
    8928             :     {
    8929           0 :         return error;
    8930             :     }
    8931     1126140 :     IF( NE_32( ( error = renderActiveInputsMc( hIvasRend, outAudio ) ), IVAS_ERR_OK ) )
    8932             :     {
    8933           0 :         return error;
    8934             :     }
    8935     1126140 :     IF( NE_32( ( error = renderActiveInputsSba( hIvasRend, outAudio ) ), IVAS_ERR_OK ) )
    8936             :     {
    8937           0 :         return error;
    8938             :     }
    8939     1126140 :     IF( NE_32( ( error = renderActiveInputsMasa( hIvasRend, outAudio ) ), IVAS_ERR_OK ) )
    8940             :     {
    8941           0 :         return error;
    8942             :     }
    8943             : 
    8944     1126140 :     test();
    8945     1126140 :     IF( EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
    8946             :     {
    8947             :         ISAR_SPLIT_REND_BITS_DATA bits;
    8948             :         Word16 cldfb_in_flag, i, j, k, ch, ro_md_flag;
    8949             :         Word32 Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    8950             :         Word32 Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX];
    8951             : 
    8952           0 :         FOR( i = 0; i < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; i++ )
    8953             :         {
    8954           0 :             FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ )
    8955             :             {
    8956           0 :                 FOR( k = 0; k < CLDFB_NO_CHANNELS_MAX; k++ )
    8957             :                 {
    8958           0 :                     Cldfb_RealBuffer_Binaural[i][j][k] = 0;
    8959           0 :                     Cldfb_ImagBuffer_Binaural[i][j][k] = 0;
    8960           0 :                     move32();
    8961           0 :                     move32();
    8962             :                 }
    8963             :             }
    8964             :         }
    8965             : 
    8966             :         Word32 *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k];
    8967             : 
    8968           0 :         FOR( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ )
    8969             :         {
    8970           0 :             tmpBinaural[ch] = tmpBinaural_buff[ch];
    8971           0 :             move32();
    8972             :         }
    8973             : 
    8974           0 :         IF( EQ_16( outAudio.config.is_cldfb, 1 ) )
    8975             :         {
    8976           0 :             cldfb_in_flag = 1;
    8977           0 :             move16();
    8978           0 :             copyBufferToCLDFBarray_fx( outAudio, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural );
    8979             :         }
    8980             :         ELSE
    8981             :         {
    8982           0 :             cldfb_in_flag = 0;
    8983           0 :             move16();
    8984           0 :             copyBufferTo2dArray_fx( outAudio, tmpBinaural_buff );
    8985             :         }
    8986             : 
    8987             :         /* Encode split rendering bitstream */
    8988           0 :         convertBitsBufferToInternalBitsBuff( *hBits, &bits );
    8989             : 
    8990           0 :         ro_md_flag = 0;
    8991           0 :         move16();
    8992           0 :         FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i )
    8993             :         {
    8994           0 :             IF( NE_32( hIvasRend->inputsIsm[i].base.inConfig, IVAS_AUDIO_CONFIG_INVALID ) )
    8995             :             {
    8996           0 :                 ro_md_flag = 1;
    8997           0 :                 move16();
    8998           0 :                 break;
    8999             :             }
    9000             :         }
    9001             : 
    9002           0 :         Word16 q1 = 31, q2 = 31, Q_buff;
    9003             :         Word16 Q_out[CLDFB_NO_COL_MAX];
    9004           0 :         Q_out[0] = 31;
    9005           0 :         Word16 num_poses = hIvasRend->splitRendWrapper->multiBinPoseData.num_poses;
    9006             : 
    9007           0 :         for ( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ )
    9008             :         {
    9009           0 :             for ( j = 0; j < CLDFB_NO_COL_MAX; j++ )
    9010             :             {
    9011           0 :                 q1 = s_min( q1, L_norm_arr( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) );
    9012           0 :                 q2 = s_min( q2, L_norm_arr( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX ) );
    9013             :             }
    9014             :         }
    9015           0 :         Q_buff = s_min( q1, q2 );
    9016           0 :         for ( i = 0; i < num_poses * BINAURAL_CHANNELS; i++ )
    9017             :         {
    9018           0 :             for ( j = 0; j < CLDFB_NO_COL_MAX; j++ )
    9019             :             {
    9020           0 :                 scale_sig32( Cldfb_RealBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff );
    9021           0 :                 scale_sig32( Cldfb_ImagBuffer_Binaural[i][j], CLDFB_NO_CHANNELS_MAX, Q_buff );
    9022             :             }
    9023             :         }
    9024           0 :         Q_buff = Q_buff + *outAudio.pq_fact;
    9025             : 
    9026           0 :         IF( EQ_16( cldfb_in_flag, 0 ) )
    9027             :         {
    9028             :             /*TD input*/
    9029           0 :             num_poses = hIvasRend->splitRendWrapper->multiBinPoseData.num_poses;
    9030             : 
    9031           0 :             FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i )
    9032             :             {
    9033           0 :                 Q_out[0] = s_min( Q_out[0], L_norm_arr( tmpBinaural_buff[i], L_FRAME48k ) );
    9034             :             }
    9035             : 
    9036           0 :             FOR( i = 0; i < num_poses * BINAURAL_CHANNELS; ++i )
    9037             :             {
    9038           0 :                 scale_sig32( tmpBinaural_buff[i], L_FRAME48k, Q_out[0] );
    9039             :             }
    9040             : 
    9041           0 :             Q_out[0] = Q_out[0] + *outAudio.pq_fact;
    9042             :         }
    9043             : 
    9044           0 :         if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( hIvasRend->splitRendWrapper, hIvasRend->headRotData.headPositions[0], hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, hIvasRend->hRendererConfig->split_rend_config.codec,
    9045           0 :                                                               hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms,
    9046           0 :                                                               hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms,
    9047           0 :                                                               &bits, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, ( const Word16 )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, 1, cldfb_in_flag, ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, ro_md_flag, Q_buff, &Q_out[0] ) ) != IVAS_ERR_OK )
    9048             :         {
    9049           0 :             return error;
    9050             :         }
    9051             : 
    9052           0 :         Word16 pcm_out_flag = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0;
    9053           0 :         IF( NE_16( pcm_out_flag, 0 ) )
    9054             :         {
    9055           0 :             FOR( j = 0; j < BINAURAL_CHANNELS; j++ )
    9056             :             {
    9057           0 :                 scale_sig32( tmpBinaural_buff[j], L_FRAME48k, sub( *outAudio.pq_fact, Q_out[j] ) ); // *outAudio.pq_fact
    9058             :             }
    9059             :         }
    9060             : 
    9061           0 :         convertInternalBitsBuffToBitsBuffer( hBits, bits );
    9062             : 
    9063             :         /* reset to outAudioOrig in case of PCM output */
    9064           0 :         outAudio.config = outAudioOrig.config;
    9065           0 :         outAudio.data_fx = outAudioOrig.data_fx;
    9066             : 
    9067           0 :         IF( NE_16( pcm_out_flag, 0 ) )
    9068             :         {
    9069           0 :             accumulate2dArrayToBuffer_fx( tmpBinaural_buff, &outAudio );
    9070             :         }
    9071             :     }
    9072             : 
    9073     1126140 :     if ( outAudio.config.is_cldfb == 0 )
    9074             :     {
    9075     1126140 :         Word32 limiter_thresold = L_lshl( IVAS_LIMITER_THRESHOLD, *outAudio.pq_fact );
    9076             : #ifndef DISABLE_LIMITER
    9077     1126140 :         limitRendererOutput_fx( hIvasRend->hLimiter, outAudio.data_fx, outAudio.config.numSamplesPerChannel, limiter_thresold, *outAudio.pq_fact );
    9078             : #endif
    9079             :     }
    9080             : 
    9081             :     /* update global cominbed orientation start index */
    9082     1126140 :     ivas_combined_orientation_update_start_index( hIvasRend->hCombinedOrientationData, outAudio.config.numSamplesPerChannel );
    9083             : 
    9084     1126140 :     return IVAS_ERR_OK;
    9085             : }
    9086             : 
    9087             : 
    9088             : /*-------------------------------------------------------------------*
    9089             :  * IVAS_REND_GetSamples()
    9090             :  *
    9091             :  *
    9092             :  *-------------------------------------------------------------------*/
    9093             : 
    9094     1126140 : ivas_error IVAS_REND_GetSamples(
    9095             :     IVAS_REND_HANDLE hIvasRend,    /* i/o: Renderer handle          */
    9096             :     IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio  */
    9097             : )
    9098             : {
    9099     1126140 :     return getSamplesInternal( hIvasRend, outAudio, NULL );
    9100             : }
    9101             : 
    9102             : 
    9103             : /*-------------------------------------------------------------------*
    9104             :  * IVAS_REND_GetSplitBinauralBitstream()
    9105             :  *
    9106             :  *
    9107             :  *-------------------------------------------------------------------*/
    9108             : 
    9109           0 : ivas_error IVAS_REND_GetSplitBinauralBitstream(
    9110             :     IVAS_REND_HANDLE hIvasRend,      /* i/o: Renderer handle             */
    9111             :     IVAS_REND_AudioBuffer outAudio,  /* i/o: buffer for output audio     */
    9112             :     IVAS_REND_BitstreamBuffer *hBits /* o  : buffer for output bitstream */
    9113             : )
    9114             : {
    9115             :     Word16 cldfb_in_flag;
    9116             : 
    9117           0 :     cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN );
    9118           0 :     hIvasRend->splitRendEncBuffer.config.is_cldfb = cldfb_in_flag;
    9119             : 
    9120           0 :     if ( hIvasRend->hRendererConfig->split_rend_config.dof == 0 || hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE )
    9121             :     {
    9122           0 :         hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = outAudio.config.numSamplesPerChannel;
    9123             :     }
    9124             :     else
    9125             :     {
    9126           0 :         hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = (Word16) ( hIvasRend->sampleRateOut / FRAMES_PER_SEC );
    9127             :     }
    9128             : 
    9129           0 :     hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel *= cldfb_in_flag ? 2 : 1;
    9130             : 
    9131             :     /* hIvasRend->splitRendEncBuffer used for BINAURAL_SPLIT_CODED output
    9132             :            outAudio used for BINAURAL_SPLIT_PCM output */
    9133           0 :     return getSamplesInternal( hIvasRend, outAudio, hBits );
    9134             : }
    9135             : 
    9136             : 
    9137             : /*-------------------------------------------------------------------*
    9138             :  * IVAS_REND_GetSplitRendBitstreamHeader()
    9139             :  *
    9140             :  *
    9141             :  *-------------------------------------------------------------------*/
    9142             : 
    9143           0 : ivas_error IVAS_REND_GetSplitRendBitstreamHeader(
    9144             :     IVAS_REND_HANDLE hIvasRend,                           /* i/o: IVAS renderer handle                  */
    9145             :     ISAR_SPLIT_REND_CODEC *pCodec,                        /* o  : pointer to codec setting              */
    9146             :     ISAR_SPLIT_REND_POSE_CORRECTION_MODE *poseCorrection, /* o  : pointer to pose correction mode       */
    9147             :     Word16 *pCodec_frame_size_ms,                         /* o  : pointer to codec frame size setting   */
    9148             :     Word16 *pIsar_frame_size_ms                           /* o  : pointer to ISAR frame size setting    */
    9149             : )
    9150             : {
    9151           0 :     test();
    9152           0 :     IF( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL )
    9153             :     {
    9154           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    9155             :     }
    9156             : 
    9157           0 :     *pCodec = hIvasRend->hRendererConfig->split_rend_config.codec;
    9158           0 :     *pCodec_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms;
    9159           0 :     *pIsar_frame_size_ms = hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms;
    9160           0 :     *poseCorrection = hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode;
    9161             : 
    9162           0 :     return IVAS_ERR_OK;
    9163             : }
    9164             : 
    9165             : 
    9166             : /*-------------------------------------------------------------------*
    9167             :  * IVAS_REND_Close()
    9168             :  *
    9169             :  *
    9170             :  *-------------------------------------------------------------------*/
    9171             : 
    9172         666 : void IVAS_REND_Close(
    9173             :     IVAS_REND_HANDLE *phIvasRend /* i/o: Pointer to renderer handle */
    9174             : )
    9175             : {
    9176             :     UWord16 i;
    9177             :     IVAS_REND_HANDLE hIvasRend;
    9178             : 
    9179             :     /* Validate function arguments */
    9180         666 :     test();
    9181         666 :     IF( phIvasRend == NULL || *phIvasRend == NULL )
    9182             :     {
    9183           0 :         return;
    9184             :     }
    9185         666 :     hIvasRend = *phIvasRend;
    9186             : 
    9187         666 :     IF( hIvasRend->efapOutWrapper.hEfap != NULL )
    9188             :     {
    9189         471 :         efap_free_data_fx( &hIvasRend->efapOutWrapper.hEfap );
    9190             :     }
    9191             : 
    9192             :     /* clear inputs */
    9193        3330 :     FOR( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i )
    9194             :     {
    9195        2664 :         clearInputIsm( &hIvasRend->inputsIsm[i] );
    9196             :     }
    9197        1332 :     FOR( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i )
    9198             :     {
    9199         666 :         clearInputMc( &hIvasRend->inputsMc[i] );
    9200             :     }
    9201        1332 :     FOR( i = 0; i < RENDERER_MAX_SBA_INPUTS; ++i )
    9202             :     {
    9203         666 :         clearInputSba( &hIvasRend->inputsSba[i] );
    9204             :     }
    9205        1332 :     FOR( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i )
    9206             :     {
    9207         666 :         clearInputMasa( &hIvasRend->inputsMasa[i] );
    9208             :     }
    9209             : 
    9210             :     /* clear Config. Renderer */
    9211         666 :     ivas_render_config_close( &( hIvasRend->hRendererConfig ) );
    9212             : 
    9213         666 :     ivas_limiter_close_fx( &hIvasRend->hLimiter );
    9214             : 
    9215             :     /* Split binaural rendering */
    9216         666 :     IF( hIvasRend->splitRendWrapper != NULL )
    9217             :     {
    9218           0 :         ISAR_PRE_REND_close( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer );
    9219           0 :         free( hIvasRend->splitRendWrapper );
    9220           0 :         hIvasRend->splitRendWrapper = NULL;
    9221             :     }
    9222             : 
    9223         666 :     closeHeadRotation( hIvasRend );
    9224             : 
    9225         666 :     ivas_external_orientation_close_fx( &hIvasRend->hExternalOrientationData );
    9226         666 :     ivas_combined_orientation_close_fx( &hIvasRend->hCombinedOrientationData );
    9227             : 
    9228             :     /* Fastconv HRTF memories */
    9229         666 :     ivas_binaural_hrtf_close( &hIvasRend->hHrtfs.hHrtfFastConv );
    9230             : 
    9231             :     /* Parametric binauralizer HRTF filters */
    9232         666 :     ivas_HRTF_binary_close_fx( &( hIvasRend->hHrtfs.hHrtfTD ) );
    9233         666 :     ivas_HRTF_CRend_binary_close_fx( &( hIvasRend->hHrtfs.hSetOfHRTF ) );
    9234         666 :     ivas_HRTF_fastconv_binary_close_fx( &( hIvasRend->hHrtfs.hHrtfFastConv ) );
    9235         666 :     ivas_HRTF_parambin_binary_close_fx( &( hIvasRend->hHrtfs.hHrtfParambin ) );
    9236         666 :     ivas_HRTF_statistics_close( &( hIvasRend->hHrtfs.hHrtfStatistics ) );
    9237             : 
    9238         666 :     free( hIvasRend );
    9239         666 :     *phIvasRend = NULL;
    9240             : 
    9241         666 :     return;
    9242             : }
    9243             : 
    9244             : /*-------------------------------------------------------------------*
    9245             :  * IVAS_REND_openCldfb()
    9246             :  *
    9247             :  *
    9248             :  *-------------------------------------------------------------------*/
    9249             : 
    9250           0 : ivas_error IVAS_REND_openCldfb(
    9251             :     IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS],
    9252             :     IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_OUTPUT_CHANNELS],
    9253             :     const Word16 num_in_chs,
    9254             :     const Word16 num_out_chs,
    9255             :     const Word32 output_Fs )
    9256             : {
    9257             :     Word16 n;
    9258             :     ivas_error error;
    9259             : 
    9260           0 :     FOR( n = 0; n < num_in_chs; n++ )
    9261             :     {
    9262           0 :         IF( ( error = openCldfb_ivas_fx( &( cldfbAna[n] ), CLDFB_ANALYSIS, output_Fs, CLDFB_PROTOTYPE_5_00MS, DEC ) ) != IVAS_ERR_OK )
    9263             :         {
    9264           0 :             return error;
    9265             :         }
    9266             :     }
    9267           0 :     FOR( ; n < IVAS_MAX_INPUT_CHANNELS; n++ )
    9268             :     {
    9269           0 :         cldfbAna[n] = NULL;
    9270             :     }
    9271             : 
    9272           0 :     FOR( n = 0; n < num_out_chs; n++ )
    9273             :     {
    9274           0 :         IF( ( error = openCldfb_ivas_fx( &( cldfbSyn[n] ), CLDFB_SYNTHESIS, output_Fs, CLDFB_PROTOTYPE_5_00MS, DEC ) ) != IVAS_ERR_OK )
    9275             :         {
    9276           0 :             return error;
    9277             :         }
    9278             :     }
    9279           0 :     FOR( ; n < IVAS_MAX_OUTPUT_CHANNELS; n++ )
    9280             :     {
    9281           0 :         cldfbSyn[n] = NULL;
    9282             :     }
    9283             : 
    9284           0 :     return IVAS_ERR_OK;
    9285             : }
    9286             : 
    9287             : 
    9288             : /*-------------------------------------------------------------------*
    9289             :  * IVAS_REND_closeCldfb()
    9290             :  *
    9291             :  *
    9292             :  *-------------------------------------------------------------------*/
    9293             : 
    9294           0 : void IVAS_REND_closeCldfb(
    9295             :     IVAS_CLDFB_FILTER_BANK_HANDLE cldfbAna[IVAS_MAX_INPUT_CHANNELS],
    9296             :     IVAS_CLDFB_FILTER_BANK_HANDLE cldfbSyn[IVAS_MAX_OUTPUT_CHANNELS] )
    9297             : {
    9298             :     Word16 n;
    9299             : 
    9300           0 :     FOR( n = 0; n < IVAS_MAX_INPUT_CHANNELS; n++ )
    9301             :     {
    9302           0 :         IF( cldfbAna[n] != NULL )
    9303             :         {
    9304           0 :             deleteCldfb_ivas_fx( &( cldfbAna[n] ) );
    9305           0 :             cldfbAna[n] = NULL;
    9306             :         }
    9307             :     }
    9308             : 
    9309           0 :     FOR( n = 0; n < IVAS_MAX_OUTPUT_CHANNELS; n++ )
    9310             :     {
    9311           0 :         IF( cldfbSyn[n] != NULL )
    9312             :         {
    9313           0 :             deleteCldfb_ivas_fx( &( cldfbSyn[n] ) );
    9314           0 :             cldfbSyn[n] = NULL;
    9315             :         }
    9316             :     }
    9317             : 
    9318           0 :     return;
    9319             : }
    9320             : 
    9321             : 
    9322             : /*-------------------------------------------------------------------*
    9323             :  * IVAS_REND_cldfbSynthesis_wrapper()
    9324             :  *
    9325             :  *
    9326             :  *-------------------------------------------------------------------*/
    9327             : 
    9328           0 : void IVAS_REND_cldfbAnalysis_ts_wrapper(
    9329             :     const Word32 *timeIn,                          /* i  : time buffer         */
    9330             :     Word32 realBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o  : real value buffer   */
    9331             :     Word32 imagBuffer[IVAS_CLDFB_NO_CHANNELS_MAX], /* o  : imag value buffer   */
    9332             :     const Word16 samplesToProcess,                 /* i  : samples to process  */
    9333             :     IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb,         /* i  : filterbank state    */
    9334             :     Word16 Q_in,
    9335             :     Word16 *Q_out )
    9336             : {
    9337             : 
    9338           0 :     Word16 Q_cldfb = Q_in;
    9339           0 :     assert( Q_in == h_cldfb->Q_cldfb_state );
    9340           0 :     cldfbAnalysis_ts_fx_fixed_q( timeIn, realBuffer, imagBuffer, samplesToProcess, h_cldfb, &Q_cldfb );
    9341             : 
    9342           0 :     *Q_out = sub( Q_in, 5 );
    9343             : 
    9344           0 :     return;
    9345             : }
    9346             : 
    9347             : 
    9348             : /*-------------------------------------------------------------------*
    9349             :  * IVAS_REND_cldfbSynthesis_wrapper()
    9350             :  *
    9351             :  *
    9352             :  *-------------------------------------------------------------------*/
    9353             : 
    9354           0 : void IVAS_REND_cldfbSynthesis_wrapper(
    9355             :     Word32 **realBuffer,                   /* i  : real values                 */
    9356             :     Word32 **imagBuffer,                   /* i  : imag values                 */
    9357             :     Word32 *timeOut,                       /* o  : output time domain samples  */
    9358             :     const Word16 samplesToProcess,         /* i  : number of processed samples */
    9359             :     IVAS_CLDFB_FILTER_BANK_HANDLE h_cldfb, /* i  : filter bank state           */
    9360             :     Word16 Q_cldfb,
    9361             :     Word16 *Q_out )
    9362             : {
    9363             : 
    9364           0 :     Scale_sig32( h_cldfb->cldfb_state_fx, h_cldfb->p_filter_length, sub( sub( Q_cldfb, 1 ), h_cldfb->Q_cldfb_state ) );
    9365           0 :     cldfbSynthesis_ivas_fx( realBuffer, imagBuffer, timeOut, samplesToProcess, 0, 0, h_cldfb ); // Q_cldfb - 1
    9366           0 :     *Q_out = sub( Q_cldfb, 1 );
    9367           0 :     move16();
    9368           0 :     h_cldfb->Q_cldfb_state = *Q_out;
    9369           0 :     move16();
    9370             : 
    9371           0 :     return;
    9372             : }
    9373             : 
    9374             : 
    9375             : /*---------------------------------------------------------------------*
    9376             :  * IVAS_REND_GetHrtfHandle( )
    9377             :  *
    9378             :  *
    9379             :  *---------------------------------------------------------------------*/
    9380             : 
    9381           0 : ivas_error IVAS_REND_GetHrtfHandle(
    9382             :     IVAS_REND_HANDLE hIvasRend,    /* i/o: IVAS renderer handle     */
    9383             :     IVAS_DEC_HRTF_HANDLE **hHrtfTD /* o  : HRTF handle              */
    9384             : )
    9385             : {
    9386           0 :     if ( hIvasRend == NULL || hIvasRend->hHrtfs.hHrtfTD == NULL )
    9387             :     {
    9388           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    9389             :     }
    9390             : 
    9391           0 :     *hHrtfTD = &hIvasRend->hHrtfs.hHrtfTD;
    9392             : 
    9393           0 :     return IVAS_ERR_OK;
    9394             : }
    9395             : 
    9396             : 
    9397             : /*---------------------------------------------------------------------*
    9398             :  * IVAS_REND_GetHrtfCRendHandle( )
    9399             :  *
    9400             :  *
    9401             :  *---------------------------------------------------------------------*/
    9402             : 
    9403           0 : ivas_error IVAS_REND_GetHrtfCRendHandle(
    9404             :     IVAS_REND_HANDLE hIvasRend,             /* i/o: IVAS renderer handle     */
    9405             :     IVAS_DEC_HRTF_CREND_HANDLE **hSetOfHRTF /* o  : Set of HRTF handle       */
    9406             : )
    9407             : {
    9408           0 :     if ( hIvasRend == NULL || hIvasRend->hHrtfs.hSetOfHRTF == NULL )
    9409             :     {
    9410           0 :         return IVAS_ERR_WRONG_PARAMS;
    9411             :     }
    9412             : 
    9413           0 :     *hSetOfHRTF = &hIvasRend->hHrtfs.hSetOfHRTF;
    9414             : 
    9415           0 :     return IVAS_ERR_OK;
    9416             : }
    9417             : 
    9418             : 
    9419             : /*---------------------------------------------------------------------*
    9420             :  * IVAS_REND_GetHrtfFastConvHandle( )
    9421             :  *
    9422             :  *
    9423             :  *---------------------------------------------------------------------*/
    9424             : 
    9425           0 : ivas_error IVAS_REND_GetHrtfFastConvHandle(
    9426             :     IVAS_REND_HANDLE hIvasRend,                   /* i/o: IVAS renderer handle   */
    9427             :     IVAS_DEC_HRTF_FASTCONV_HANDLE **hHrtfFastConv /* o  : FASTCONV HRTF handle   */
    9428             : )
    9429             : {
    9430           0 :     if ( hIvasRend == NULL || hIvasRend->hHrtfs.hHrtfFastConv == NULL )
    9431             :     {
    9432           0 :         return IVAS_ERR_WRONG_PARAMS;
    9433             :     }
    9434             : 
    9435           0 :     *hHrtfFastConv = &hIvasRend->hHrtfs.hHrtfFastConv;
    9436             : 
    9437           0 :     return IVAS_ERR_OK;
    9438             : }
    9439             : 
    9440             : 
    9441             : /*---------------------------------------------------------------------*
    9442             :  * IVAS_REND_GetHrtfParamBinHandle( )
    9443             :  *
    9444             :  *
    9445             :  *---------------------------------------------------------------------*/
    9446             : 
    9447           0 : ivas_error IVAS_REND_GetHrtfParamBinHandle(
    9448             :     IVAS_REND_HANDLE hIvasRend,                   /* i/o: IVAS renderer handle                */
    9449             :     IVAS_DEC_HRTF_PARAMBIN_HANDLE **hHrtfParambin /* o  : Parametric binauralizer HRTF handle */
    9450             : )
    9451             : {
    9452           0 :     if ( hIvasRend == NULL || hIvasRend->hHrtfs.hHrtfParambin == NULL )
    9453             :     {
    9454           0 :         return IVAS_ERR_WRONG_PARAMS;
    9455             :     }
    9456             : 
    9457           0 :     *hHrtfParambin = &hIvasRend->hHrtfs.hHrtfParambin;
    9458             : 
    9459           0 :     return IVAS_ERR_OK;
    9460             : }
    9461             : 
    9462             : 
    9463             : /*---------------------------------------------------------------------*
    9464             :  * IVAS_REND_GetHrtfStatisticsHandle( )
    9465             :  *
    9466             :  *
    9467             :  *---------------------------------------------------------------------*/
    9468             : 
    9469           0 : ivas_error IVAS_REND_GetHrtfStatisticsHandle(
    9470             :     IVAS_REND_HANDLE hIvasRend,                       /* i/o: IVAS renderer handle    */
    9471             :     IVAS_DEC_HRTF_STATISTICS_HANDLE **hHrtfStatistics /* o  : HRTF statistics handle  */
    9472             : )
    9473             : {
    9474           0 :     if ( hIvasRend == NULL || hIvasRend->hHrtfs.hHrtfStatistics == NULL )
    9475             :     {
    9476           0 :         return IVAS_ERR_WRONG_PARAMS;
    9477             :     }
    9478             : 
    9479           0 :     *hHrtfStatistics = &hIvasRend->hHrtfs.hHrtfStatistics;
    9480             : 
    9481           0 :     return IVAS_ERR_OK;
    9482             : }
    9483             : 
    9484          34 : static ivas_error ivas_masa_ext_rend_dirac_rend_init(
    9485             :     input_masa *inputMasa )
    9486             : {
    9487             :     Word16 nchan_out_woLFE;
    9488             :     Word16 nchan_transport;
    9489             :     UWord16 i, j, k;
    9490             :     Word32 ls_azimuth_fx[MAX_OUTPUT_CHANNELS];   /*Q22*/
    9491             :     Word32 ls_elevation_fx[MAX_OUTPUT_CHANNELS]; /*Q22*/
    9492             :     Word32 output_Fs;
    9493             :     ivas_error error;
    9494             :     DIRAC_REND_HANDLE hDirACRend;
    9495             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
    9496             : 
    9497          34 :     error = IVAS_ERR_OK;
    9498          34 :     move32();
    9499             : 
    9500          34 :     hDirACRend = NULL;
    9501          34 :     output_Fs = *( inputMasa->base.ctx.pOutSampleRate );
    9502          34 :     move32();
    9503             : 
    9504          34 :     hSpatParamRendCom = inputMasa->hMasaExtRend->hSpatParamRendCom;
    9505             : 
    9506             :     /*-----------------------------------------------------------------*
    9507             :      * prepare library opening
    9508             :      *-----------------------------------------------------------------*/
    9509             : 
    9510          34 :     IF( ( hDirACRend = (DIRAC_REND_HANDLE) malloc( sizeof( DIRAC_REND_DATA ) ) ) == NULL )
    9511             :     {
    9512           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC renderer\n" ) );
    9513             :     }
    9514             : 
    9515          34 :     IF( EQ_16( inputMasa->base.inConfig, IVAS_AUDIO_CONFIG_MASA2 ) )
    9516             :     {
    9517          18 :         nchan_transport = 2;
    9518          18 :         move16();
    9519             :     }
    9520             :     ELSE
    9521             :     {
    9522          16 :         nchan_transport = 1;
    9523          16 :         move16();
    9524             :     }
    9525             : 
    9526             :     /*-----------------------------------------------------------------*
    9527             :      * output setup: for parametric binaural renderer, use output setup, otherwise internal setup
    9528             :      *-----------------------------------------------------------------*/
    9529             : 
    9530          34 :     ivas_output_init( &hDirACRend->hOutSetup, *inputMasa->base.ctx.pOutConfig );
    9531             : 
    9532          34 :     IF( EQ_16( hDirACRend->hOutSetup.output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
    9533             :     {
    9534             :         /* Copy from ivas_ls_custom_setup */
    9535           0 :         hDirACRend->hOutSetup.nchan_out_woLFE = inputMasa->base.ctx.pCustomLsOut->num_spk;
    9536           0 :         move16();
    9537           0 :         hDirACRend->hOutSetup.ls_azimuth_fx = inputMasa->base.ctx.pCustomLsOut->ls_azimuth_fx;
    9538           0 :         hDirACRend->hOutSetup.ls_elevation_fx = inputMasa->base.ctx.pCustomLsOut->ls_elevation_fx;
    9539             : 
    9540           0 :         hDirACRend->hOutSetup.num_lfe = inputMasa->base.ctx.pCustomLsOut->num_lfe;
    9541           0 :         move16();
    9542           0 :         hDirACRend->hOutSetup.index_lfe[0] = inputMasa->base.ctx.pCustomLsOut->lfe_idx[0];
    9543           0 :         move16();
    9544             : 
    9545           0 :         hDirACRend->hOutSetup.is_loudspeaker_setup = TRUE;
    9546           0 :         move16();
    9547           0 :         hDirACRend->hOutSetup.is_planar_setup = (Word8) inputMasa->base.ctx.pCustomLsOut->is_planar_setup;
    9548           0 :         move16();
    9549             :     }
    9550             : 
    9551          34 :     nchan_out_woLFE = hDirACRend->hOutSetup.nchan_out_woLFE;
    9552          34 :     move16();
    9553             : 
    9554          34 :     test();
    9555          34 :     IF( hDirACRend->hOutSetup.ls_azimuth_fx != NULL && hDirACRend->hOutSetup.ls_elevation_fx != NULL )
    9556             :     {
    9557          20 :         Copy32( hDirACRend->hOutSetup.ls_azimuth_fx, ls_azimuth_fx, nchan_out_woLFE );
    9558          20 :         Copy32( hDirACRend->hOutSetup.ls_elevation_fx, ls_elevation_fx, nchan_out_woLFE );
    9559             :     }
    9560             : 
    9561          34 :     IF( EQ_16( hDirACRend->hOutSetup.ambisonics_order, -1 ) )
    9562             :     {
    9563          22 :         hDirACRend->hOutSetup.ambisonics_order = SBA_HOA3_ORDER; /* Order 3 is used by default in DirAC for SHD processing */
    9564          22 :         move16();
    9565          22 :         test();
    9566          22 :         if ( EQ_16( hDirACRend->hOutSetup.output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_16( hDirACRend->hOutSetup.output_config, IVAS_AUDIO_CONFIG_STEREO ) )
    9567             :         {
    9568           2 :             hDirACRend->hOutSetup.ambisonics_order = SBA_FOA_ORDER;
    9569           2 :             move16();
    9570             :         }
    9571             :     }
    9572          12 :     ELSE IF( GE_16( hDirACRend->hOutSetup.ambisonics_order, SBA_FOA_ORDER ) )
    9573             :     {
    9574          12 :         Copy32( ls_azimuth_4d4_fx, ls_azimuth_fx, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS );
    9575          12 :         Copy32( ls_elevation_4d4_fx, ls_elevation_fx, DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS );
    9576             :     }
    9577             : 
    9578             :     /*-----------------------------------------------------------------*
    9579             :      * set input parameters
    9580             :      *-----------------------------------------------------------------*/
    9581             : 
    9582          34 :     test();
    9583          34 :     IF( EQ_16( hDirACRend->hOutSetup.output_config, IVAS_AUDIO_CONFIG_MONO ) )
    9584             :     {
    9585           2 :         hDirACRend->synthesisConf = DIRAC_SYNTHESIS_MONO;
    9586           2 :         move32();
    9587           2 :         hDirACRend->panningConf = DIRAC_PANNING_HOA3;
    9588           2 :         move32();
    9589           2 :         nchan_out_woLFE = 1;
    9590           2 :         move16();
    9591             :     }
    9592          32 :     ELSE IF( hDirACRend->hOutSetup.is_loudspeaker_setup )
    9593             :     {
    9594          20 :         hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_LS;
    9595          20 :         hDirACRend->panningConf = DIRAC_PANNING_VBAP;
    9596          20 :         move32();
    9597          20 :         move32();
    9598             :     }
    9599          12 :     ELSE IF( !hDirACRend->hOutSetup.is_loudspeaker_setup && GT_16( nchan_transport, 1 ) )
    9600             :     {
    9601           6 :         hDirACRend->synthesisConf = DIRAC_SYNTHESIS_PSD_SHD;
    9602           6 :         move32();
    9603           6 :         hDirACRend->panningConf = DIRAC_PANNING_HOA3;
    9604           6 :         move32();
    9605             :     }
    9606             :     ELSE
    9607             :     {
    9608           6 :         hDirACRend->synthesisConf = DIRAC_SYNTHESIS_GAIN_SHD;
    9609           6 :         move32();
    9610           6 :         hDirACRend->panningConf = DIRAC_PANNING_HOA3;
    9611           6 :         move32();
    9612             :     }
    9613             : 
    9614          34 :     IF( ( hDirACRend->frequency_axis_fx = (Word16 *) malloc( hSpatParamRendCom->num_freq_bands * sizeof( Word16 ) ) ) == NULL )
    9615             :     {
    9616           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9617             :     }
    9618          34 :     set16_fx( hDirACRend->frequency_axis_fx, 0, hSpatParamRendCom->num_freq_bands );
    9619          34 :     ivas_dirac_dec_get_frequency_axis_fx( hDirACRend->frequency_axis_fx, output_Fs, hSpatParamRendCom->num_freq_bands );
    9620             : 
    9621          34 :     test();
    9622          34 :     IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_HOA3 ) && EQ_16( nchan_transport, 2 ) )
    9623             :     {
    9624           8 :         IF( ( hDirACRend->masa_stereo_type_detect = (MASA_STEREO_TYPE_DETECT *) malloc( sizeof( MASA_STEREO_TYPE_DETECT ) ) ) == NULL )
    9625             :         {
    9626           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9627             :         }
    9628           8 :         ivas_masa_init_stereotype_detection_fx( hDirACRend->masa_stereo_type_detect );
    9629             :     }
    9630             :     ELSE
    9631             :     {
    9632          26 :         hDirACRend->masa_stereo_type_detect = NULL;
    9633             :     }
    9634             : 
    9635          34 :     hSpatParamRendCom->numIsmDirections = 0;
    9636          34 :     move16();
    9637             : 
    9638             :     /*-----------------------------------------------------------------*
    9639             :      * (re)configure sub-modules
    9640             :      *-----------------------------------------------------------------*/
    9641             : 
    9642             :     /* prototype signal computation */
    9643             :     /* allocate output setup related arrays */
    9644          34 :     IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_LS ) )
    9645             :     {
    9646             :         /* Directional and diffuses components in output LS format */
    9647          20 :         hDirACRend->num_outputs_diff = nchan_out_woLFE;
    9648          20 :         move16();
    9649          20 :         hDirACRend->num_outputs_dir = nchan_out_woLFE;
    9650          20 :         move16();
    9651             :     }
    9652          14 :     ELSE IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) )
    9653             :     {
    9654             :         /* Directional and diffuses components in SHD */
    9655             :         /* Diffuseness components up to 1st order */
    9656           6 :         hDirACRend->num_outputs_diff = imult1616( add( s_min( hDirACRend->hOutSetup.ambisonics_order, 1 ), 1 ), ( add( s_min( hDirACRend->hOutSetup.ambisonics_order, 1 ), 1 ) ) );
    9657           6 :         hDirACRend->num_outputs_dir = ivas_sba_get_nchan_fx( hDirACRend->hOutSetup.ambisonics_order, 0 );
    9658             :     }
    9659           8 :     ELSE IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_SHD ) )
    9660             :     {
    9661           6 :         hDirACRend->num_outputs_diff = DIRAC_HOA_RENDERING_NUM_VIRT_DECORR_LS;
    9662           6 :         move16();
    9663           6 :         hDirACRend->num_outputs_dir = nchan_out_woLFE;
    9664           6 :         move16();
    9665             :     }
    9666           2 :     ELSE IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO ) )
    9667             :     {
    9668           2 :         hDirACRend->num_outputs_diff = 1; /* There is one output channel in mono */
    9669           2 :         move16();
    9670           2 :         hDirACRend->num_outputs_dir = 2; /* Two channels are pre-rendered for stereo type detection */
    9671           2 :         move16();
    9672             :     }
    9673             :     ELSE
    9674             :     {
    9675           0 :         assert( 0 && "DirAC: not existing synthesis methods!" );
    9676             :     }
    9677             : 
    9678          34 :     IF( ( hDirACRend->proto_index_dir = (Word16 *) malloc( sizeof( Word16 ) * hDirACRend->num_outputs_dir ) ) == NULL )
    9679             :     {
    9680           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9681             :     }
    9682             : 
    9683          34 :     IF( ( hDirACRend->proto_index_diff = (Word16 *) malloc( sizeof( Word16 ) * hDirACRend->num_outputs_diff ) ) == NULL )
    9684             :     {
    9685           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9686             :     }
    9687             : 
    9688          34 :     set16_fx( hDirACRend->proto_index_dir, 0, hDirACRend->num_outputs_dir );
    9689          34 :     set16_fx( hDirACRend->proto_index_diff, 0, hDirACRend->num_outputs_diff );
    9690             : 
    9691          34 :     hDirACRend->sba_map_tc = sba_map_tc;
    9692             : 
    9693          34 :     IF( EQ_16( nchan_transport, 1 ) )
    9694             :     {
    9695          16 :         hDirACRend->num_protos_ambi = 1;
    9696          16 :         move16();
    9697          16 :         hDirACRend->num_protos_dir = 1;
    9698          16 :         move16();
    9699          16 :         hDirACRend->num_protos_diff = 1;
    9700          16 :         move16();
    9701             :     }
    9702          18 :     ELSE IF( EQ_16( nchan_transport, 2 ) )
    9703             :     {
    9704          18 :         IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) )
    9705             :         {
    9706           0 :             hDirACRend->num_protos_ambi = 2;
    9707           0 :             move16();
    9708           0 :             hDirACRend->num_protos_diff = 1;
    9709           0 :             move16();
    9710           0 :             hDirACRend->num_protos_dir = 2;
    9711           0 :             move16();
    9712           0 :             hDirACRend->proto_index_dir[1] = 1;
    9713           0 :             move16();
    9714             :         }
    9715          18 :         ELSE IF( EQ_16( hDirACRend->hOutSetup.output_config, IVAS_AUDIO_CONFIG_MONO ) )
    9716             :         {
    9717             :             /* Following the foa rendering for code compatibility */
    9718           2 :             hDirACRend->num_protos_ambi = 2;
    9719           2 :             move16();
    9720           2 :             hDirACRend->num_protos_dir = 2;
    9721           2 :             move16();
    9722           2 :             hDirACRend->num_protos_diff = 3;
    9723           2 :             move16();
    9724           2 :             hDirACRend->proto_index_dir[0] = 0;
    9725           2 :             move16();
    9726           2 :             hDirACRend->proto_index_diff[0] = 0;
    9727           2 :             move16();
    9728             :         }
    9729             :         ELSE
    9730             :         {
    9731          16 :             hDirACRend->num_protos_ambi = 2;
    9732          16 :             move16();
    9733          16 :             hDirACRend->num_protos_diff = 3;
    9734          16 :             move16();
    9735             : 
    9736         142 :             FOR( k = 0; k < hDirACRend->num_outputs_diff; k++ )
    9737             :             {
    9738         126 :                 IF( ls_azimuth_fx[k] > 0 )
    9739             :                 {
    9740          58 :                     hDirACRend->proto_index_diff[k] = 1;
    9741             :                 }
    9742          68 :                 ELSE IF( ls_azimuth_fx[k] < 0 )
    9743             :                 {
    9744          58 :                     hDirACRend->proto_index_diff[k] = 2;
    9745             :                 }
    9746             :                 ELSE
    9747             :                 {
    9748          10 :                     hDirACRend->proto_index_diff[k] = 0;
    9749             :                 }
    9750         126 :                 move16();
    9751             :             }
    9752             : 
    9753          16 :             IF( hDirACRend->hOutSetup.is_loudspeaker_setup )
    9754             :             {
    9755          10 :                 hDirACRend->num_protos_dir = 3;
    9756          10 :                 move16();
    9757          10 :                 Copy( hDirACRend->proto_index_diff, hDirACRend->proto_index_dir, nchan_out_woLFE );
    9758             :             }
    9759             :             ELSE
    9760             :             {
    9761           6 :                 hDirACRend->num_protos_dir = 2;
    9762           6 :                 move16();
    9763           6 :                 hDirACRend->proto_index_dir[1] = 1;
    9764           6 :                 move16();
    9765             :             }
    9766             :         }
    9767             :     }
    9768             : 
    9769             :     /* direct/diffuse responses */
    9770          34 :     IF( ( hDirACRend->diffuse_response_function_fx = (Word16 *) malloc( sizeof( Word16 ) * hDirACRend->num_outputs_dir ) ) == NULL )
    9771             :     {
    9772           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9773             :     }
    9774             : 
    9775          34 :     test();
    9776          34 :     test();
    9777          34 :     IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_LS ) || EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_SHD ) || EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO ) )
    9778             :     {
    9779          28 :         initDiffuseResponses_fx( hDirACRend->diffuse_response_function_fx, nchan_out_woLFE, hDirACRend->hOutSetup.output_config,
    9780          28 :                                  hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, MASA_FORMAT, &hDirACRend->num_ele_spk_no_diffuse_rendering, IVAS_AUDIO_CONFIG_INVALID );
    9781             :     }
    9782             :     ELSE
    9783             :     {
    9784           6 :         initDiffuseResponses_fx( hDirACRend->diffuse_response_function_fx, hDirACRend->num_outputs_dir, IVAS_AUDIO_CONFIG_FOA,
    9785           6 :                                  hDirACRend->hOutSetup, hDirACRend->hOutSetup.ambisonics_order, MASA_FORMAT, &hDirACRend->num_ele_spk_no_diffuse_rendering, IVAS_AUDIO_CONFIG_INVALID );
    9786             :     }
    9787             : 
    9788          34 :     hDirACRend->hoa_encoder_fx = NULL;
    9789          34 :     IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_SHD ) )
    9790             :     {
    9791           6 :         IF( ( hDirACRend->hoa_encoder_fx = (Word32 *) malloc( nchan_out_woLFE * hDirACRend->num_outputs_diff * sizeof( Word32 ) ) ) == NULL )
    9792             :         {
    9793           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9794             :         }
    9795             : 
    9796           6 :         set32_fx( hDirACRend->hoa_encoder_fx, 0, imult1616( nchan_out_woLFE, hDirACRend->num_outputs_diff ) );
    9797           6 :         compute_hoa_encoder_mtx_fx( ls_azimuth_fx, ls_elevation_fx, hDirACRend->hoa_encoder_fx, hDirACRend->num_outputs_diff, hDirACRend->hOutSetup.ambisonics_order );
    9798             :     }
    9799             : 
    9800             :     /* VBAP */
    9801          34 :     inputMasa->hMasaExtRend->hVBAPdata = NULL;
    9802             : 
    9803          34 :     IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_VBAP ) )
    9804             :     {
    9805          20 :         IF( NE_32( ( error = vbap_init_data_fx( &( inputMasa->hMasaExtRend->hVBAPdata ), ls_azimuth_fx, ls_elevation_fx, nchan_out_woLFE, MASA_FORMAT ) ), IVAS_ERR_OK ) )
    9806             :         {
    9807           0 :             return error;
    9808             :         }
    9809             :     }
    9810             : 
    9811             :     /* HOA panning/dec */
    9812          34 :     hDirACRend->hoa_decoder = NULL;
    9813          34 :     IF( EQ_16( hDirACRend->panningConf, DIRAC_PANNING_HOA3 ) )
    9814             :     {
    9815          14 :         IF( hDirACRend->hOutSetup.is_loudspeaker_setup )
    9816             :         {
    9817           2 :             IF( NE_32( ( error = ivas_sba_get_hoa_dec_matrix_fx( hDirACRend->hOutSetup, &inputMasa->hMasaExtRend->hoa_dec_mtx, hDirACRend->hOutSetup.ambisonics_order ) ), IVAS_ERR_OK ) )
    9818             :             {
    9819           0 :                 return error;
    9820             :             }
    9821             : 
    9822           2 :             hDirACRend->hoa_decoder = inputMasa->hMasaExtRend->hoa_dec_mtx;
    9823             :         }
    9824             :     }
    9825             : 
    9826             :     /* decorrelation */
    9827          34 :     hDirACRend->proto_signal_decorr_on = 1;
    9828          34 :     move16();
    9829          34 :     if ( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_MONO ) )
    9830             :     {
    9831           2 :         hDirACRend->proto_signal_decorr_on = 0;
    9832           2 :         move16();
    9833             :     }
    9834             : 
    9835          34 :     IF( hDirACRend->proto_signal_decorr_on )
    9836             :     {
    9837          32 :         IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDirACRend->h_freq_domain_decorr_ap_params ),
    9838             :                                                             &( hDirACRend->h_freq_domain_decorr_ap_state ),
    9839             :                                                             hSpatParamRendCom->num_freq_bands,
    9840             :                                                             hDirACRend->num_outputs_diff,
    9841             :                                                             hDirACRend->num_protos_diff,
    9842             :                                                             hDirACRend->synthesisConf,
    9843             :                                                             hDirACRend->frequency_axis_fx,
    9844             :                                                             nchan_transport,
    9845             :                                                             output_Fs ) ),
    9846             :                    IVAS_ERR_OK ) )
    9847             :         {
    9848           0 :             return error;
    9849             :         }
    9850             :     }
    9851             : 
    9852             :     /* output synthesis */
    9853          34 :     IF( NE_32( ( ivas_dirac_dec_output_synthesis_open_fx( hSpatParamRendCom, hDirACRend, RENDERER_DIRAC, nchan_transport, output_Fs, 0 ) ), IVAS_ERR_OK ) )
    9854             :     {
    9855           0 :         return error;
    9856             :     }
    9857          34 :     hDirACRend->h_output_synthesis_psd_params.use_onset_filters = hDirACRend->proto_signal_decorr_on;
    9858          34 :     move16();
    9859             : 
    9860          34 :     test();
    9861          34 :     if ( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_SHD ) || EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) )
    9862             :     {
    9863          12 :         hDirACRend->h_output_synthesis_psd_params.use_onset_filters = 0;
    9864          12 :         move16();
    9865             :     }
    9866             : 
    9867             :     /*-----------------------------------------------------------------*
    9868             :      * memory allocation
    9869             :      *-----------------------------------------------------------------*/
    9870             : 
    9871          34 :     IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_GAIN_SHD ) )
    9872             :     {
    9873           6 :         hDirACRend->proto_frame_f_fx = NULL;
    9874             :     }
    9875             :     ELSE
    9876             :     {
    9877          28 :         IF( ( hDirACRend->proto_frame_f_fx = (Word32 *) malloc( sizeof( Word32 ) * shl( imult1616( hDirACRend->num_protos_diff, hSpatParamRendCom->num_freq_bands ), 1 ) ) ) == NULL )
    9878             :         {
    9879           0 :             return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC\n" ) );
    9880             :         }
    9881          28 :         hDirACRend->proto_frame_f_len = shl( imult1616( hDirACRend->num_protos_diff, hSpatParamRendCom->num_freq_bands ), 1 );
    9882          28 :         move16();
    9883             :     }
    9884             : 
    9885             : 
    9886          34 :     hDirACRend->buffer_energy_fx = NULL;
    9887         136 :     FOR( i = 0; i < DIRAC_NUM_DIMS; i++ )
    9888             :     {
    9889        3366 :         FOR( j = 0; j < DIRAC_NO_COL_AVG_DIFF; j++ )
    9890             :         {
    9891        3264 :             hDirACRend->buffer_intensity_real_fx[i][j] = NULL;
    9892             :         }
    9893             :     }
    9894             : 
    9895             :     /* output synthesis */
    9896          34 :     ivas_dirac_dec_output_synthesis_init_fx( hSpatParamRendCom, hDirACRend, nchan_out_woLFE, 0 );
    9897             : 
    9898             :     /* Allocate stack memory */
    9899          34 :     IF( NE_32( ( error = ivas_dirac_alloc_mem_fx( hDirACRend, RENDERER_DIRAC, hSpatParamRendCom->num_freq_bands, &( hDirACRend->stack_mem ), 0 ) ), IVAS_ERR_OK ) )
    9900             :     {
    9901           0 :         return error;
    9902             :     }
    9903             : 
    9904          34 :     inputMasa->hMasaExtRend->hDirACRend = hDirACRend;
    9905             : 
    9906          34 :     return error;
    9907             : }
    9908             : 
    9909             : 
    9910          12 : static ivas_error ivas_masa_ext_rend_parambin_init(
    9911             :     input_masa *inputMasa,                  /* i/o: MASA external renderer structure        */
    9912             :     const RENDER_CONFIG_DATA *hRendCfg,     /* i  : Renderer configuration data handle      */
    9913             :     HRTFS_STATISTICS_HANDLE hHrtfStatistics /* i  : HRTF statistics                         */
    9914             : )
    9915             : {
    9916             :     DIRAC_DEC_BIN_HANDLE hDiracDecBin;
    9917             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    9918             :     HRTFS_PARAMBIN_HANDLE *phHrtfParambin;
    9919             : #else
    9920             :     HRTFS_PARAMBIN_HANDLE hHrtfParambin;
    9921             : #endif
    9922             :     Word16 nBins;
    9923             :     Word32 output_Fs;
    9924             :     RENDERER_TYPE renderer_type;
    9925             :     Word16 j, k, bin;
    9926             :     Word32 binCenterFreq_fx;
    9927             :     Word16 tmpFloat_fx;
    9928             :     ivas_error error;
    9929             :     Word16 frequency_axis_fx[CLDFB_NO_CHANNELS_MAX];
    9930             : #ifdef FIX_587_DEFAULT_REVERB
    9931             :     const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *pRoomAcoustics;
    9932             : #endif
    9933             : 
    9934             :     Word16 pos_idx, num_poses;
    9935             :     Word16 tmp;
    9936             :     Word16 tmp_e;
    9937             :     Word16 tmp2;
    9938             : 
    9939          12 :     error = IVAS_ERR_OK;
    9940          12 :     move32();
    9941             : 
    9942             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
    9943          12 :     phHrtfParambin = inputMasa->hMasaExtRend->hHrtfParambin;
    9944             : #else
    9945             :     hHrtfParambin = *( inputMasa->hMasaExtRend->hHrtfParambin );
    9946             : #endif
    9947             :     /* Set common variables and defaults */
    9948          12 :     output_Fs = *( inputMasa->base.ctx.pOutSampleRate );
    9949          12 :     move32();
    9950          12 :     nBins = inputMasa->hMasaExtRend->hSpatParamRendCom->num_freq_bands;
    9951          12 :     move16();
    9952          12 :     renderer_type = inputMasa->hMasaExtRend->renderer_type;
    9953          12 :     move32();
    9954             : 
    9955          12 :     num_poses = 1;
    9956          12 :     move16();
    9957          12 :     if ( inputMasa->base.ctx.pSplitRendWrapper != NULL )
    9958             :     {
    9959           0 :         num_poses = inputMasa->base.ctx.pSplitRendWrapper->multiBinPoseData.num_poses;
    9960           0 :         move16();
    9961             :     }
    9962             : 
    9963          24 :     for ( pos_idx = 0; pos_idx < num_poses; pos_idx++ )
    9964             :     {
    9965          12 :         hDiracDecBin = inputMasa->hMasaExtRend->hDiracDecBin[pos_idx];
    9966             : 
    9967             :         /* Init assumes that no reconfiguration is required in external renderer. Instead, free and rebuild whole rendering. */
    9968          12 :         IF( ( hDiracDecBin = (DIRAC_DEC_BIN_HANDLE) malloc( sizeof( DIRAC_DEC_BIN_DATA ) ) ) == NULL )
    9969             :         {
    9970           0 :             return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DirAC binaural handle " );
    9971             :         }
    9972             : 
    9973          12 :         hDiracDecBin->hTdDecorr = NULL;
    9974          12 :         hDiracDecBin->hReverb = NULL;
    9975          12 :         hDiracDecBin->h_freq_domain_decorr_ap_params = NULL;
    9976          12 :         hDiracDecBin->h_freq_domain_decorr_ap_state = NULL;
    9977          12 :         hDiracDecBin->hDiffuseDist = NULL; /* Not used in external renderer */
    9978          12 :         hDiracDecBin->useTdDecorr = 0;     /* Always use frequency domain decorrelator in external renderer */
    9979          12 :         move16();
    9980             : 
    9981          36 :         FOR( j = 0; j < BINAURAL_CHANNELS; j++ )
    9982             :         {
    9983         168 :             FOR( k = 0; k < BINAURAL_CHANNELS + MAX_NUM_OBJECTS; k++ )
    9984             :             {
    9985         144 :                 set16_fx( hDiracDecBin->processMtxRe_fx[j][k], 0, nBins );
    9986         144 :                 set16_fx( hDiracDecBin->processMtxIm_fx[j][k], 0, nBins );
    9987             :             }
    9988             : 
    9989          72 :             FOR( k = 0; k < BINAURAL_CHANNELS; k++ )
    9990             :             {
    9991          48 :                 set16_fx( hDiracDecBin->processMtxDecRe_fx[j][k], 0, nBins );
    9992          48 :                 set16_fx( hDiracDecBin->processMtxDecIm_fx[j][k], 0, nBins );
    9993             :             }
    9994          24 :             hDiracDecBin->q_processMtx = Q15;
    9995          24 :             hDiracDecBin->q_processMtxSCCR = Q15;
    9996          24 :             hDiracDecBin->q_processMtxPrev = Q15;
    9997          24 :             hDiracDecBin->q_processMtxPrevSCCR = Q15;
    9998          24 :             hDiracDecBin->q_processMtxDec = Q15;
    9999          24 :             hDiracDecBin->q_processMtxDecPrev = Q15;
   10000          24 :             move16();
   10001          24 :             move16();
   10002          24 :             move16();
   10003          24 :             move16();
   10004          24 :             move16();
   10005          24 :             move16();
   10006          24 :             set_zero_fx( hDiracDecBin->ChEnePrev_fx[j], nBins );
   10007          24 :             set_zero_fx( hDiracDecBin->ChEneOutPrev_fx[j], nBins );
   10008          24 :             set16_fx( hDiracDecBin->ChEnePrev_e[j], 0, nBins );
   10009          24 :             set16_fx( hDiracDecBin->ChEneOutPrev_e[j], 0, nBins );
   10010             :         }
   10011          12 :         set_zero_fx( hDiracDecBin->ChCrossRePrev_fx, nBins );
   10012          12 :         set_zero_fx( hDiracDecBin->ChCrossImPrev_fx, nBins );
   10013          12 :         set_zero_fx( hDiracDecBin->ChCrossReOutPrev_fx, nBins );
   10014          12 :         set_zero_fx( hDiracDecBin->ChCrossImOutPrev_fx, nBins );
   10015          12 :         set16_fx( hDiracDecBin->ChCrossRePrev_e, 0, nBins );
   10016          12 :         set16_fx( hDiracDecBin->ChCrossImPrev_e, 0, nBins );
   10017          12 :         set16_fx( hDiracDecBin->ChCrossReOutPrev_e, 0, nBins );
   10018          12 :         set16_fx( hDiracDecBin->ChCrossImOutPrev_e, 0, nBins );
   10019          12 :         hDiracDecBin->renderStereoOutputInsteadOfBinaural = 0;
   10020          12 :         move16();
   10021             : 
   10022         732 :         FOR( bin = 0; bin < nBins; bin++ )
   10023             :         {
   10024         720 :             binCenterFreq_fx = L_mult0( extract_l( L_shr( output_Fs, 1 ) ), div_s( add( shl( bin, 1 ), 1 ), shl( nBins, 1 ) ) ) /*( (float) bin + 0.5f ) / (float) nBins * ( (float) output_Fs / 2.0f )*/; /*Q15*/
   10025             :             /* These formulas and values are from Christian Borss's publication for binaural diffuse field coherence */
   10026         720 :             tmp = BASOP_Util_Divide3232_Scale( binCenterFreq_fx, L_shl( 2700, Q15 ), &tmp_e );
   10027         720 :             IF( tmp_e < 0 )
   10028             :             {
   10029          36 :                 tmp = shl( tmp, tmp_e ); /*q15*/
   10030          36 :                 tmp_e = 0;
   10031          36 :                 move16();
   10032             :             }
   10033         720 :             tmpFloat_fx = s_max( 0, sub( shl_sat( 1, sub( 15, tmp_e ) ), tmp ) ) /*max( 0.0f, 1.0f - binCenterFreq / 2700.0f )*/;                                                             /*Q30*/
   10034         720 :             tmp2 = extract_l( Mult_32_32( binCenterFreq_fx, 1952258 /*=2^31*180/(550)/360*/ ) % 32767 );                                                                                      //*binCenterFreq_fx * EVS_PI / 550.0f*/
   10035         720 :             hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( L_mult0( divide3232( tmpFloat_fx, Mult_32_16( binCenterFreq_fx, 187 /*2^15*pi/550*/ ) ), getSineWord16R2( tmp2 ) ), tmp_e ); /*tmpFloat * sinf( binCenterFreq * EVS_PI / 550.0f ) / ( binCenterFreq * EVS_PI / 550.0f );*/
   10036         720 :             hDiracDecBin->diffuseFieldCoherence_fx[bin] = L_shl( hDiracDecBin->diffuseFieldCoherence_fx[bin], 1 );                                                                            /* Q31 */
   10037         720 :             move32();
   10038         720 :             move32();
   10039             :         }
   10040             : 
   10041             :         /* No SPAR in external renderer so set directive diffuse field coherence tables to zero */
   10042          12 :         set_zero_fx( hDiracDecBin->diffuseFieldCoherenceX_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS );
   10043          12 :         set_zero_fx( hDiracDecBin->diffuseFieldCoherenceY_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS );
   10044          12 :         set_zero_fx( hDiracDecBin->diffuseFieldCoherenceZ_fx, BINAURAL_COHERENCE_DIFFERENCE_BINS );
   10045             : 
   10046          12 :         IF( EQ_16( renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) /* Indication of binaural rendering without room effect */
   10047             :         {
   10048           8 :             set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28 /*1.0f Q28*/, CLDFB_NO_CHANNELS_MAX );
   10049           8 :             hDiracDecBin->q_earlyPartEneCorrection = Q28;
   10050           8 :             move16();
   10051           8 :             hDiracDecBin->hReverb = NULL;
   10052             :         }
   10053           4 :         ELSE IF( EQ_16( renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) /* Indication of binaural rendering with room effect */
   10054             :         {
   10055             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
   10056             : #ifdef NONBE_FIX_981_PARAMBIN_DEFAULT_EARLY_PART
   10057           0 :             IF( EQ_32( *inputMasa->base.ctx.pOutConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) )
   10058             :             {
   10059           0 :                 Copy32( ( *phHrtfParambin )->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
   10060             : #ifdef FIX_587_DEFAULT_REVERB
   10061           0 :                 pRoomAcoustics = NULL;
   10062             : #endif
   10063             :             }
   10064             :             ELSE
   10065             :             {
   10066           0 :                 set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28, CLDFB_NO_CHANNELS_MAX );
   10067             : #ifdef FIX_587_DEFAULT_REVERB
   10068           0 :                 pRoomAcoustics = &( hRendCfg->roomAcoustics );
   10069             : #endif
   10070             :             }
   10071             : #else
   10072             :             Copy32( ( *phHrtfParambin )->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
   10073             : #endif
   10074             : #else
   10075             :             Copy32( hHrtfParambin->parametricEarlyPartEneCorrection_fx, hDiracDecBin->earlyPartEneCorrection_fx, nBins );
   10076             : #endif
   10077           0 :             hDiracDecBin->q_earlyPartEneCorrection = Q28;
   10078           0 :             move16();
   10079             : 
   10080           0 :             IF( hDiracDecBin->hReverb == NULL && pos_idx == 0 ) /* open reverb only for the main direction */
   10081             :             {
   10082             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
   10083             : #ifdef FIX_587_DEFAULT_REVERB
   10084             : #ifdef FIX_1139_REV_COLORATION_SHORT_T60
   10085           0 :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx, hDiracDecBin->earlyPartEneCorrection_fx ) ), IVAS_ERR_OK ) )
   10086             : #else
   10087             :                 if ( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, pRoomAcoustics, output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
   10088             : #endif
   10089             : #else
   10090             :                 if ( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRendCfg->roomAcoustics ), output_Fs, ( *phHrtfParambin )->parametricReverberationTimes_fx, ( *phHrtfParambin )->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
   10091             : #endif
   10092             : #else
   10093             :                 IF( NE_32( ( error = ivas_binaural_reverb_init( &hDiracDecBin->hReverb, hHrtfStatistics, nBins, CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES, &( hRendCfg->roomAcoustics ), output_Fs, hHrtfParambin->parametricReverberationTimes_fx, hHrtfParambin->parametricReverberationEneCorrections_fx ) ), IVAS_ERR_OK ) )
   10094             : #endif
   10095             :                 {
   10096           0 :                     return error;
   10097             :                 }
   10098             :             }
   10099             :         }
   10100           4 :         ELSE IF( EQ_16( renderer_type, RENDERER_STEREO_PARAMETRIC ) )
   10101             :         {
   10102           4 :             set32_fx( hDiracDecBin->earlyPartEneCorrection_fx, ONE_IN_Q28 /*1.0f Q28*/, CLDFB_NO_CHANNELS_MAX );
   10103           4 :             hDiracDecBin->q_earlyPartEneCorrection = Q28;
   10104           4 :             move16();
   10105           4 :             hDiracDecBin->hReverb = NULL;
   10106           4 :             hDiracDecBin->renderStereoOutputInsteadOfBinaural = 1;
   10107           4 :             move16();
   10108             :         }
   10109             :         ELSE /* Not valid renderer type for this renderer */
   10110             :         {
   10111           0 :             assert( false );
   10112             :         }
   10113             : 
   10114          12 :         IF( pos_idx == 0 ) /* open decorrelator only for the main direction */
   10115             :         {
   10116             :             /* Always open frequency domain decorrelator */
   10117          12 :             ivas_dirac_dec_get_frequency_axis_fx( frequency_axis_fx, output_Fs, nBins );
   10118             : 
   10119          12 :             IF( NE_32( ( error = ivas_dirac_dec_decorr_open_fx( &( hDiracDecBin->h_freq_domain_decorr_ap_params ),
   10120             :                                                                 &( hDiracDecBin->h_freq_domain_decorr_ap_state ),
   10121             :                                                                 nBins,
   10122             :                                                                 BINAURAL_CHANNELS,
   10123             :                                                                 BINAURAL_CHANNELS,
   10124             :                                                                 DIRAC_SYNTHESIS_PSD_LS,
   10125             :                                                                 frequency_axis_fx,
   10126             :                                                                 BINAURAL_CHANNELS,
   10127             :                                                                 output_Fs ) ),
   10128             :                        IVAS_ERR_OK ) )
   10129             :             {
   10130           0 :                 return error;
   10131             :             }
   10132             :         }
   10133             : 
   10134             :         /* External renderer uses constant regularization factor */
   10135          12 :         hDiracDecBin->reqularizationFactor_fx = 6554; /* 0.4f in Q14 */
   10136          12 :         move16();
   10137             : 
   10138             : #ifdef NONBE_FIX_991_PARAMBIN_BINARY_HRTF
   10139          12 :         hDiracDecBin->phHrtfParambin = phHrtfParambin;
   10140             : #endif
   10141             : 
   10142          12 :         inputMasa->hMasaExtRend->hDiracDecBin[pos_idx] = hDiracDecBin;
   10143             :     }
   10144             : 
   10145          12 :     return error;
   10146             : }
   10147             : 
   10148             : 
   10149          48 : static ivas_error initMasaExtRenderer(
   10150             :     input_masa *inputMasa,
   10151             :     const AUDIO_CONFIG outConfig,
   10152             :     const RENDER_CONFIG_DATA *hRendCfg,
   10153             :     hrtf_handles *hrtfs )
   10154             : {
   10155             :     Word16 i;
   10156             :     ivas_error error;
   10157             :     MASA_EXT_REND_HANDLE hMasaExtRend;
   10158             : 
   10159          48 :     error = IVAS_ERR_OK;
   10160          48 :     move32();
   10161             : 
   10162          48 :     IF( ( hMasaExtRend = (MASA_EXT_REND_HANDLE) malloc( sizeof( MASA_EXT_REND_DATA ) ) ) == NULL )
   10163             :     {
   10164           0 :         return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for MASA external renderer structure\n" ) );
   10165             :     }
   10166             : 
   10167          48 :     inputMasa->hMasaExtRend = hMasaExtRend;
   10168             : 
   10169             :     /* Default init */
   10170          48 :     hMasaExtRend->renderer_type = RENDERER_DISABLE;
   10171          48 :     move32();
   10172          48 :     hMasaExtRend->hDirACRend = NULL;
   10173          48 :     hMasaExtRend->hSpatParamRendCom = NULL;
   10174         432 :     for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ )
   10175             :     {
   10176         384 :         hMasaExtRend->hDiracDecBin[i] = NULL;
   10177             :     }
   10178          48 :     hMasaExtRend->hReverb = NULL;
   10179          48 :     hMasaExtRend->hHrtfParambin = &hrtfs->hHrtfParambin;
   10180          48 :     hMasaExtRend->hVBAPdata = NULL;
   10181          48 :     hMasaExtRend->hoa_dec_mtx = NULL;
   10182             : 
   10183          48 :     IF( NE_32( ( error = getAudioConfigNumChannels( inputMasa->base.inConfig, &hMasaExtRend->nchan_input ) ), IVAS_ERR_OK ) )
   10184             :     {
   10185           0 :         return error;
   10186             :     }
   10187             : 
   10188          48 :     IF( EQ_32( outConfig, IVAS_AUDIO_CONFIG_LS_CUSTOM ) )
   10189             :     {
   10190           0 :         hMasaExtRend->nchan_output = add( inputMasa->base.ctx.pCustomLsOut->num_spk, inputMasa->base.ctx.pCustomLsOut->num_lfe );
   10191           0 :         move16();
   10192             :     }
   10193          48 :     ELSE IF( NE_32( ( error = getAudioConfigNumChannels( outConfig, &hMasaExtRend->nchan_output ) ), IVAS_ERR_OK ) )
   10194             :     {
   10195           0 :         return error;
   10196             :     }
   10197             : 
   10198          48 :     SWITCH( outConfig )
   10199             :     {
   10200           4 :         case IVAS_AUDIO_CONFIG_MONO:
   10201           4 :             IF( EQ_16( inputMasa->base.inConfig, IVAS_AUDIO_CONFIG_MASA2 ) )
   10202             :             {
   10203           2 :                 hMasaExtRend->renderer_type = RENDERER_DIRAC;
   10204           2 :                 move32();
   10205             :             }
   10206             :             ELSE
   10207             :             {
   10208             :                 /* 1TC MASA to mono does not need rendering. */
   10209           2 :                 hMasaExtRend->renderer_type = RENDERER_DISABLE;
   10210           2 :                 move32();
   10211             :             }
   10212           4 :             BREAK;
   10213             : 
   10214           4 :         case IVAS_AUDIO_CONFIG_STEREO:
   10215           4 :             hMasaExtRend->renderer_type = RENDERER_STEREO_PARAMETRIC;
   10216           4 :             move32();
   10217           4 :             BREAK;
   10218             : 
   10219          32 :         case IVAS_AUDIO_CONFIG_5_1:
   10220             :         case IVAS_AUDIO_CONFIG_7_1:
   10221             :         case IVAS_AUDIO_CONFIG_5_1_2:
   10222             :         case IVAS_AUDIO_CONFIG_5_1_4:
   10223             :         case IVAS_AUDIO_CONFIG_7_1_4:
   10224             :         case IVAS_AUDIO_CONFIG_LS_CUSTOM:
   10225             :         case IVAS_AUDIO_CONFIG_FOA:
   10226             :         case IVAS_AUDIO_CONFIG_HOA2:
   10227             :         case IVAS_AUDIO_CONFIG_HOA3:
   10228          32 :             hMasaExtRend->renderer_type = RENDERER_DIRAC;
   10229          32 :             move32();
   10230          32 :             BREAK;
   10231             : 
   10232           8 :         case IVAS_AUDIO_CONFIG_BINAURAL:
   10233             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM:
   10234             :         case IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED:
   10235           8 :             hMasaExtRend->renderer_type = RENDERER_BINAURAL_PARAMETRIC;
   10236           8 :             move32();
   10237           8 :             BREAK;
   10238             : 
   10239           0 :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR:
   10240             :         case IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB:
   10241           0 :             hMasaExtRend->renderer_type = RENDERER_BINAURAL_PARAMETRIC_ROOM;
   10242           0 :             move32();
   10243           0 :             BREAK;
   10244             : 
   10245           0 :         default:
   10246           0 :             return ( IVAS_ERROR( IVAS_ERR_IO_CONFIG_PAIR_NOT_SUPPORTED, "Wrong output config for MASA input in external renderer\n" ) );
   10247             :     }
   10248             : 
   10249          48 :     IF( NE_16( hMasaExtRend->renderer_type, RENDERER_DISABLE ) )
   10250             :     {
   10251             :         Word16 subframe;
   10252          46 :         IF( NE_32( ( error = ivas_spat_hSpatParamRendCom_config_fx( &hMasaExtRend->hSpatParamRendCom, DIRAC_OPEN, 0, MASA_FORMAT, MC_MODE_NONE, *( inputMasa->base.ctx.pOutSampleRate ), 0, 1 ) ), IVAS_ERR_OK ) )
   10253             :         {
   10254           0 :             return error;
   10255             :         }
   10256             :         /* Simple population of the metadata index map as no adaptation is present */
   10257          46 :         set16_fx( hMasaExtRend->hSpatParamRendCom->render_to_md_map, 0, MAX_JBM_SUBFRAMES_5MS * JBM_CLDFB_SLOTS_IN_SUBFRAME );
   10258         230 :         FOR( subframe = 0; subframe < MAX_PARAM_SPATIAL_SUBFRAMES; subframe++ )
   10259             :         {
   10260         184 :             hMasaExtRend->hSpatParamRendCom->render_to_md_map[subframe] = subframe;
   10261         184 :             move16();
   10262             :         }
   10263          46 :         hMasaExtRend->hSpatParamRendCom->subframes_rendered = 0;
   10264          46 :         move16();
   10265             :     }
   10266             : 
   10267          48 :     IF( EQ_16( hMasaExtRend->renderer_type, RENDERER_DIRAC ) )
   10268             :     {
   10269          34 :         IF( NE_32( ( error = ivas_masa_ext_rend_dirac_rend_init( inputMasa ) ), IVAS_ERR_OK ) )
   10270             :         {
   10271           0 :             return error;
   10272             :         }
   10273             :     }
   10274             : 
   10275          48 :     test();
   10276          48 :     test();
   10277          48 :     IF( EQ_16( hMasaExtRend->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_16( hMasaExtRend->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_16( hMasaExtRend->renderer_type, RENDERER_STEREO_PARAMETRIC ) )
   10278             :     {
   10279          12 :         IF( NE_16( hMasaExtRend->renderer_type, RENDERER_STEREO_PARAMETRIC ) )
   10280             :         {
   10281           8 :             IF( NE_32( ( error = ivas_dirac_dec_binaural_copy_hrtfs_fx( inputMasa->hMasaExtRend->hHrtfParambin ) ), IVAS_ERR_OK ) )
   10282             :             {
   10283           0 :                 return error;
   10284             :             }
   10285             :         }
   10286          12 :         if ( NE_32( ( error = ivas_masa_ext_rend_parambin_init( inputMasa, hRendCfg, hrtfs->hHrtfStatistics ) ), IVAS_ERR_OK ) )
   10287             :         {
   10288           0 :             return error;
   10289             :         }
   10290             :     }
   10291             : 
   10292             :     /* Init CLDFB for analysis & synthesis if renderer is used. Otherwise, NULL. */
   10293         144 :     FOR( i = 0; i < MASA_MAX_TRANSPORT_CHANNELS; i++ )
   10294             :     {
   10295          96 :         hMasaExtRend->cldfbAnaRend[i] = NULL;
   10296             :     }
   10297             : 
   10298         816 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
   10299             :     {
   10300         768 :         hMasaExtRend->cldfbSynRend[i] = NULL;
   10301             :     }
   10302             : 
   10303          48 :     IF( NE_32( hMasaExtRend->renderer_type, RENDERER_DISABLE ) )
   10304             :     {
   10305         116 :         FOR( i = 0; i < hMasaExtRend->nchan_input; i++ )
   10306             :         {
   10307          70 :             IF( NE_32( ( error = openCldfb_ivas_fx( &( hMasaExtRend->cldfbAnaRend[i] ), CLDFB_ANALYSIS, *inputMasa->base.ctx.pOutSampleRate, CLDFB_PROTOTYPE_5_00MS, DEC ) ), IVAS_ERR_OK ) )
   10308             :             {
   10309           0 :                 return error;
   10310             :             }
   10311             :         }
   10312             : 
   10313         364 :         FOR( i = 0; i < hMasaExtRend->nchan_output; i++ )
   10314             :         {
   10315         318 :             IF( NE_32( ( error = openCldfb_ivas_fx( &( hMasaExtRend->cldfbSynRend[i] ), CLDFB_SYNTHESIS, *inputMasa->base.ctx.pOutSampleRate, CLDFB_PROTOTYPE_5_00MS, DEC ) ), IVAS_ERR_OK ) )
   10316             :             {
   10317           0 :                 return error;
   10318             :             }
   10319             :         }
   10320             :     }
   10321             : 
   10322          48 :     inputMasa->hMasaExtRend = hMasaExtRend;
   10323             : 
   10324          48 :     return IVAS_ERR_OK;
   10325             : }
   10326             : 
   10327             : 
   10328         666 : static void freeMasaExtRenderer(
   10329             :     MASA_EXT_REND_HANDLE *hMasaExtRendOut )
   10330             : {
   10331             :     MASA_EXT_REND_HANDLE hMasaExtRend;
   10332             :     Word16 i;
   10333             : 
   10334         666 :     test();
   10335         666 :     IF( hMasaExtRendOut == NULL || *hMasaExtRendOut == NULL )
   10336             :     {
   10337         618 :         return;
   10338             :     }
   10339             : 
   10340          48 :     hMasaExtRend = *hMasaExtRendOut;
   10341             : 
   10342          48 :     IF( hMasaExtRend->hDirACRend != NULL )
   10343             :     {
   10344          34 :         ivas_dirac_rend_close_fx( &hMasaExtRend->hDirACRend );
   10345             :     }
   10346             : 
   10347          48 :     IF( hMasaExtRend->hSpatParamRendCom != NULL )
   10348             :     {
   10349          46 :         ivas_spat_hSpatParamRendCom_close_fx( &hMasaExtRend->hSpatParamRendCom );
   10350             :     }
   10351             : 
   10352         432 :     for ( i = 0; i < MAX_HEAD_ROT_POSES; i++ )
   10353             :     {
   10354         384 :         if ( hMasaExtRend->hDiracDecBin[i] != NULL )
   10355             :         {
   10356          12 :             ivas_dirac_dec_close_binaural_data( &hMasaExtRend->hDiracDecBin[i] );
   10357             :         }
   10358             :     }
   10359             : 
   10360          48 :     IF( hMasaExtRend->hReverb != NULL )
   10361             :     {
   10362           0 :         ivas_binaural_reverb_close_fx( &hMasaExtRend->hReverb );
   10363             :     }
   10364             : 
   10365          48 :     IF( hMasaExtRend->hHrtfParambin != NULL )
   10366             :     {
   10367          48 :         ivas_HRTF_parambin_binary_close_fx( hMasaExtRend->hHrtfParambin );
   10368             :     }
   10369             : 
   10370          48 :     IF( hMasaExtRend->hVBAPdata != NULL )
   10371             :     {
   10372          20 :         vbap_free_data_fx( &hMasaExtRend->hVBAPdata );
   10373             :     }
   10374             : 
   10375          48 :     IF( hMasaExtRend->hoa_dec_mtx != NULL )
   10376             :     {
   10377           2 :         free( hMasaExtRend->hoa_dec_mtx );
   10378             :     }
   10379             : 
   10380         144 :     FOR( i = 0; i < MASA_MAX_TRANSPORT_CHANNELS; i++ )
   10381             :     {
   10382          96 :         IF( hMasaExtRend->cldfbAnaRend[i] != NULL )
   10383             :         {
   10384          70 :             deleteCldfb_ivas_fx( &hMasaExtRend->cldfbAnaRend[i] );
   10385             :         }
   10386             :     }
   10387             : 
   10388         816 :     FOR( i = 0; i < MAX_OUTPUT_CHANNELS; i++ )
   10389             :     {
   10390         768 :         IF( hMasaExtRend->cldfbSynRend[i] != NULL )
   10391             :         {
   10392         318 :             deleteCldfb_ivas_fx( &hMasaExtRend->cldfbSynRend[i] );
   10393             :         }
   10394             :     }
   10395             : 
   10396          48 :     free( hMasaExtRend );
   10397          48 :     *hMasaExtRendOut = NULL;
   10398             : 
   10399          48 :     return;
   10400             : }
   10401             : 
   10402       25500 : static void intermidiate_ext_dirac_render(
   10403             :     MASA_EXT_REND_HANDLE hMasaExtRend, /* i/o: MASA renderer structure             */
   10404             :     Word16 to_fix )
   10405             : {
   10406             :     SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom;
   10407       25500 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
   10408             :     DIRAC_DEC_STACK_MEM DirAC_mem;
   10409             :     Word16 ch;
   10410             :     DIRAC_REND_HANDLE hDirACRend;
   10411             :     Word16 subframe_idx;
   10412             :     Word16 slot_idx;
   10413             :     Word16 nchan_transport;
   10414             :     Word16 tmp;
   10415             : 
   10416       25500 :     hDirACRend = hMasaExtRend->hDirACRend;
   10417       25500 :     hSpatParamRendCom = hMasaExtRend->hSpatParamRendCom;
   10418       25500 :     nchan_transport = hMasaExtRend->nchan_input;
   10419             :     DIRAC_OUTPUT_SYNTHESIS_STATE *h_dirac_output_synthesis_state;
   10420             : 
   10421       25500 :     h_dirac_output_synthesis_state = &( hDirACRend->h_output_synthesis_psd_state );
   10422             : 
   10423       25500 :     subframe_idx = hSpatParamRendCom->subframes_rendered;
   10424       25500 :     move16();
   10425             : 
   10426       25500 :     DirAC_mem = hDirACRend->stack_mem;
   10427             : 
   10428       25500 :     IF( to_fix )
   10429             :     {
   10430       12750 :         DirAC_mem.reference_power_smooth_q[0] = DirAC_mem.reference_power_q[0] = Q31;
   10431       12750 :         DirAC_mem.reference_power_smooth_q[1] = DirAC_mem.reference_power_q[1] = Q31;
   10432       12750 :         move16();
   10433       12750 :         move16();
   10434       12750 :         move16();
   10435       43486 :         FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ )
   10436             :         {
   10437       30736 :             Scale_sig32( hDirACRend->h_output_synthesis_psd_state.direct_responses_fx, i_mult( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ), sub( Q30, hDirACRend->h_output_synthesis_psd_state.direct_responses_q ) ); /* Q30 */
   10438       30736 :             hDirACRend->h_output_synthesis_psd_state.direct_responses_q = Q30;
   10439       30736 :             move16();
   10440             :         }
   10441             : 
   10442       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_fx )
   10443             :         {
   10444       12750 :             Word16 shift = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_len );
   10445       12750 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_len, shift ); /* Q(hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth + shift) */
   10446       12750 :             hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth = add( hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth, shift );
   10447       12750 :             move16();
   10448             :         }
   10449       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_fx )
   10450             :         {
   10451       12750 :             Word16 shift = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_len );
   10452       12750 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_cross_dir_smooth_prev_len, shift ); /* Q(hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev + shift) */
   10453       12750 :             hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev = add( hDirACRend->h_output_synthesis_psd_state.q_cy_cross_dir_smooth_prev, shift );
   10454       12750 :             move16();
   10455             :         }
   10456             : 
   10457       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_fx )
   10458             :         {
   10459       10500 :             Word16 shift = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_fx, imult1616( hDirACRend->num_outputs_dir, hSpatParamRendCom->num_freq_bands ) );
   10460       10500 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_len, shift ); /* Q(hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth + shift) */
   10461       10500 :             hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth = add( hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth, shift );
   10462       10500 :             move16();
   10463             :         }
   10464             : 
   10465       12750 :         Word16 num_channels_dir = hDirACRend->num_outputs_dir;
   10466       12750 :         move16();
   10467             : 
   10468       12750 :         IF( EQ_16( hDirACRend->synthesisConf, DIRAC_SYNTHESIS_PSD_LS ) )
   10469             :         {
   10470        7500 :             num_channels_dir = hDirACRend->hOutSetup.nchan_out_woLFE;
   10471        7500 :             move16();
   10472             :         }
   10473             : 
   10474       12750 :         IF( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx )
   10475             :         {
   10476       12750 :             tmp = L_norm_arr( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, imult1616( num_channels_dir, hSpatParamRendCom->num_freq_bands ) );
   10477       12750 :             scale_sig32( h_dirac_output_synthesis_state->cy_auto_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_len, tmp ); /* Q(h_dirac_output_synthesis_state->q_cy_auto_diff_smooth + tmp) */
   10478       12750 :             h_dirac_output_synthesis_state->q_cy_auto_diff_smooth = add( h_dirac_output_synthesis_state->q_cy_auto_diff_smooth, tmp );
   10479       12750 :             move16();
   10480             :         }
   10481             : 
   10482       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_fx )
   10483             :         {
   10484       12750 :             tmp = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_len );
   10485       12750 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_diff_smooth_prev_len, tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev + tmp) */
   10486       12750 :             hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev = add( hDirACRend->h_output_synthesis_psd_state.q_cy_auto_diff_smooth_prev, tmp );
   10487       12750 :             move16();
   10488             :         }
   10489             : 
   10490       12750 :         scale_sig32( hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_fx, hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_len, sub( Q26, hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_q ) ); /* Q26 */
   10491       12750 :         hDirACRend->h_output_synthesis_psd_state.gains_dir_prev_q = Q26;
   10492       12750 :         move16();
   10493       12750 :         scale_sig32( hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_fx, hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_len, sub( Q26, hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_q ) ); /* Q26 */
   10494       12750 :         hDirACRend->h_output_synthesis_psd_state.gains_diff_prev_q = Q26;
   10495       12750 :         move16();
   10496       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev_fx )
   10497             :         {
   10498       10500 :             Word16 shift = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev_fx, imult1616( hSpatParamRendCom->num_freq_bands, hDirACRend->num_outputs_dir ) );
   10499       10500 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.cy_auto_dir_smooth_prev_len, shift ); /* Q(hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth_prev + shift) */
   10500       10500 :             hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth_prev = add( hDirACRend->h_output_synthesis_psd_state.q_cy_auto_dir_smooth_prev, shift );
   10501       10500 :             move16();
   10502             :         }
   10503             : 
   10504       12750 :         IF( EQ_16( hDirACRend->proto_signal_decorr_on, 1 ) )
   10505             :         {
   10506       12000 :             tmp = L_norm_arr( hDirACRend->h_freq_domain_decorr_ap_state->decorr_buffer_fx, hDirACRend->h_freq_domain_decorr_ap_state->decorr_buffer_len );
   10507       12000 :             scale_sig32( hDirACRend->h_freq_domain_decorr_ap_state->decorr_buffer_fx, hDirACRend->h_freq_domain_decorr_ap_state->decorr_buffer_len, tmp ); /* Q(hDirACRend->h_freq_domain_decorr_ap_state->q_decorr_buffer + tmp) */
   10508       12000 :             hDirACRend->h_freq_domain_decorr_ap_state->q_decorr_buffer = add( hDirACRend->h_freq_domain_decorr_ap_state->q_decorr_buffer, tmp );
   10509       12000 :             move16();
   10510             :         }
   10511             : 
   10512       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_len > 0 )
   10513             :         {
   10514             :             Word16 shift, norm1, norm2;
   10515             :             Word32 tmp1, tmp2;
   10516       12000 :             maximum_abs_32_fx( hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx, hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_len, &tmp2 );
   10517       12000 :             maximum_abs_32_fx( hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx, hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_len, &tmp1 );
   10518             : 
   10519       12000 :             IF( tmp1 == 0 )
   10520             :             {
   10521          32 :                 norm1 = 31;
   10522          32 :                 move16();
   10523             :             }
   10524             :             ELSE
   10525             :             {
   10526       11968 :                 norm1 = norm_l( tmp1 );
   10527             :             }
   10528             : 
   10529       12000 :             IF( tmp2 == 0 )
   10530             :             {
   10531          32 :                 norm2 = 31;
   10532          32 :                 move16();
   10533             :             }
   10534             :             ELSE
   10535             :             {
   10536       11968 :                 norm2 = norm_l( tmp2 );
   10537             :             }
   10538             : 
   10539       12000 :             shift = s_min( norm1, norm2 );
   10540             : 
   10541       12000 :             Word16 hr_exp = sub( 31, shift );
   10542             : 
   10543       12000 :             Scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_fx, hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_len, sub( sub( 31, hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q ), hr_exp ) ); /* Q(31 - hr_exp) */
   10544       12000 :             hDirACRend->h_output_synthesis_psd_state.proto_diffuse_buffer_f_q = sub( 31, hr_exp );
   10545       12000 :             move16();
   10546             :         }
   10547             : 
   10548       43486 :         FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[subframe_idx]; slot_idx++ )
   10549             :         {
   10550             :             /* CLDFB Analysis*/
   10551       77744 :             FOR( ch = 0; ch < nchan_transport; ch++ )
   10552             :             {
   10553       47008 :                 hMasaExtRend->cldfbAnaRend[ch]->Q_cldfb_state = Q11;
   10554       47008 :                 move16();
   10555             :             }
   10556             :         }
   10557       12750 :         hDirACRend->proto_frame_dec_f_q = sub( 31, hDirACRend->proto_frame_dec_f_q );
   10558       12750 :         move16();
   10559             : 
   10560       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx )
   10561             :         {
   10562       10500 :             tmp = 0;
   10563       10500 :             move16();
   10564       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10565             :             {
   10566       81750 :                 tmp = s_min( tmp, L_norm_arr( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx + slot_idx, s_min( hSpatParamRendCom->num_freq_bands, CLDFB_NO_CHANNELS_HALF ) ) );
   10567             :             }
   10568       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10569             :             {
   10570       81750 :                 scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx + slot_idx, s_min( hSpatParamRendCom->num_freq_bands, CLDFB_NO_CHANNELS_HALF ), tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q + tmp) */
   10571             :             }
   10572       10500 :             hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q[0] = add( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q[0], tmp );
   10573       10500 :             move16();
   10574       10500 :             tmp = 0;
   10575       10500 :             move16();
   10576       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10577             :             {
   10578       81750 :                 tmp = s_min( tmp, L_norm_arr( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx + slot_idx + CLDFB_NO_CHANNELS_HALF, s_max( 0, sub( hSpatParamRendCom->num_freq_bands, CLDFB_NO_CHANNELS_HALF ) ) ) );
   10579             :             }
   10580       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10581             :             {
   10582       81750 :                 scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_fx + slot_idx + CLDFB_NO_CHANNELS_HALF, s_max( 0, sub( hSpatParamRendCom->num_freq_bands, CLDFB_NO_CHANNELS_HALF ) ), tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q + tmp) */
   10583             :             }
   10584       10500 :             hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q[1] = add( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_q[1], tmp );
   10585       10500 :             move16();
   10586       10500 :             tmp = 0;
   10587       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10588             :             {
   10589       81750 :                 tmp = s_min( tmp, L_norm_arr( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_fx, s_min( CLDFB_NO_CHANNELS_HALF, hSpatParamRendCom->num_freq_bands ) ) );
   10590             :             }
   10591       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10592             :             {
   10593       81750 :                 scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_fx, s_min( CLDFB_NO_CHANNELS_HALF, hSpatParamRendCom->num_freq_bands ), tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q + tmp) */
   10594             :             }
   10595       10500 :             hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q[0] = add( tmp, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q[0] );
   10596       10500 :             move16();
   10597       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10598             :             {
   10599       81750 :                 tmp = s_min( tmp, L_norm_arr( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_fx + CLDFB_NO_CHANNELS_HALF, s_max( 0, sub( hSpatParamRendCom->num_freq_bands, CLDFB_NO_CHANNELS_HALF ) ) ) );
   10600             :             }
   10601       92250 :             FOR( slot_idx = 0; slot_idx < hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_len; slot_idx = add( slot_idx, hSpatParamRendCom->num_freq_bands ) )
   10602             :             {
   10603       81750 :                 scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_fx + CLDFB_NO_CHANNELS_HALF, s_max( 0, sub( hSpatParamRendCom->num_freq_bands, CLDFB_NO_CHANNELS_HALF ) ), tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q + tmp) */
   10604             :             }
   10605       10500 :             hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q[1] = add( tmp, hDirACRend->h_output_synthesis_psd_state.proto_power_smooth_prev_q[1] );
   10606       10500 :             move16();
   10607             :         }
   10608       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_fx != NULL )
   10609             :         {
   10610             : 
   10611       10500 :             tmp = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_len );
   10612       10500 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_len, tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q + tmp) */
   10613       10500 :             hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q = add( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_q, tmp );
   10614       10500 :             move16();
   10615             :         }
   10616             : 
   10617       12750 :         IF( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_fx != NULL )
   10618             :         {
   10619        9750 :             tmp = L_norm_arr( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_len );
   10620        9750 :             scale_sig32( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_fx, hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_len, tmp ); /* Q(hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_q + tmp) */
   10621        9750 :             hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_q = add( hDirACRend->h_output_synthesis_psd_state.proto_power_diff_smooth_prev_q, tmp );
   10622        9750 :             move16();
   10623             :         }
   10624             :     }
   10625             :     ELSE
   10626             :     {
   10627       43350 :         FOR( slot_idx = 0; slot_idx < hSpatParamRendCom->subframe_nbslots[hSpatParamRendCom->subframes_rendered]; slot_idx++ )
   10628             :         {
   10629             :             /* CLDFB Analysis*/
   10630       77400 :             FOR( ch = 0; ch < nchan_transport; ch++ )
   10631             :             {
   10632       46800 :                 scale_sig32( hMasaExtRend->cldfbAnaRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbAnaRend[ch]->cldfb_size, sub( Q11, hMasaExtRend->cldfbAnaRend[0]->Q_cldfb_state ) ); /* Q11 */
   10633       46800 :                 hMasaExtRend->cldfbAnaRend[ch]->Q_cldfb_state = Q11;
   10634       46800 :                 move16();
   10635             :             }
   10636             :         }
   10637             : 
   10638      123000 :         FOR( ch = 0; ch < hDirACRend->hOutSetup.nchan_out_woLFE + hDirACRend->hOutSetup.num_lfe; ch++ )
   10639             :         {
   10640      110250 :             scale_sig32( hMasaExtRend->cldfbSynRend[ch]->cldfb_state_fx, hMasaExtRend->cldfbSynRend[ch]->cldfb_size, sub( Q11, hMasaExtRend->cldfbSynRend[0]->Q_cldfb_state ) ); /* Q11 */
   10641      110250 :             hMasaExtRend->cldfbSynRend[ch]->Q_cldfb_state = Q11;
   10642      110250 :             move16();
   10643             :         }
   10644             :     }
   10645             : 
   10646       25500 :     return;
   10647             : }
   10648             : 
   10649             : 
   10650         666 : static ivas_error printConfigInfo_rend(
   10651             :     IVAS_REND_HANDLE hIvasRend /* i  : IVAS renderer handle     */
   10652             : )
   10653             : {
   10654             :     ivas_error error;
   10655             :     Word8 config_str[50];
   10656             : 
   10657             :     /*-----------------------------------------------------------------*
   10658             :      * Print output audio configuration
   10659             :      *-----------------------------------------------------------------*/
   10660             : 
   10661         666 :     IF( NE_32( ( error = get_channel_config( hIvasRend->outputConfig, &config_str[0] ) ), IVAS_ERR_OK ) )
   10662             :     {
   10663           0 :         return error;
   10664             :     }
   10665             : 
   10666         666 :     fprintf( stdout, "Output configuration:   %s\n", config_str );
   10667             : 
   10668             :     /*-----------------------------------------------------------------*
   10669             :      * Print renderer configurations
   10670             :      *-----------------------------------------------------------------*/
   10671             : 
   10672         666 :     fprintf( stdout, "Output sampling rate:   %d Hz\n", hIvasRend->sampleRateOut );
   10673             : 
   10674         666 :     if ( hIvasRend->headRotData.headRotEnabled )
   10675             :     {
   10676          94 :         fprintf( stdout, "Head-tracking:          ON\n" );
   10677             :     }
   10678             : 
   10679         666 :     test();
   10680         666 :     test();
   10681         666 :     test();
   10682         666 :     test();
   10683         666 :     IF( EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL ) ||
   10684             :         EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) ||
   10685             :         EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ||
   10686             :         EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) ||
   10687             :         EQ_16( hIvasRend->outputConfig, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) )
   10688             :     {
   10689         188 :         fprintf( stdout, "Render framesize:       %dms\n", i_mult( hIvasRend->num_subframes, 5 ) );
   10690             :     }
   10691             : 
   10692         666 :     return IVAS_ERR_OK;
   10693             : }
   10694             : 
   10695             : 
   10696             : /*---------------------------------------------------------------------*
   10697             :  * IVAS_REND_PrintInputConfig()
   10698             :  *
   10699             :  *
   10700             :  *---------------------------------------------------------------------*/
   10701             : 
   10702         729 : void IVAS_REND_PrintInputConfig(
   10703             :     const IVAS_AUDIO_CONFIG inputConfig /* i  : input audio configuration    */
   10704             : )
   10705             : {
   10706             :     Word8 config_str[50];
   10707             : 
   10708         729 :     get_channel_config( inputConfig, &config_str[0] );
   10709         729 :     fprintf( stdout, "Input configuration:    %s\n", config_str );
   10710             : 
   10711         729 :     return;
   10712             : }
   10713             : 
   10714             : 
   10715             : /*---------------------------------------------------------------------*
   10716             :  * IVAS_REND_PrintConfig()
   10717             :  *
   10718             :  *
   10719             :  *---------------------------------------------------------------------*/
   10720             : 
   10721         666 : ivas_error IVAS_REND_PrintConfig(
   10722             :     IVAS_REND_HANDLE hIvasRend /* i  : IVAS renderer handle    */
   10723             : )
   10724             : {
   10725         666 :     if ( hIvasRend == NULL )
   10726             :     {
   10727           0 :         return IVAS_ERR_UNEXPECTED_NULL_POINTER;
   10728             :     }
   10729             : 
   10730         666 :     return printConfigInfo_rend( hIvasRend );
   10731             : }
   10732             : 
   10733             : 
   10734             : /*---------------------------------------------------------------------*
   10735             :  * IVAS_REND_PrintDisclaimer()
   10736             :  *
   10737             :  * Print IVAS disclaimer to console
   10738             :  *---------------------------------------------------------------------*/
   10739             : 
   10740         666 : void IVAS_REND_PrintDisclaimer( void )
   10741             : {
   10742         666 :     print_disclaimer( stderr );
   10743             : 
   10744         666 :     return;
   10745             : }

Generated by: LCOV version 1.14