LCOV - code coverage report
Current view: top level - lib_rend - lib_rend_fx.c (source / functions) Hit Total Coverage
Test: Coverage on main @ da9cc8ead0679b4682d329fdff98cf1616159273 Lines: 3119 4427 70.5 %
Date: 2025-10-13 22:24:20 Functions: 136 171 79.5 %

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

Generated by: LCOV version 1.14