Commit 4882e387 authored by Archit Tamarapu's avatar Archit Tamarapu
Browse files

Merge branch 'Philips/external-renderer-api2' into 'FhG/external-renderer'

Render Config File for External Renderer

See merge request !239
parents bce63a80 72bb8776
Loading
Loading
Loading
Loading
Loading
+36 −0
Original line number Diff line number Diff line
@@ -658,6 +658,42 @@ int main(
        exit( -1 );
    }

    /* === Configure === */
    if ( ( error = IVAS_REND_InitConfig( hIvasRend, headRotReader != NULL, strlen( args.renderConfigFilePath ) != 0 ) ) != IVAS_ERR_OK )
    {
        exit( -1 );
    }

    if ( args.renderConfigFilePath[0] != '\0' )
    {
        IVAS_RENDER_CONFIG_DATA renderConfig;

        /* sanity check */
        if ( args.outConfig.audioConfig != IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
        {
            fprintf( stderr, "\nExternal Renderer Config is supported only when BINAURAL_ROOM is used as output. Exiting. \n" );
            exit( -1 );
        }

        if ( ( error = IVAS_REND_GetRenderConfig( hIvasRend, &renderConfig ) ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "\nIVAS_DEC_GetRenderConfig failed\n" );
            exit( -1 );
        }

        if ( RenderConfigReader_read( renderConfigReader, &renderConfig ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "Failed to read renderer configuration from file %s\n", args.renderConfigFilePath );
            exit( -1 );
        }

        if ( ( error = IVAS_REND_FeedRenderConfig( hIvasRend, renderConfig ) ) != IVAS_ERR_OK )
        {
            fprintf( stderr, "\nIVAS_DEC_FeedRenderConfig failed\n" );
            exit( -1 );
        }
    }

    /* Set up output custom layout configuration */
    if ( args.outConfig.audioConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM )
    {
+19 −16
Original line number Diff line number Diff line
@@ -1146,8 +1146,9 @@ ivas_error ivas_crend_process(

ivas_error ivas_rend_openCrend(
    CREND_WRAPPER *pCrend,
    IVAS_REND_AudioConfig inConfig,
    IVAS_REND_AudioConfig outConfig,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_AudioConfig outConfig,
    RENDER_CONFIG_DATA *hRendCfg,
    const int32_t output_Fs )
{
    /* TODO tmu : Based on ivas_crend_open() - could be harmonized / refactored */
@@ -1162,7 +1163,7 @@ ivas_error ivas_rend_openCrend(

    if ( pCrend->hHrtfCrend == NULL )
    {
        if ( ( error = ivas_rend_initCrend( pCrend, inConfig, outConfig, output_Fs ) ) != IVAS_ERR_OK )
        if ( ( error = ivas_rend_initCrend( pCrend, inConfig, outConfig, hRendCfg, output_Fs ) ) != IVAS_ERR_OK )
        {
            return error;
        }
@@ -1276,15 +1277,18 @@ ivas_error ivas_rend_openCrend(
            hCrend->hTrack = NULL;
        }

        /* TODO tmu : implement renderConfig */
        // if ( ( ( st_ivas->hRenderConfig != NULL ) && st_ivas->hRenderConfig->roomAcoustics.late_reverb_on ) )
        // {
        //     if ( ( error = ivas_reverb_open( &( hCrend->hReverb ), st_ivas->intern_config, hHrtf, st_ivas->hRenderConfig, st_ivas->hDecoderConfig->output_Fs ) ) != IVAS_ERR_OK )
        //     {
        //         return error;
        //     }
        // }
        // else
        if ( ( hRendCfg != NULL ) && ( hRendCfg->roomAcoustics.late_reverb_on ) )
        {
            if ( ( error = ivas_reverb_open( &( hCrend->hReverb ),
                                             getIvasAudioConfigFromRendAudioConfig( inConfig ),
                                             pCrend->hHrtfCrend,
                                             hRendCfg,
                                             output_Fs ) ) != IVAS_ERR_OK )
            {
                return error;
            }
        }
        else
        {
            hCrend->hReverb = NULL;
        }
@@ -1306,6 +1310,7 @@ ivas_error ivas_rend_initCrend(
    CREND_WRAPPER *pCrend,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_AudioConfig outConfig,
    RENDER_CONFIG_DATA *hRendCfg,
    const int32_t output_Fs )
{
    int16_t i, j, tmp;
@@ -1337,9 +1342,7 @@ ivas_error ivas_rend_initCrend(

    /* set BRIR flag */
    use_brir = false;
    /* TODO tmu : pass down render config handle */
    // if ((pCrend->hRenderConfig != NULL && pCrend->hRenderConfig->roomAcoustics.use_brir) || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
    if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
    if ( ( hRendCfg != NULL && hRendCfg->roomAcoustics.use_brir ) || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
    {
        use_brir = true;
    }
@@ -1760,7 +1763,7 @@ ivas_error ivas_rend_closeCrend(
}

/*-----------------------------------------------------------------------------------------*
 * Function ivas_crend_process()
 * Function ivas_rend_crend_Process()
 *
 * Process call for IVAS Crend renderer
 *-----------------------------------------------------------------------------------------*/
+34 −0
Original line number Diff line number Diff line
/******************************************************************************************************

   (C) 2022 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB,
   Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
   Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
   Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
   contributors to this repository. All Rights Reserved.

   This software is protected by copyright law and by international treaties.
   The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB,
   Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD.,
   Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange,
   Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other
   contributors to this repository retain full ownership rights in their respective contributions in
   the software. This notice grants no license of any kind, including but not limited to patent
   license, nor is any license granted by implication, estoppel or otherwise.

   Contributors are required to enter into the IVAS codec Public Collaboration agreement before making
   contributions.

   This software is provided "AS IS", without any express or implied warranties. The software is in the
   development stage. It is intended exclusively for experts who have experience with such software and
   solely for the purpose of inspection. All implied warranties of non-infringement, merchantability
   and fitness for a particular purpose are hereby disclaimed and excluded.

   Any dispute, controversy or claim arising under or in relation to providing this software shall be
   submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in
   accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and
   the United Nations Convention on Contracts on the International Sales of Goods.

*******************************************************************************************************/

#include "ivas_error.h"
#include "lib_rend.h"
#include "ivas_stat_dec.h"
@@ -41,12 +73,14 @@ ivas_error ivas_rend_openCrend(
    CREND_WRAPPER *pCrend,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_AudioConfig outConfig,
    RENDER_CONFIG_DATA *hRendCfg,
    const int32_t output_Fs );

ivas_error ivas_rend_initCrend(
    CREND_WRAPPER *pCrend,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_AudioConfig outConfig,
    RENDER_CONFIG_DATA *hRendCfg,
    const int32_t output_Fs );

ivas_error ivas_rend_closeCrend(
+154 −15
Original line number Diff line number Diff line
@@ -148,10 +148,16 @@ struct IVAS_REND
    input_mc inputsMc[RENDERER_MAX_MC_INPUTS];
    input_sba inputsSba[RENDERER_MAX_SBA_INPUTS];

    IVAS_REND_AudioConfig inputConfig;
    IVAS_REND_AudioConfig outputConfig;
    EFAP_WRAPPER efapOutWrapper;
    IVAS_LSSETUP_CUSTOM_STRUCT customLsOut;

    int8_t enableHeadRotation;
    IVAS_REND_HeadRotData headRotData;

    int8_t rendererConfigEnabled;
    RENDER_CONFIG_DATA *hRendererConfig; /* Renderer config pointer */
};

static IVAS_QUATERNION quaternionInit(
@@ -921,7 +927,8 @@ static CREND_WRAPPER defaultCrendWrapper(
static ivas_error setRendInputActiveIsm(
    void *input,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_InputId id )
    const IVAS_REND_InputId id,
    RENDER_CONFIG_DATA *hRendCfg )
{
    ivas_error error;
    rendering_context rendCtx;
@@ -947,7 +954,11 @@ static ivas_error setRendInputActiveIsm(
    }
    else if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
    {
        error = ivas_rend_openCrend( &inputIsm->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, *rendCtx.pOutSampleRate );
        error = ivas_rend_openCrend( &inputIsm->crendWrapper,
                                     IVAS_REND_AUDIO_CONFIG_7_1_4,
                                     outConfig,
                                     hRendCfg,
                                     *rendCtx.pOutSampleRate );
    }
    if ( error != IVAS_ERR_OK )
    {
@@ -1466,7 +1477,8 @@ static void tmpFixBuggyTdBinRendInit( BINAURAL_TD_OBJECT_RENDERER_HANDLE hBinRen
static ivas_error initMcBinauralRendering(
    input_mc *inputMc,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_AudioConfig outConfig )
    const IVAS_REND_AudioConfig outConfig,
    RENDER_CONFIG_DATA *hRendCfg )
{
    ivas_error error;
    int32_t outSampleRate;
@@ -1512,7 +1524,11 @@ static ivas_error initMcBinauralRendering(
    }

    {
        if ( ( error = ivas_rend_openCrend( &inputMc->crendWrapper, ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) ? IVAS_REND_AUDIO_CONFIG_7_1_4 : inConfig, outConfig, outSampleRate ) ) != IVAS_ERR_OK )
        if ( ( error = ivas_rend_openCrend( &inputMc->crendWrapper,
                                            ( inConfig == IVAS_REND_AUDIO_CONFIG_LS_CUSTOM ) ? IVAS_REND_AUDIO_CONFIG_7_1_4 : inConfig,
                                            outConfig,
                                            hRendCfg,
                                            outSampleRate ) ) != IVAS_ERR_OK )
        {
            return error;
        }
@@ -1579,7 +1595,8 @@ static IVAS_REND_LfeRouting defaultLfeRouting(
static ivas_error setRendInputActiveMc(
    void *input,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_InputId id )
    const IVAS_REND_InputId id,
    RENDER_CONFIG_DATA *hRendCfg )
{
    ivas_error error;
    rendering_context rendCtx;
@@ -1600,7 +1617,7 @@ static ivas_error setRendInputActiveMc(

    if ( outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL || outConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
    {
        if ( ( error = initMcBinauralRendering( inputMc, inConfig, outConfig ) ) != IVAS_ERR_OK )
        if ( ( error = initMcBinauralRendering( inputMc, inConfig, outConfig, hRendCfg ) ) != IVAS_ERR_OK )
        {
            return error;
        }
@@ -1731,7 +1748,8 @@ static ivas_error initSbaPanGainsForSbaOut(

static ivas_error updateSbaPanGains(
    input_sba *inputSba,
    const IVAS_REND_AudioConfig outConfig )
    const IVAS_REND_AudioConfig outConfig,
    RENDER_CONFIG_DATA *hRendCfg )
{
    ivas_error error;
    IVAS_REND_AudioConfig inConfig;
@@ -1755,14 +1773,14 @@ static ivas_error updateSbaPanGains(
            switch ( outConfig )
            {
                case IVAS_REND_AUDIO_CONFIG_BINAURAL:
                    error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, *rendCtx.pOutSampleRate );
                    error = ivas_rend_openCrend( &inputSba->crendWrapper, inConfig, outConfig, hRendCfg, *rendCtx.pOutSampleRate );
                    break;
                case IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM:
                    if ( ( error = initSbaPanGainsForMcOut( inputSba, IVAS_REND_AUDIO_CONFIG_7_1_4, NULL ) ) != IVAS_ERR_OK )
                    {
                        return error;
                    }
                    error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, *rendCtx.pOutSampleRate );
                    error = ivas_rend_openCrend( &inputSba->crendWrapper, IVAS_REND_AUDIO_CONFIG_7_1_4, outConfig, hRendCfg, *rendCtx.pOutSampleRate );
                    break;
                default:
                    return IVAS_ERR_INVALID_OUTPUT_FORMAT;
@@ -1783,7 +1801,8 @@ static ivas_error updateSbaPanGains(
static ivas_error setRendInputActiveSba(
    void *input,
    const IVAS_REND_AudioConfig inConfig,
    const IVAS_REND_InputId id )
    const IVAS_REND_InputId id,
    RENDER_CONFIG_DATA *hRendCfg )
{
    ivas_error error;
    rendering_context rendCtx;
@@ -1799,7 +1818,7 @@ static ivas_error setRendInputActiveSba(
    inputSba->crendWrapper = defaultCrendWrapper();
    initRotGains( inputSba->rot_gains_prev );

    if ( ( error = updateSbaPanGains( inputSba, outConfig ) ) != IVAS_ERR_OK )
    if ( ( error = updateSbaPanGains( inputSba, outConfig, hRendCfg ) ) != IVAS_ERR_OK )
    {
        return error;
    }
@@ -2027,7 +2046,7 @@ ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout(
            /* Input inactive, skip. */
            continue;
        }
        if ( ( error = updateSbaPanGains( inputSba, hIvasRend->outputConfig ) ) != IVAS_ERR_OK )
        if ( ( error = updateSbaPanGains( inputSba, hIvasRend->outputConfig, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK )
        {
            return error;
        }
@@ -2245,7 +2264,7 @@ ivas_error IVAS_REND_AddInput(
    int32_t maxNumInputsOfType;
    void *inputsArray;
    int32_t inputStructSize;
    ivas_error ( *activateInput )( void *, IVAS_REND_AudioConfig, IVAS_REND_InputId );
    ivas_error ( *activateInput )( void *, IVAS_REND_AudioConfig, IVAS_REND_InputId, RENDER_CONFIG_DATA * );
    int32_t inputIndex;

    /*-----------------------------------------------------------------*
@@ -2289,7 +2308,7 @@ ivas_error IVAS_REND_AddInput(

    *inputId = makeInputId( inConfig, inputIndex );

    if ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId ) ) != IVAS_ERR_OK )
    if ( ( error = activateInput( (uint8_t *) inputsArray + inputStructSize * inputIndex, inConfig, *inputId, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK )
    {
        return error;
    }
@@ -2338,7 +2357,7 @@ ivas_error IVAS_REND_ConfigureCustomInputLoudspeakerLayout(

    if ( hIvasRend->outputConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL || hIvasRend->outputConfig == IVAS_REND_AUDIO_CONFIG_BINAURAL_ROOM )
    {
        if ( ( error = initMcBinauralRendering( inputMc, inputMc->base.inConfig, hIvasRend->outputConfig ) ) != IVAS_ERR_OK )
        if ( ( error = initMcBinauralRendering( inputMc, inputMc->base.inConfig, hIvasRend->outputConfig, hIvasRend->hRendererConfig ) ) != IVAS_ERR_OK )
        {
            return error;
        }
@@ -2652,6 +2671,123 @@ ivas_error IVAS_REND_FeedInputObjectMetadata(
    return IVAS_ERR_OK;
}

ivas_error IVAS_REND_InitConfig( IVAS_REND_HANDLE st,
                                 bool headRotationEnabled,
                                 bool rendererConfigEnabled )
{
    ivas_error error;

    if ( headRotationEnabled )
    {
        st->enableHeadRotation = 1;
    }
    else
    {
        st->enableHeadRotation = 0;
    }

    if ( rendererConfigEnabled )
    {
        st->rendererConfigEnabled = 1;
    }
    else
    {
        st->rendererConfigEnabled = 0;
    }

    if ( ( error = ivas_render_config_open( &( st->hRendererConfig ) ) ) != IVAS_ERR_OK )
    {
        return error;
    }

    if ( ivas_render_config_init_from_rom( &st->hRendererConfig, st->rendererConfigEnabled ) != IVAS_ERR_OK )
    {
        return IVAS_ERR_INTERNAL_FATAL;
    }

    return IVAS_ERR_OK;
}

int16_t IVAS_REND_GetRenderConfig(
    IVAS_REND_HANDLE hIvasRend,            /* i/o: IVAS decoder handle         */
    const IVAS_RENDER_CONFIG_HANDLE hRCout /* o  : Render configuration handle */
)
{
    RENDER_CONFIG_HANDLE hRCin;

    if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL || hRCout == NULL )
    {
        return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    }

    hRCin = hIvasRend->hRendererConfig;
#ifdef DEBUGGING
    switch ( hRCin->renderer_type_override )
    {
        case RENDER_TYPE_OVERRIDE_CREND:
            hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_CREND;
            break;
        case RENDER_TYPE_OVERRIDE_FASTCONV:
            hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_FASTCONV;
            break;
        default:
            hRCout->renderer_type_override = IVAS_RENDER_TYPE_OVERRIDE_NONE;
            break;
    }
#endif
    hRCout->room_acoustics.override = hRCin->roomAcoustics.override;
    hRCout->room_acoustics.use_brir = hRCin->roomAcoustics.use_brir;
    hRCout->room_acoustics.late_reverb_on = hRCin->roomAcoustics.late_reverb_on;
    hRCout->room_acoustics.nBands = hRCin->roomAcoustics.nBands;
    hRCout->room_acoustics.acousticPreDelay = hRCin->roomAcoustics.acousticPreDelay;
    hRCout->room_acoustics.inputPreDelay = hRCin->roomAcoustics.inputPreDelay;

    mvr2r( hRCin->roomAcoustics.pFc_input, hRCout->room_acoustics.pFc_input, CLDFB_NO_CHANNELS_MAX );
    mvr2r( hRCin->roomAcoustics.pAcoustic_rt60, hRCout->room_acoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX );
    mvr2r( hRCin->roomAcoustics.pAcoustic_dsr, hRCout->room_acoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX );

    return IVAS_ERR_OK;
}


int16_t IVAS_REND_FeedRenderConfig(
    IVAS_REND_HANDLE hIvasRend,                /* i/o: IVAS decoder handle         */
    const IVAS_RENDER_CONFIG_DATA renderConfig /* i  : Render configuration struct */
)
{
    RENDER_CONFIG_HANDLE hRenderConfig;

    if ( hIvasRend == NULL || hIvasRend->hRendererConfig == NULL )
    {
        return IVAS_ERR_UNEXPECTED_NULL_POINTER;
    }

    hRenderConfig = hIvasRend->hRendererConfig;
#ifdef DEBUGGING
    hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_NONE;
    if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_FASTCONV )
    {
        hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_FASTCONV;
    }
    if ( renderConfig.renderer_type_override == IVAS_RENDER_TYPE_OVERRIDE_CREND )
    {
        hRenderConfig->renderer_type_override = RENDER_TYPE_OVERRIDE_CREND;
    }
#endif
    hRenderConfig->roomAcoustics.override = renderConfig.room_acoustics.override;
    hRenderConfig->roomAcoustics.use_brir = renderConfig.room_acoustics.use_brir;
    hRenderConfig->roomAcoustics.late_reverb_on = renderConfig.room_acoustics.late_reverb_on;
    hRenderConfig->roomAcoustics.nBands = renderConfig.room_acoustics.nBands;
    hRenderConfig->roomAcoustics.acousticPreDelay = renderConfig.room_acoustics.acousticPreDelay;
    hRenderConfig->roomAcoustics.inputPreDelay = renderConfig.room_acoustics.inputPreDelay;
    mvr2r( renderConfig.room_acoustics.pFc_input, hRenderConfig->roomAcoustics.pFc_input, CLDFB_NO_CHANNELS_MAX );
    mvr2r( renderConfig.room_acoustics.pAcoustic_rt60, hRenderConfig->roomAcoustics.pAcoustic_rt60, CLDFB_NO_CHANNELS_MAX );
    mvr2r( renderConfig.room_acoustics.pAcoustic_dsr, hRenderConfig->roomAcoustics.pAcoustic_dsr, CLDFB_NO_CHANNELS_MAX );

    return IVAS_ERR_OK;
}


ivas_error IVAS_REND_SetHeadRotation(
    IVAS_REND_HANDLE hIvasRend,
    const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME] )
@@ -3977,6 +4113,9 @@ void IVAS_REND_Close(
        clearInputSba( &hIvasRend->inputsSba[i] );
    }

    /* clear Config. Renderer */
    ivas_render_config_close( &( hIvasRend->hRendererConfig ) );

    ivas_limiter_close( &hIvasRend->hLimiter );

    count_free( hIvasRend );
+16 −0
Original line number Diff line number Diff line
@@ -236,6 +236,22 @@ ivas_error IVAS_REND_FeedInputMasaMetadata(
    void* TODO
);

ivas_error IVAS_REND_InitConfig( 
    IVAS_REND_HANDLE st,                            /* i/o: Renderer handle */
    bool headRotationEnabled,                       /* i  : enable head rotation for binaural output, ignored for other output formats  */
    bool rendererConfigEnabled                      /* i  : flag indicating if a renderer configuration file was supplied               */
);

int16_t IVAS_REND_GetRenderConfig(
    IVAS_REND_HANDLE hIvasRend,              /* i/o: IVAS decoder handle         */
    const IVAS_RENDER_CONFIG_HANDLE hRCout /* o  : Render configuration handle */
);

int16_t IVAS_REND_FeedRenderConfig(
    IVAS_REND_HANDLE hIvasRend,                  /* i/o: IVAS decoder handle         */
    const IVAS_RENDER_CONFIG_DATA renderConfig /* i  : Render configuration struct */
);

ivas_error IVAS_REND_SetHeadRotation(
    IVAS_REND_HANDLE hIvasRend,                     /* i/o: Renderer handle                                     */
    const IVAS_QUATERNION headRot[RENDERER_HEAD_POSITIONS_PER_FRAME] /* i  : head positions for next rendering call */
Loading