From 567b949a7cca9d4a1747481195998049cd3368a3 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 7 Jul 2025 17:28:23 +0200 Subject: [PATCH 01/49] rename IVAS_REND_NumOutChannels() to IVAS_REND_GetNumOutChannels() --- apps/renderer.c | 2 +- lib_rend/lib_rend.c | 10 +++++----- lib_rend/lib_rend.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 5242242f7f..d51b740fea 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1350,7 +1350,7 @@ int main( } int16_t numOutChannels; - if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_GetNumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_NumOutChannels(): %s\n", ivas_error_to_string( error ) ); goto cleanup; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 08f6c7fbbc..0fbda5b2fb 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -2804,7 +2804,7 @@ ivas_error IVAS_REND_Open( hIvasRend->num_subframes = num_subframes; /* Initialize limiter */ - if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_GetNumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) { return error; } @@ -3058,7 +3058,7 @@ ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( hIvasRend->customLsOut = makeCustomLsSetup( layout ); /* Re-initialize limiter - number of output channels may have changed */ - if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_GetNumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) { return error; } @@ -3116,12 +3116,12 @@ ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( /*-------------------------------------------------------------------* - * IVAS_REND_NumOutChannels() + * IVAS_REND_GetNumOutChannels() * * *-------------------------------------------------------------------*/ -ivas_error IVAS_REND_NumOutChannels( +ivas_error IVAS_REND_GetNumOutChannels( IVAS_REND_CONST_HANDLE hIvasRend, int16_t *numOutChannels ) { @@ -7405,7 +7405,7 @@ static ivas_error getSamplesInternal( } } - if ( ( error = IVAS_REND_NumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_GetNumOutChannels( hIvasRend, &numOutChannels ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index 194bca0165..a0aa40841b 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -134,7 +134,7 @@ ivas_error IVAS_REND_ConfigureCustomOutputLoudspeakerLayout( /* Functions to be called before/during rendering */ -ivas_error IVAS_REND_NumOutChannels( +ivas_error IVAS_REND_GetNumOutChannels( IVAS_REND_CONST_HANDLE hIvasRend, /* i : Renderer handle */ int16_t *numOutChannels /* o : number of output channels */ ); -- GitLab From 40f1b098363818bda4da20847c41f07cec03313b Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 7 Jul 2025 17:30:31 +0200 Subject: [PATCH 02/49] readability improvements/code deduplication in renderer.c --- apps/renderer.c | 186 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 133 insertions(+), 53 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index d51b740fea..edf31dd427 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -742,8 +742,11 @@ int main( CmdlnArgs args = parseCmdlnArgs( argc, argv ); - if ( args.nonDiegeticPan && !( ( args.inConfig.numAudioObjects == 0 && args.inConfig.multiChannelBuses[0].audioConfig == IVAS_AUDIO_CONFIG_MONO ) || - ( args.inConfig.numAudioObjects > 0 && args.inConfig.audioObjects[0].audioConfig == IVAS_AUDIO_CONFIG_OBA && args.inConfig.numAudioObjects == 1 ) ) ) + if ( args.nonDiegeticPan && + !( ( args.inConfig.numAudioObjects == 0 && + args.inConfig.multiChannelBuses[0].audioConfig == IVAS_AUDIO_CONFIG_MONO ) || + ( args.inConfig.numAudioObjects > 0 && + args.inConfig.audioObjects[0].audioConfig == IVAS_AUDIO_CONFIG_OBA && args.inConfig.numAudioObjects == 1 ) ) ) { fprintf( stderr, "\ninvalid configuration - non-diegetic panning requires mono or ISM1 input\n" ); goto cleanup; @@ -820,12 +823,20 @@ int main( if ( args.sceneDescriptionInput ) { /* With scene description input, inputFilePath is the path to the scene description file. Parse it. */ - parseSceneDescriptionFile( args.inputFilePath, audioFilePath, &args.inConfig, positionProvider, masaReaders, lfeRoutingConfigs ); + parseSceneDescriptionFile( args.inputFilePath, + audioFilePath, + &args.inConfig, + positionProvider, + masaReaders, + lfeRoutingConfigs ); } else { /* With single-format input, all information is given on command line. */ - setupWithSingleFormatInput( args, audioFilePath, positionProvider, masaReaders ); + setupWithSingleFormatInput( args, + audioFilePath, + positionProvider, + masaReaders ); } /* Check that there is allowed configuration for MASA format output */ @@ -891,7 +902,15 @@ int main( const int16_t frameSize_smpls = (int16_t) ( ( args.render_framesize ) * args.sampleRate * 5 / ( 1000 ) ); - if ( ( error = IVAS_REND_Open( &hIvasRend, args.sampleRate, args.outConfig.audioConfig, !isEmptyString( args.customHrtfFilePath ), args.nonDiegeticPan, args.nonDiegeticPanGain, args.Opt_Headrotation, args.Opt_ExternalOrientation, (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_Open( &hIvasRend, + args.sampleRate, + args.outConfig.audioConfig, + !isEmptyString( args.customHrtfFilePath ), + args.nonDiegeticPan, + args.nonDiegeticPanGain, + args.Opt_Headrotation, + args.Opt_ExternalOrientation, + (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError opening renderer handle: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1064,7 +1083,10 @@ int main( { /* sanity check */ - if ( ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && !is_split_pre_rend_mode( &args ) ) + if ( ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL ) && + ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR ) && + ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) && + !is_split_pre_rend_mode( &args ) ) { fprintf( stderr, "\nExternal Renderer Config is supported only when binaural output configurations is used as output OR when Split pre-rendering mode is enabled. Exiting. \n" ); goto cleanup; @@ -1210,7 +1232,9 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, mcIds[i], args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, + mcIds[i], + args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1243,7 +1267,11 @@ int main( /* set panning gains for input LFE */ else if ( args.lfePanningEnabled ) { - if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], args.lfeConfigGain, args.lfeConfigAzimuth, args.lfeConfigElevation ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, + mcIds[i], + args.lfeConfigGain, + args.lfeConfigAzimuth, + args.lfeConfigElevation ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputLfePos failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1272,7 +1300,11 @@ int main( /* set position based gains */ else { - if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], lfeRoutingConfigs[i]->lfe_gain_dB, lfeRoutingConfigs[i]->lfe_azi, lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, + mcIds[i], + lfeRoutingConfigs[i]->lfe_gain_dB, + lfeRoutingConfigs[i]->lfe_azi, + lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputLfePos failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1290,7 +1322,9 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, ismIds[i], args.inputGainGlobal * dBToLin( args.inConfig.audioObjects[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, + ismIds[i], + args.inputGainGlobal * dBToLin( args.inConfig.audioObjects[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1311,7 +1345,9 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, sbaIds[i], args.inputGainGlobal * dBToLin( args.inConfig.ambisonicsBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, + sbaIds[i], + args.inputGainGlobal * dBToLin( args.inConfig.ambisonicsBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1326,7 +1362,9 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, masaIds[i], args.inputGainGlobal * dBToLin( args.inConfig.masaBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, + masaIds[i], + args.inputGainGlobal * dBToLin( args.inConfig.masaBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1358,16 +1396,30 @@ int main( if ( cldfb_in_flag ) { - if ( ( error = IVAS_REND_openCldfb( cldfbAna, cldfbSyn, totalNumInChannels, numOutChannels, args.sampleRate ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_openCldfb( cldfbAna, + cldfbSyn, + totalNumInChannels, + numOutChannels, + args.sampleRate ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_openCldfb(): %s\n", ivas_error_to_string( error ) ); goto cleanup; } } - if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) + char *outFile = args.outMetadataFilePath; + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { + outFile = args.outputFilePath; + audioWriter = NULL; + } + if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, + &bitsBuffer.config.codec, + &bitsBuffer.config.poseCorrection, + &bitsBuffer.config.codec_frame_size_ms, + &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_GetSplitRendBitstreamHeader()!\n" ); goto cleanup; @@ -1379,35 +1431,23 @@ int main( goto cleanup; } - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outputFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, + outFile, + delayNumSamples_temp, + delayTimeScale_temp, + bitsBuffer.config.codec, + bitsBuffer.config.poseCorrection, + bitsBuffer.config.codec_frame_size_ms, + bitsBuffer.config.isar_frame_size_ms, + args.sampleRate, + bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) { - fprintf( stderr, "\nCould not open split rend metadata file %s\n", args.outputFilePath ); + fprintf( stderr, "\nCould not open split rend metadata file %s\n", outFile ); goto cleanup; } - audioWriter = NULL; } else { - if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nError in IVAS_REND_GetSplitRendBitstreamHeader()!\n" ); - goto cleanup; - } - - if ( IVAS_REND_GetDelay( hIvasRend, &delayNumSamples_temp, &delayTimeScale_temp ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nUnable to get delay of renderer!\n" ); - goto cleanup; - } - - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) - { - fprintf( stderr, "\nCould not open split rend metadata file %s\n", args.outMetadataFilePath ); - goto cleanup; - } - } if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) { @@ -1502,7 +1542,9 @@ int main( args.aeSequence.selected = 0; } args.aeSequence.frameCounter = 0; - if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, args.aeSequence.pID[args.aeSequence.selected], &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) + if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, + args.aeSequence.pID[args.aeSequence.selected], + &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { @@ -1538,7 +1580,13 @@ int main( } /* Convert from int to float and from interleaved to packed */ - convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); + convertInputBuffer( inpInt16Buffer, + numSamplesRead, + inBuffer.config.numSamplesPerChannel, + num_in_channels, + inFloatBuffer, + inBuffer.config.is_cldfb, + cldfbAna ); int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; @@ -1622,7 +1670,12 @@ int main( int16_t numFramesToTargetOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { - if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &quatBuffer[sf_idx], &enableHeadRotation[sf_idx], &enableExternalOrientation[sf_idx], &enableRotationInterpolation[sf_idx], &numFramesToTargetOrientation[sf_idx] ) ) != IVAS_ERR_OK ) + if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, + &quatBuffer[sf_idx], + &enableHeadRotation[sf_idx], + &enableExternalOrientation[sf_idx], + &enableRotationInterpolation[sf_idx], + &numFramesToTargetOrientation[sf_idx] ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in External Orientation File Reading: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1630,7 +1683,13 @@ int main( } for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { - if ( ( error = IVAS_REND_SetExternalOrientation( hIvasRend, &quatBuffer[sf_idx], enableHeadRotation[sf_idx], enableExternalOrientation[sf_idx], enableRotationInterpolation[sf_idx], numFramesToTargetOrientation[sf_idx], sf_idx ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetExternalOrientation( hIvasRend, + &quatBuffer[sf_idx], + enableHeadRotation[sf_idx], + enableExternalOrientation[sf_idx], + enableRotationInterpolation[sf_idx], + numFramesToTargetOrientation[sf_idx], + sf_idx ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError setting External Orientation: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1653,7 +1712,9 @@ int main( fprintf( stderr, "\nIVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, numChannels ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, + (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, + numChannels ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { @@ -1668,7 +1729,9 @@ int main( { if ( i == 0 ) { - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, args.inConfig.numAudioObjects ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, + (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, + args.inConfig.numAudioObjects ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { @@ -1685,7 +1748,9 @@ int main( } else { - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, 1 ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, + (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, + 1 ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { @@ -1708,7 +1773,9 @@ int main( fprintf( stderr, "\nIVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, numChannels ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, + (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, + numChannels ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { @@ -1724,7 +1791,9 @@ int main( fprintf( stderr, "IVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.masaBuses[i].inputChannelIndex, numChannels ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, + (int16_t) args.inConfig.masaBuses[i].inputChannelIndex, + numChannels ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, masaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) { @@ -1774,7 +1843,12 @@ int main( /* Convert from float to int and from packed to interleaved. * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ - convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, cldfb_in_flag, cldfbSyn ); + convertOutputBuffer( outFloatBuffer, + outBuffer.config.numSamplesPerChannel, + num_out_channels, + outInt16Buffer, + cldfb_in_flag, + cldfbSyn ); if ( delayNumSamples == -1 ) { @@ -1809,7 +1883,9 @@ int main( { if ( delayNumSamples * num_out_channels < outBufferSize ) { - if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) + if ( AudioFileWriter_write( audioWriter, + &outInt16Buffer[delayNumSamples * num_out_channels], + outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError writing audio file %s\n", args.outputFilePath ); goto cleanup; @@ -1898,7 +1974,8 @@ int main( } } - if ( ( args.inConfig.numAmbisonicsBuses > 0 || args.inConfig.numMultiChannelBuses > 0 || args.inConfig.numMasaBuses > 0 ) && args.inConfig.numAudioObjects > 0 ) + if ( ( args.inConfig.numAmbisonicsBuses > 0 || args.inConfig.numMultiChannelBuses > 0 || args.inConfig.numMasaBuses > 0 ) && + args.inConfig.numAudioObjects > 0 ) { inputType2 = IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED; if ( ( error = IVAS_REND_MergeMasaMetadata( hIvasRend, &hMetaOutput, inputType1, inputType2 ) ) != IVAS_ERR_OK ) @@ -1949,9 +2026,11 @@ int main( zeroPadToWrite = 0; } - if ( args.inConfig.numAudioObjects != 0 && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) + if ( args.inConfig.numAudioObjects != 0 && + ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) { - fprintf( stdout, "\n\nMetadata delayed %d subframes\n\n", (int16_t) round( args.syncMdDelay / ( 1000 / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); + fprintf( stdout, "\n\nMetadata delayed %d subframes\n\n", + (int16_t) round( args.syncMdDelay / ( 1000 / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); } if ( !args.quietModeEnabled && args.delayCompensationEnabled ) @@ -3281,7 +3360,8 @@ static void parseObjectPosition( *positionDuration = (uint16_t) strtol( line, &endptr, 10 ); readNextMetadataChunk( line, "\n" ); - read_values = (int16_t) sscanf( line, "%f,%f,%f,%f,%f,%f,%f,%f", &meta_prm[0], &meta_prm[1], &meta_prm[2], &meta_prm[3], &meta_prm[4], &meta_prm[5], &meta_prm[6], &meta_prm[7] ); + read_values = (int16_t) sscanf( line, "%f,%f,%f,%f,%f,%f,%f,%f", + &meta_prm[0], &meta_prm[1], &meta_prm[2], &meta_prm[3], &meta_prm[4], &meta_prm[5], &meta_prm[6], &meta_prm[7] ); if ( read_values < 2 ) { -- GitLab From 9de90db9a301677969baf23b37dbd2c588ead309 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 10 Jul 2025 11:30:01 +0200 Subject: [PATCH 03/49] [fix] incorrect value used in assert for LFE to binaural delaybuffer --- lib_rend/lib_rend.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 0fbda5b2fb..7e19d83e4f 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -5758,8 +5758,7 @@ static ivas_error renderLfeToBinaural( num_cpy_smpl_prev_frame = mcInput->binauralDelaySmp; num_cpy_smpl_cur_frame = frame_size - num_cpy_smpl_prev_frame; - /* Assuming LFE should be delayed by less that the duration of one frame */ - assert( mcInput->binauralDelaySmp < frame_size ); + assert( mcInput->binauralDelaySmp <= MAX_BIN_DELAY_SAMPLES ); /* Get delayed LFE signal from previous frame, apply gain and save in tmp buffer */ v_multc( mcInput->lfeDelayBuffer, gain, tmpLfeBuffer, num_cpy_smpl_prev_frame ); -- GitLab From e5ce37c2b3026a56086196af772fce1983382874 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 10 Jul 2025 11:33:19 +0200 Subject: [PATCH 04/49] [fix] inconsistent return statement in setRendInputActiveSba --- lib_rend/lib_rend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 7e19d83e4f..740161d87d 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -2644,7 +2644,7 @@ static ivas_error setRendInputActiveSba( return error; } - return error; + return IVAS_ERR_OK; } -- GitLab From 74caff9171a3d3eeef6e8428f0171e5dc848f9a2 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 10 Jul 2025 11:37:20 +0200 Subject: [PATCH 05/49] [fix] compiler warning; integer division used in floating point context --- apps/renderer.c | 3 +-- lib_rend/lib_rend.c | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index edf31dd427..bd008bb250 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -2029,8 +2029,7 @@ int main( if ( args.inConfig.numAudioObjects != 0 && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) { - fprintf( stdout, "\n\nMetadata delayed %d subframes\n\n", - (int16_t) round( args.syncMdDelay / ( 1000 / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); + fprintf( stdout, "\n\nMetadata delayed %d subframes\n\n", (int16_t) round( args.syncMdDelay / ( 1000.f / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); } if ( !args.quietModeEnabled && args.delayCompensationEnabled ) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 740161d87d..c9e251798c 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -5141,7 +5141,7 @@ static ivas_error renderIsmToBinaural( push_wmops( "renderIsmToBinaural" ); /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */ - ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms / ( 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms / ( 1000.f / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); copyBufferTo2dArray( ismInput->base.inputBuffer, tmpTDRendBuffer ); if ( ( error = ivas_td_binaural_renderer_ext( &ismInput->tdRendWrapper, ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, ismInput->hReverb, ism_md_subframe_update_ext, @@ -5345,7 +5345,7 @@ static ivas_error renderIsmToBinauralReverb( push_wmops( "renderIsmToBinauralRoom" ); /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */ - ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms / ( 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms / ( 1000.f / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); copyBufferTo2dArray( ismInput->base.inputBuffer, tmpRendBuffer ); @@ -5523,7 +5523,7 @@ static ivas_error renderIsmToSplitBinaural( pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; /* Metadata Delay to sync with audio delay converted from ms to 5ms (1000/50/4) subframe index */ - ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms / ( 1000 / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); + ism_md_subframe_update_ext = (int16_t) roundf( ismInput->ism_metadata_delay_ms / ( 1000.f / FRAMES_PER_SEC / MAX_PARAM_SPATIAL_SUBFRAMES ) ); pCombinedOrientationData = *ismInput->base.ctx.pCombinedOrientationData; -- GitLab From e75628ae412bb7561e442f1bc78fe0a553b679af Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 10 Jul 2025 12:03:01 +0200 Subject: [PATCH 06/49] add delay alignment for multiple inputs in external renderer --- apps/renderer.c | 2 + lib_rend/ivas_td_ring_buffer.c | 235 ++++++++++++++++++++++ lib_rend/ivas_td_ring_buffer.h | 106 ++++++++++ lib_rend/lib_rend.c | 348 ++++++++++++++++++++++++++------- 4 files changed, 620 insertions(+), 71 deletions(-) create mode 100644 lib_rend/ivas_td_ring_buffer.c create mode 100644 lib_rend/ivas_td_ring_buffer.h diff --git a/apps/renderer.c b/apps/renderer.c index bd008bb250..0096471854 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -2004,6 +2004,8 @@ int main( #endif } + /* TODO a flush method is needed to empty the delay buffers */ + /* add zeros at the end to have equal length of synthesized signals */ if ( audioWriter != NULL ) { diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c new file mode 100644 index 0000000000..6e29cc5bdd --- /dev/null +++ b/lib_rend/ivas_td_ring_buffer.c @@ -0,0 +1,235 @@ +/****************************************************************************************************** + + (C) 2022-2025 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_td_ring_buffer.h" +#include "ivas_error_utils.h" +#include +#include + +struct TdRingBuf +{ + float *data; /* samples in interleaved layout */ + uint32_t capacity; + uint16_t num_channels; + uint32_t write_pos; + uint32_t read_pos; + int16_t is_full; +}; + +ivas_error TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, uint32_t capacity_per_channel, uint16_t num_channels ) +{ + TD_RINGBUF_HANDLE h; + uint32_t capacity; + capacity = capacity_per_channel * num_channels; + + h = malloc( sizeof( struct TdRingBuf ) ); + if ( h == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" ); + } + h->data = NULL; + h->capacity = 0; + h->num_channels = num_channels; + h->write_pos = 0; + h->read_pos = 0; + h->is_full = 0; + *ph = h; + + h->data = malloc( capacity * sizeof( float ) ); + if ( h->data == NULL ) + { + return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" ); + } + h->capacity = capacity; + + return IVAS_ERR_OK; +} + +void TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph ) +{ + TD_RINGBUF_HANDLE h; + + if ( ph == NULL ) + { + return; + } + h = *ph; + + if ( h == NULL ) + { + return; + } + + if ( h->data != NULL ) + { + free( h->data ); + } + + free( h ); + *ph = NULL; + + return; +} + +/* Returns total number of buffered samples (includes number of channels) */ +static uint32_t total_size( TD_RINGBUF_HANDLE h ) +{ + if ( TD_RINGBUF_IsFull( h ) ) + { + return h->capacity; + } + + if ( h->read_pos <= h->write_pos ) + { + return h->write_pos - h->read_pos; + } + /* else wrap around */ + return h->write_pos + h->capacity - h->read_pos; +} + +static int16_t has_space_for_num_samples( TD_RINGBUF_HANDLE h, uint32_t num_samples ) +{ + return (int16_t) ( total_size( h ) + num_samples <= h->capacity ); +} + +void TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, uint32_t num_samples_per_channel ) +{ + uint32_t s; + uint16_t c; + + assert( has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); + + for ( s = 0; s < num_samples_per_channel; ++s ) + { + for ( c = 0; c < h->num_channels; ++c ) + { + h->data[h->write_pos] = *( data + c * num_samples_per_channel + s ); + ++h->write_pos; + + if ( h->write_pos == h->capacity ) + { + h->write_pos = 0; + } + } + } + + if ( h->read_pos == h->write_pos ) + { + h->is_full = 1; + } + + return; +} + +void TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, uint32_t num_samples_per_channel ) +{ + uint32_t s; + uint16_t c; + + assert( has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); + if ( !num_samples_per_channel ) + { + return; + } + + for ( s = 0; s < num_samples_per_channel; ++s ) + { + for ( c = 0; c < h->num_channels; ++c ) + { + h->data[h->write_pos] = 0.f; + ++h->write_pos; + + if ( h->write_pos == h->capacity ) + { + h->write_pos = 0; + } + } + } + + if ( h->read_pos == h->write_pos ) + { + h->is_full = 1; + } + + return; +} + +void TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, uint32_t num_samples_per_channel ) +{ + uint32_t s; + uint16_t c; + + assert( total_size( h ) >= num_samples_per_channel * h->num_channels ); + + for ( s = 0; s < num_samples_per_channel; ++s ) + { + for ( c = 0; c < h->num_channels; ++c ) + { + *( data + c * num_samples_per_channel + s ) = h->data[h->read_pos]; + ++h->read_pos; + + if ( h->read_pos == h->capacity ) + { + h->read_pos = 0; + } + } + } + + if ( h->is_full ) + { + h->is_full = 0; + } + + return; +} + +int16_t TD_RINGBUF_IsEmpty( TD_RINGBUF_HANDLE h ) +{ + return (int16_t) ( h->read_pos == h->write_pos && !h->is_full ); +} + +int16_t TD_RINGBUF_IsFull( TD_RINGBUF_HANDLE h ) +{ + return h->is_full; +} + +uint32_t TD_RINGBUF_Size( TD_RINGBUF_HANDLE h ) +{ + return total_size( h ) / (uint32_t) h->num_channels; +} + +void TD_RINGBUF_Clear( TD_RINGBUF_HANDLE h ) +{ + h->read_pos = h->write_pos; + h->is_full = 0; + return; +} diff --git a/lib_rend/ivas_td_ring_buffer.h b/lib_rend/ivas_td_ring_buffer.h new file mode 100644 index 0000000000..4670f88fab --- /dev/null +++ b/lib_rend/ivas_td_ring_buffer.h @@ -0,0 +1,106 @@ +/****************************************************************************************************** + + (C) 2022-2025 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. + +*******************************************************************************************************/ + +#ifndef IVAS_TD_RING_BUFFER_H +#define IVAS_TD_RING_BUFFER_H + +#include "ivas_error.h" +#include + +typedef struct TdRingBuf *TD_RINGBUF_HANDLE; + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Open() + * + * Allocate a ring buffer for TD data with the given capacity of TD samples per channel. + * + * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise. + *---------------------------------------------------------------------*/ +ivas_error TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, uint32_t capacity_per_channel, uint16_t num_channels ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Close() + * + * Dellocate TD ring buffer. The given handle will be set to NULL. + *---------------------------------------------------------------------*/ +void TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Push() + * + * Push samples onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ +void TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, uint32_t num_samples_per_channel ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_PushZeros() + * + * Push zero samples onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ +void TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, uint32_t num_samples_per_channel ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Pop() + * + * Pop samples from the front of the TD ring buffer. + *---------------------------------------------------------------------*/ +void TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, uint32_t num_samples_per_channel ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_IsEmpty() + * + * Returns 1 if the ring buffer is empty, or 0 otherwise. + *---------------------------------------------------------------------*/ +int16_t TD_RINGBUF_IsEmpty( TD_RINGBUF_HANDLE h ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_IsFull() + * + * Returns 1 if the ring buffer is full, or 0 otherwise. + *---------------------------------------------------------------------*/ +int16_t TD_RINGBUF_IsFull( TD_RINGBUF_HANDLE h ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Size() + * + * Returns number of buffered samples per channel. + *---------------------------------------------------------------------*/ +uint32_t TD_RINGBUF_Size( TD_RINGBUF_HANDLE h ); + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Clear() + * + * Remove all samples from the buffer. + *---------------------------------------------------------------------*/ +void TD_RINGBUF_Clear( TD_RINGBUF_HANDLE h ); + +#endif /* IVAS_TD_RING_BUFFER_H */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index c9e251798c..50ddce03ce 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -40,6 +40,7 @@ #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_rend.h" +#include "ivas_td_ring_buffer.h" #include #include #include @@ -81,6 +82,7 @@ typedef struct typedef struct { const int32_t *pOutSampleRate; + const float *pMaxGlobalDelayNs; const AUDIO_CONFIG *pOutConfig; const LSSETUP_CUSTOM_STRUCT *pCustomLsOut; const EFAP_WRAPPER *pEfapOutWrapper; @@ -97,9 +99,12 @@ typedef struct AUDIO_CONFIG inConfig; IVAS_REND_InputId id; IVAS_REND_AudioBuffer inputBuffer; + TD_RINGBUF_HANDLE delayBuffer; float gain; /* Linear, not in dB */ rendering_context ctx; int32_t numNewSamplesPerChannel; /* Used to keep track how much new audio was fed before rendering current frame */ + int32_t delayNumSamples; + float delay_ns; // TODO is this needed? } input_base; typedef struct @@ -188,7 +193,8 @@ typedef struct hrtf_handles struct IVAS_REND { - int32_t sampleRateOut; + int32_t sampleRateOut; // TODO rename to sampleRate? + float maxGlobalDelayNs; IVAS_LIMITER_HANDLE hLimiter; #ifdef DEBUGGING @@ -262,6 +268,13 @@ static void freeInputBaseBufferData( return; } +static int16_t latencyNsToSamples( + int32_t sampleRate, + float latency_ns ) +{ + return (int16_t) roundf( (float) ( latency_ns ) * ( sampleRate / 1000000000.f ) ); +} + static ivas_error allocateMcLfeDelayBuffer( float **lfeDelayBuffer, const int16_t data_size ) @@ -1162,6 +1175,9 @@ static void initRendInputBase( inputBase->gain = 1.0f; inputBase->ctx = rendCtx; inputBase->numNewSamplesPerChannel = 0; + inputBase->delayNumSamples = 0; + inputBase->delay_ns = 0; + inputBase->delayBuffer = NULL; inputBase->inputBuffer.config.numSamplesPerChannel = 0; inputBase->inputBuffer.config.numChannels = 0; @@ -1210,6 +1226,7 @@ static rendering_context getRendCtx( /* Note: when refactoring this, always take the ADDRESS of a member of the * renderer struct, so that the context stores a POINTER to the member, even * if the member is a pointer or handle itself. */ + ctx.pMaxGlobalDelayNs = &hIvasRend->maxGlobalDelayNs; ctx.pOutConfig = &hIvasRend->outputConfig; ctx.pOutSampleRate = &hIvasRend->sampleRateOut; ctx.pCustomLsOut = &hIvasRend->customLsOut; @@ -1252,6 +1269,135 @@ static bool isIoConfigPairSupported( } +static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) +{ + int16_t i; + int32_t latency_ns; + int32_t max_latency_ns; + + max_latency_ns = 0; + + /* Compute the maximum delay across all inputs */ + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) + { + if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + latency_ns = max( ( hIvasRend->inputsIsm[i].crendWrapper != NULL ) ? hIvasRend->inputsIsm[i].crendWrapper->binaural_latency_ns : 0, + hIvasRend->inputsIsm[i].tdRendWrapper.binaural_latency_ns ); + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + for ( i = 0; i < RENDERER_MAX_MC_INPUTS; i++ ) + { + if ( hIvasRend->inputsMc[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + latency_ns = max( ( hIvasRend->inputsMc[i].crendWrapper != NULL ) ? hIvasRend->inputsMc[i].crendWrapper->binaural_latency_ns : 0, + hIvasRend->inputsMc[i].tdRendWrapper.binaural_latency_ns ); + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; i++ ) + { + if ( hIvasRend->inputsSba[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + if ( hIvasRend->splitRendWrapper != NULL && hIvasRend->splitRendWrapper->hBinHrSplitPreRend != NULL ) + { + if ( hIvasRend->hRendererConfig->split_rend_config.rendererSelection == IVAS_BIN_RENDERER_TYPE_FASTCONV ) + { + latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; + } + else + { + latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; + } + max_latency_ns = max( max_latency_ns, latency_ns ); + } + else if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) + { + latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; + latency_ns += IVAS_FB_DEC_DELAY_NS; + max_latency_ns = max( max_latency_ns, latency_ns ); + } + else + { + latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + } + + for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; i++ ) + { + if ( hIvasRend->inputsMasa[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + latency_ns = (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ); + max_latency_ns = max( max_latency_ns, latency_ns ); + } + } + + return max_latency_ns; +} + +static void updateMaxGlobalDelayNs( IVAS_REND_HANDLE hIvasRend ) +{ + hIvasRend->maxGlobalDelayNs = getMaxGlobalDelayNs( (IVAS_REND_CONST_HANDLE) hIvasRend ); +} + +static ivas_error alignInputDelay( + input_base *inputBase, + const IVAS_REND_ReadOnlyAudioBuffer inputAudio, + const float maxGlobalDelayNs, + const int32_t sampleRateOut, + const int16_t cldfb2tdSampleFact ) +{ + ivas_error error; + input_ism *inputIsm; + int16_t maxGlobalDelaySamples; + uint32_t tmpSize; + + maxGlobalDelaySamples = latencyNsToSamples( sampleRateOut, maxGlobalDelayNs ); + maxGlobalDelaySamples *= cldfb2tdSampleFact; + + /* open the delay buffer if it isn't already */ + if ( inputBase->delayBuffer == NULL ) + { + /* buffer has to accomodate maxGlobalDelaySamples + 2 * frameSize */ + tmpSize = maxGlobalDelaySamples; + tmpSize += 2 * inputAudio.config.numSamplesPerChannel; + if ( ( error = TD_RINGBUF_Open( &inputBase->delayBuffer, + tmpSize, + inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* for the first frame we need to push zeros to align the input delay to the global delay + * and then push a frame of actual data */ + tmpSize = maxGlobalDelaySamples - inputBase->delayNumSamples * cldfb2tdSampleFact; + TD_RINGBUF_PushZeros( inputBase->delayBuffer, + tmpSize ); + + /* for ISM inputs, ensure the metadata sync delay is updated */ + if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) + { + inputIsm = (input_ism *) inputBase; + inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs * 1000; + } + } + + /* push in the new input data and pop to retrieve a complete input frame */ + TD_RINGBUF_Push( inputBase->delayBuffer, + inputAudio.data, + inputAudio.config.numSamplesPerChannel ); + TD_RINGBUF_Pop( inputBase->delayBuffer, + inputBase->inputBuffer.data, + inputAudio.config.numSamplesPerChannel ); + + return IVAS_ERR_OK; +} + static ivas_error initIsmMasaRendering( input_ism *inputIsm, const int32_t inSampleRate ) @@ -1275,6 +1421,33 @@ static ivas_error initIsmMasaRendering( return IVAS_ERR_OK; } +static void setRendInputDelayIsm( void *input ) +{ + int32_t latency_ns; + input_ism *inputIsm; + + latency_ns = 0; + inputIsm = (input_ism *) input; + + /* set the rendering delay in InputBase */ + latency_ns = max( latency_ns, + inputIsm->tdRendWrapper.binaural_latency_ns ); + if ( inputIsm->crendWrapper != NULL ) + { + latency_ns = max( latency_ns, + inputIsm->crendWrapper->binaural_latency_ns ); + } + if ( inputIsm->hOMasa != NULL ) + { + /* TODO tmu: verify what should be set for MASA prerendering */ + latency_ns = max( latency_ns, + (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + } + + inputIsm->base.delay_ns = latency_ns; + inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); +} + static ivas_error setRendInputActiveIsm( void *input, @@ -1387,6 +1560,8 @@ static void clearInputIsm( rendCtx = inputIsm->base.ctx; freeInputBaseBufferData( &inputIsm->base.inputBuffer.data ); + TD_RINGBUF_Close( &inputIsm->base.delayBuffer ); + initRendInputBase( &inputIsm->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); /* Free input's internal handles */ @@ -2256,6 +2431,32 @@ static lfe_routing defaultLfeRouting( return routing; } +static void setRendInputDelayMc( void *input ) +{ + int32_t latency_ns; + input_mc *inputMc; + + latency_ns = 0; + inputMc = (input_mc *) input; + + /* set the rendering delay in InputBase */ + latency_ns = max( latency_ns, + inputMc->tdRendWrapper.binaural_latency_ns ); + if ( inputMc->crendWrapper != NULL ) + { + latency_ns = max( latency_ns, + inputMc->crendWrapper->binaural_latency_ns ); + } + if ( inputMc->hMcMasa != NULL ) + { + /* TODO tmu: verify what should be set for MASA prerendering */ + latency_ns = max( latency_ns, + (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + } + + inputMc->base.delay_ns = latency_ns; + inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, latency_ns ); +} static ivas_error setRendInputActiveMc( void *input, @@ -2357,6 +2558,8 @@ static void clearInputMc( freeMcLfeDelayBuffer( &inputMc->lfeDelayBuffer ); freeInputBaseBufferData( &inputMc->bufferData ); + TD_RINGBUF_Close( &inputMc->base.delayBuffer ); + initRendInputBase( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); /* Free input's internal handles */ @@ -2592,6 +2795,35 @@ static ivas_error initSbaMasaRendering( return IVAS_ERR_OK; } +static void setRendInputDelaySba( void *input ) +{ + int32_t latency_ns; + input_sba *inputSba; + + latency_ns = 0; + inputSba = (input_sba *) input; + + /* set the rendering delay in InputBase */ + if ( inputSba->cldfbRendWrapper.hCldfbRend != NULL ) + { + latency_ns = max( latency_ns, + inputSba->cldfbRendWrapper.binaural_latency_ns + IVAS_FB_DEC_DELAY_NS ); + } + if ( inputSba->crendWrapper != NULL ) + { + latency_ns = max( latency_ns, + inputSba->crendWrapper->binaural_latency_ns ); + } + if ( inputSba->hDirAC != NULL ) + { + /* TODO tmu: verify what should be set for MASA prerendering */ + latency_ns = max( latency_ns, + (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + } + + inputSba->base.delay_ns = latency_ns; + inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, latency_ns ); +} static ivas_error setRendInputActiveSba( void *input, @@ -2656,6 +2888,7 @@ static void clearInputSba( rendCtx = inputSba->base.ctx; freeInputBaseBufferData( &inputSba->bufferData ); + TD_RINGBUF_Close( &inputSba->base.delayBuffer ); initRendInputBase( &inputSba->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2672,6 +2905,24 @@ static void clearInputSba( return; } +static void setRendInputDelayMasa( void *input ) +{ + int32_t latency_ns; + input_masa *inputMasa; + + latency_ns = 0; + inputMasa = (input_masa *) input; + + /* set the rendering delay in InputBase */ + if ( inputMasa->hMasaExtRend != NULL && inputMasa->hMasaExtRend->renderer_type != RENDERER_DISABLE ) + { + latency_ns = max( latency_ns, + (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + } + + inputMasa->base.delay_ns = latency_ns; + inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); +} static ivas_error setRendInputActiveMasa( void *input, @@ -2735,6 +2986,7 @@ static void clearInputMasa( rendCtx = inputMasa->base.ctx; freeInputBaseBufferData( &inputMasa->bufferData ); + TD_RINGBUF_Close( &inputMasa->base.delayBuffer ); masaPrerendClose( &inputMasa->hMasaPrerend ); freeMasaExtRenderer( &inputMasa->hMasaExtRend ); @@ -3459,6 +3711,7 @@ ivas_error IVAS_REND_AddInput( void *inputsArray; int32_t inputStructSize; ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, RENDER_CONFIG_DATA *, hrtf_handles * ); + void ( *setInputDelay )( void * ); int32_t inputIndex; /* Validate function arguments */ @@ -3485,24 +3738,28 @@ ivas_error IVAS_REND_AddInput( inputsArray = hIvasRend->inputsIsm; inputStructSize = sizeof( *hIvasRend->inputsIsm ); activateInput = setRendInputActiveIsm; + setInputDelay = setRendInputDelayIsm; break; case IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED: maxNumInputsOfType = RENDERER_MAX_MC_INPUTS; inputsArray = hIvasRend->inputsMc; inputStructSize = sizeof( *hIvasRend->inputsMc ); activateInput = setRendInputActiveMc; + setInputDelay = setRendInputDelayMc; break; case IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS: maxNumInputsOfType = RENDERER_MAX_SBA_INPUTS; inputsArray = hIvasRend->inputsSba; inputStructSize = sizeof( *hIvasRend->inputsSba ); activateInput = setRendInputActiveSba; + setInputDelay = setRendInputDelaySba; break; case IVAS_REND_AUDIO_CONFIG_TYPE_MASA: maxNumInputsOfType = RENDERER_MAX_MASA_INPUTS; inputsArray = hIvasRend->inputsMasa; inputStructSize = sizeof( *hIvasRend->inputsMasa ); activateInput = setRendInputActiveMasa; + setInputDelay = setRendInputDelayMasa; break; default: return IVAS_ERR_INVALID_INPUT_FORMAT; @@ -3519,6 +3776,11 @@ ivas_error IVAS_REND_AddInput( { return error; } + setInputDelay( (uint8_t *) inputsArray + inputStructSize * inputIndex ); + + /* update global maximum delay after adding an input */ + updateMaxGlobalDelayNs( hIvasRend ); + return IVAS_ERR_OK; } @@ -3772,6 +4034,9 @@ ivas_error IVAS_REND_RemoveInput( return IVAS_ERR_INVALID_INPUT_FORMAT; } + /* update global maximum delay after removing an input */ + updateMaxGlobalDelayNs( hIvasRend ); + return IVAS_ERR_OK; } @@ -3848,11 +4113,6 @@ ivas_error IVAS_REND_GetDelay( int32_t *timeScale /* o : Time scale of the delay, equal to renderer output sampling rate */ ) { - /* TODO tmu : this function only returns the maximum delay across all inputs - * Ideally each input has its own delay buffer and everything is aligned (binaural and LFE filtering delays are nonuniform) - */ - int16_t i; - int32_t latency_ns; int32_t max_latency_ns; /* Validate function arguments */ @@ -3861,76 +4121,16 @@ ivas_error IVAS_REND_GetDelay( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - *timeScale = hIvasRend->sampleRateOut; *nSamples = 0; - max_latency_ns = 0; - - /* Compute the maximum delay across all inputs */ - for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) - { - if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) - { - latency_ns = max( ( hIvasRend->inputsIsm[i].crendWrapper != NULL ) ? hIvasRend->inputsIsm[i].crendWrapper->binaural_latency_ns : 0, - hIvasRend->inputsIsm[i].tdRendWrapper.binaural_latency_ns ); - max_latency_ns = max( max_latency_ns, latency_ns ); - } - } - - for ( i = 0; i < RENDERER_MAX_MC_INPUTS; i++ ) - { - if ( hIvasRend->inputsMc[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) - { - latency_ns = max( ( hIvasRend->inputsMc[i].crendWrapper != NULL ) ? hIvasRend->inputsMc[i].crendWrapper->binaural_latency_ns : 0, - hIvasRend->inputsMc[i].tdRendWrapper.binaural_latency_ns ); - max_latency_ns = max( max_latency_ns, latency_ns ); - } - } - - for ( i = 0; i < RENDERER_MAX_SBA_INPUTS; i++ ) - { - if ( hIvasRend->inputsSba[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) - { - if ( hIvasRend->splitRendWrapper != NULL && hIvasRend->splitRendWrapper->hBinHrSplitPreRend != NULL ) - { - if ( hIvasRend->hRendererConfig->split_rend_config.rendererSelection == IVAS_BIN_RENDERER_TYPE_FASTCONV ) - { - latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; - } - else - { - latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; - } - max_latency_ns = max( max_latency_ns, latency_ns ); - } - else if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) - { - latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; - latency_ns += IVAS_FB_DEC_DELAY_NS; - max_latency_ns = max( max_latency_ns, latency_ns ); - } - else - { - latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; - max_latency_ns = max( max_latency_ns, latency_ns ); - } - } - } + *timeScale = hIvasRend->sampleRateOut; - for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; i++ ) - { - if ( hIvasRend->inputsMasa[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) - { - latency_ns = (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ); - max_latency_ns = max( max_latency_ns, latency_ns ); - } - } + max_latency_ns = getMaxGlobalDelayNs( hIvasRend ); *nSamples = (int16_t) roundf( (float) max_latency_ns * *timeScale / 1000000000.f ); return IVAS_ERR_OK; } - /*-------------------------------------------------------------------* * IVAS_REND_FeedInputAudio() * @@ -3996,9 +4196,15 @@ ivas_error IVAS_REND_FeedInputAudio( } inputBase->inputBuffer.config = inputAudio.config; - - mvr2r( inputAudio.data, inputBase->inputBuffer.data, inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); - + if ( ( error = alignInputDelay( + inputBase, + inputAudio, + hIvasRend->maxGlobalDelayNs, + hIvasRend->sampleRateOut, + cldfb2tdSampleFact ) ) != IVAS_ERR_OK ) + { + return error; + } inputBase->numNewSamplesPerChannel = inputAudio.config.numSamplesPerChannel / cldfb2tdSampleFact; return IVAS_ERR_OK; -- GitLab From c1c91f5f7f9299b0cc1d6a2b4a36c36a8044f8e4 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 10 Jul 2025 12:08:28 +0200 Subject: [PATCH 07/49] add new files to MSVC solution --- Workspace_msvc/lib_rend.vcxproj | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 27d4a19a69..8f94f7c662 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -175,6 +175,7 @@ + @@ -185,6 +186,7 @@ + -- GitLab From 31babc7e14508544559bc0de31d2af0d248c71c2 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 10 Jul 2025 12:13:21 +0200 Subject: [PATCH 08/49] cleanup and change variable types to fix MSVC warnings --- lib_rend/lib_rend.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 50ddce03ce..57837787bd 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -82,7 +82,7 @@ typedef struct typedef struct { const int32_t *pOutSampleRate; - const float *pMaxGlobalDelayNs; + const int32_t *pMaxGlobalDelayNs; const AUDIO_CONFIG *pOutConfig; const LSSETUP_CUSTOM_STRUCT *pCustomLsOut; const EFAP_WRAPPER *pEfapOutWrapper; @@ -104,7 +104,6 @@ typedef struct rendering_context ctx; int32_t numNewSamplesPerChannel; /* Used to keep track how much new audio was fed before rendering current frame */ int32_t delayNumSamples; - float delay_ns; // TODO is this needed? } input_base; typedef struct @@ -194,7 +193,7 @@ typedef struct hrtf_handles struct IVAS_REND { int32_t sampleRateOut; // TODO rename to sampleRate? - float maxGlobalDelayNs; + int32_t maxGlobalDelayNs; IVAS_LIMITER_HANDLE hLimiter; #ifdef DEBUGGING @@ -1176,7 +1175,6 @@ static void initRendInputBase( inputBase->ctx = rendCtx; inputBase->numNewSamplesPerChannel = 0; inputBase->delayNumSamples = 0; - inputBase->delay_ns = 0; inputBase->delayBuffer = NULL; inputBase->inputBuffer.config.numSamplesPerChannel = 0; @@ -1348,7 +1346,7 @@ static void updateMaxGlobalDelayNs( IVAS_REND_HANDLE hIvasRend ) static ivas_error alignInputDelay( input_base *inputBase, const IVAS_REND_ReadOnlyAudioBuffer inputAudio, - const float maxGlobalDelayNs, + const int32_t maxGlobalDelayNs, const int32_t sampleRateOut, const int16_t cldfb2tdSampleFact ) { @@ -1444,7 +1442,6 @@ static void setRendInputDelayIsm( void *input ) (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); } - inputIsm->base.delay_ns = latency_ns; inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); } @@ -2454,7 +2451,6 @@ static void setRendInputDelayMc( void *input ) (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); } - inputMc->base.delay_ns = latency_ns; inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, latency_ns ); } @@ -2821,7 +2817,6 @@ static void setRendInputDelaySba( void *input ) (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); } - inputSba->base.delay_ns = latency_ns; inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, latency_ns ); } @@ -2920,7 +2915,6 @@ static void setRendInputDelayMasa( void *input ) (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); } - inputMasa->base.delay_ns = latency_ns; inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); } -- GitLab From 74c1a87329f1d288a07644aa4ec53fb05011bf86 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 11 Jul 2025 11:33:23 +0200 Subject: [PATCH 09/49] modify renderer zero padding to flush any delayed input samples from the delay buffers --- apps/renderer.c | 51 ++++++++++++++++++++++++++------------------- lib_rend/lib_rend.c | 19 ++++++++++------- lib_rend/lib_rend.h | 31 ++++++++++++++------------- 3 files changed, 57 insertions(+), 44 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 0096471854..0098ebbd6b 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -698,6 +698,7 @@ int main( SplitFileReadWrite *hSplitRendFileReadWrite; int16_t delayNumSamples_temp; int32_t delayTimeScale_temp; + bool flushRendererLastFrame = false; int16_t numSamplesRead; int16_t delayNumSamples = -1; int16_t delayNumSamples_orig = 0; @@ -1576,22 +1577,25 @@ int main( if ( numSamplesRead == 0 ) { /* end of input data */ - break; + flushRendererLastFrame = true; } /* Convert from int to float and from interleaved to packed */ - convertInputBuffer( inpInt16Buffer, - numSamplesRead, - inBuffer.config.numSamplesPerChannel, - num_in_channels, - inFloatBuffer, - inBuffer.config.is_cldfb, - cldfbAna ); + if ( !flushRendererLastFrame ) + { + convertInputBuffer( inpInt16Buffer, + numSamplesRead, + inBuffer.config.numSamplesPerChannel, + num_in_channels, + inFloatBuffer, + inBuffer.config.is_cldfb, + cldfbAna ); + } int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; - if ( isCurrentFrameMultipleOf20ms ) + if ( isCurrentFrameMultipleOf20ms && !flushRendererLastFrame ) { IsmPositionProvider_getNextFrame( positionProvider, &mtdBuffer ); @@ -1716,7 +1720,7 @@ int main( (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, numChannels ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1733,7 +1737,7 @@ int main( (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, args.inConfig.numAudioObjects ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1752,7 +1756,7 @@ int main( (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, 1 ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1777,7 +1781,7 @@ int main( (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, numChannels ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1795,13 +1799,13 @@ int main( (int16_t) args.inConfig.masaBuses[i].inputChannelIndex, numChannels ); - if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, masaIds[i], tmpBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, masaIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { fprintf( stderr, "IVAS_REND_FeedInputAudio failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - if ( isCurrentFrameMultipleOf20ms ) + if ( isCurrentFrameMultipleOf20ms && !flushRendererLastFrame ) { if ( masaReaders[i] != NULL ) { @@ -1879,7 +1883,7 @@ int main( } } - if ( audioWriter != NULL ) + if ( audioWriter != NULL && !flushRendererLastFrame ) { if ( delayNumSamples * num_out_channels < outBufferSize ) { @@ -1992,6 +1996,13 @@ int main( } } + /* no new input was actually read, only delay buffers were flushed + * therefore this is not a real frame */ + if ( flushRendererLastFrame ) + { + break; + } + frame++; if ( !args.quietModeEnabled ) { @@ -2004,14 +2015,13 @@ int main( #endif } - /* TODO a flush method is needed to empty the delay buffers */ - - /* add zeros at the end to have equal length of synthesized signals */ + /* add zeros at the end to have equal length of synthesized signals + * the output buffer will contain either leftover input samples from delay aligned inputs + * or zeros for padding */ if ( audioWriter != NULL ) { for ( zeroPadToWrite = zeroPad; zeroPadToWrite > frameSize_smpls; zeroPadToWrite -= frameSize_smpls ) { - memset( outInt16Buffer, 0, outBufferSize * sizeof( int16_t ) ); if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, outBufferSize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); @@ -2019,7 +2029,6 @@ int main( } } - memset( outInt16Buffer, 0, zeroPadToWrite * outBuffer.config.numChannels * sizeof( int16_t ) ); if ( ( error = AudioFileWriter_write( audioWriter, outInt16Buffer, zeroPadToWrite * outBuffer.config.numChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 57837787bd..61720b598f 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1348,7 +1348,8 @@ static ivas_error alignInputDelay( const IVAS_REND_ReadOnlyAudioBuffer inputAudio, const int32_t maxGlobalDelayNs, const int32_t sampleRateOut, - const int16_t cldfb2tdSampleFact ) + const int16_t cldfb2tdSampleFact, + const bool flushInputs ) { ivas_error error; input_ism *inputIsm; @@ -1381,7 +1382,7 @@ static ivas_error alignInputDelay( if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) { inputIsm = (input_ism *) inputBase; - inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs * 1000; + inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs * 1000.f; } } @@ -1391,8 +1392,8 @@ static ivas_error alignInputDelay( inputAudio.config.numSamplesPerChannel ); TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, - inputAudio.config.numSamplesPerChannel ); - + flushInputs ? TD_RINGBUF_Size( inputBase->delayBuffer ) : inputAudio.config.numSamplesPerChannel ); + return IVAS_ERR_OK; } @@ -4132,9 +4133,10 @@ ivas_error IVAS_REND_GetDelay( *-------------------------------------------------------------------*/ ivas_error IVAS_REND_FeedInputAudio( - IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ - const IVAS_REND_InputId inputId, /* i : ID of the input */ - const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_ReadOnlyAudioBuffer inputAudio, /* i : buffer with input audio */ + const bool flushInputs /* i : flush input audio */ ) { ivas_error error; @@ -4195,7 +4197,8 @@ ivas_error IVAS_REND_FeedInputAudio( inputAudio, hIvasRend->maxGlobalDelayNs, hIvasRend->sampleRateOut, - cldfb2tdSampleFact ) ) != IVAS_ERR_OK ) + cldfb2tdSampleFact, + flushInputs ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_rend/lib_rend.h b/lib_rend/lib_rend.h index a0aa40841b..ac9516521d 100644 --- a/lib_rend/lib_rend.h +++ b/lib_rend/lib_rend.h @@ -114,15 +114,15 @@ typedef enum _IVAS_REND_COMPLEXITY_LEVEL /* Functions to be called before rendering */ ivas_error IVAS_REND_Open( - IVAS_REND_HANDLE *phIvasRend, /* i/o: Pointer to renderer handle */ - const int32_t outputSampleRate, /* i : output sampling rate */ - const IVAS_AUDIO_CONFIG outConfig, /* i : output audio config */ - const bool asHrtfBinary, /* i : load hrtf binary file */ - const int16_t nonDiegeticPan, /* i : non-diegetic object flag */ - const float nonDiegeticPanGain, /* i : non-diegetic panning gain */ - const int16_t Opt_Headrotation, /* i : indicates whether head-rotation is used */ - const int16_t Opt_ExternalOrientation, /* i : indicates whether external orientations are used */ - const int16_t num_subframes /* i : number of subframes */ + IVAS_REND_HANDLE *phIvasRend, /* i/o: Pointer to renderer handle */ + const int32_t outputSampleRate, /* i : output sampling rate */ + const IVAS_AUDIO_CONFIG outConfig, /* i : output audio config */ + const bool asHrtfBinary, /* i : load hrtf binary file */ + const int16_t nonDiegeticPan, /* i : non-diegetic object flag */ + const float nonDiegeticPanGain, /* i : non-diegetic panning gain */ + const int16_t Opt_Headrotation, /* i : indicates whether head-rotation is used */ + const int16_t Opt_ExternalOrientation, /* i : indicates whether external orientations are used */ + const int16_t num_subframes /* i : number of subframes */ ); /* Note: this will reset custom LFE routings set for any MC input */ @@ -212,16 +212,17 @@ ivas_error IVAS_REND_GetHrtfParamBinHandle( ); ivas_error IVAS_REND_GetHrtfStatisticsHandle( - IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ - IVAS_DEC_HRTF_STATISTICS_HANDLE **hHrtfStatistics /* o : HRTF statistics handle */ + IVAS_REND_HANDLE hIvasRend, /* i/o: IVAS renderer handle */ + IVAS_DEC_HRTF_STATISTICS_HANDLE **hHrtfStatistics /* o : HRTF statistics handle */ ); /* Functions to be called during rendering */ ivas_error IVAS_REND_FeedInputAudio( - IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ - const IVAS_REND_InputId inputId, /* i : ID of the input */ - const IVAS_REND_ReadOnlyAudioBuffer inputAudio /* i : buffer with input audio */ + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + const IVAS_REND_InputId inputId, /* i : ID of the input */ + const IVAS_REND_ReadOnlyAudioBuffer inputAudio, /* i : buffer with input audio */ + const bool flushInputs /* i : flush input audio */ ); ivas_error IVAS_REND_FeedInputObjectMetadata( @@ -382,7 +383,7 @@ ivas_error IVAS_REND_GetSamples( /* Functions to be called after rendering */ void IVAS_REND_Close( - IVAS_REND_HANDLE* phIvasRend /* i/o: Pointer to renderer handle */ + IVAS_REND_HANDLE *phIvasRend /* i/o: Pointer to renderer handle */ ); -- GitLab From e4a6a6f6630f491805602324ca5490644f959c00 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 11 Jul 2025 11:36:36 +0200 Subject: [PATCH 10/49] [fix] MSVC warning --- lib_rend/lib_rend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 61720b598f..28b0433fea 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -269,7 +269,7 @@ static void freeInputBaseBufferData( static int16_t latencyNsToSamples( int32_t sampleRate, - float latency_ns ) + int32_t latency_ns ) { return (int16_t) roundf( (float) ( latency_ns ) * ( sampleRate / 1000000000.f ) ); } @@ -1393,7 +1393,7 @@ static ivas_error alignInputDelay( TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, flushInputs ? TD_RINGBUF_Size( inputBase->delayBuffer ) : inputAudio.config.numSamplesPerChannel ); - + return IVAS_ERR_OK; } -- GitLab From 3e2cf483fe7d0aa0f6e2319205e23684d8b7dae0 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 11 Jul 2025 11:43:46 +0200 Subject: [PATCH 11/49] [fix] compiler warning --- lib_rend/lib_rend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 466d885cde..1ab0edc20c 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1392,7 +1392,7 @@ static ivas_error alignInputDelay( inputAudio.config.numSamplesPerChannel ); TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, - flushInputs ? TD_RINGBUF_Size( inputBase->delayBuffer ) : inputAudio.config.numSamplesPerChannel ); + flushInputs ? TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); return IVAS_ERR_OK; } -- GitLab From 2c36836aa1c5717f4c83782323736a48ed6a96a1 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Fri, 11 Jul 2025 12:06:28 +0200 Subject: [PATCH 12/49] add missing wmc_auto.h include --- lib_rend/ivas_td_ring_buffer.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c index 6e29cc5bdd..88d6003b20 100644 --- a/lib_rend/ivas_td_ring_buffer.c +++ b/lib_rend/ivas_td_ring_buffer.c @@ -30,10 +30,11 @@ *******************************************************************************************************/ -#include "ivas_td_ring_buffer.h" -#include "ivas_error_utils.h" -#include #include +#include +#include "ivas_error_utils.h" +#include "ivas_td_ring_buffer.h" +#include "wmc_auto.h" struct TdRingBuf { -- GitLab From 38d480bfeae984308fdb85cf2c98ceb0d796d6b7 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 11:39:28 +0200 Subject: [PATCH 13/49] [fix] do not add filterbank delay for split rendering --- lib_rend/lib_rend.c | 53 +++++++++++++++++++++++---------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 1ab0edc20c..a425332526 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1272,8 +1272,10 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) int16_t i; int32_t latency_ns; int32_t max_latency_ns; + bool splitPreRendCldfb; max_latency_ns = 0; + splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ); /* Compute the maximum delay across all inputs */ for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) @@ -1300,22 +1302,10 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { if ( hIvasRend->inputsSba[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { - if ( hIvasRend->splitRendWrapper != NULL && hIvasRend->splitRendWrapper->hBinHrSplitPreRend != NULL ) - { - if ( hIvasRend->hRendererConfig->split_rend_config.rendererSelection == IVAS_BIN_RENDERER_TYPE_FASTCONV ) - { - latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; - } - else - { - latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; - } - max_latency_ns = max( max_latency_ns, latency_ns ); - } - else if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) + if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) { latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; - latency_ns += IVAS_FB_DEC_DELAY_NS; + latency_ns += splitPreRendCldfb ? 0.f : IVAS_FB_DEC_DELAY_NS; max_latency_ns = max( max_latency_ns, latency_ns ); } else @@ -1330,7 +1320,7 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { if ( hIvasRend->inputsMasa[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { - latency_ns = (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ); + latency_ns = splitPreRendCldfb ? 0 : (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ); max_latency_ns = max( max_latency_ns, latency_ns ); } } @@ -1424,7 +1414,9 @@ static ivas_error initIsmMasaRendering( return IVAS_ERR_OK; } -static void setRendInputDelayIsm( void *input ) +static void setRendInputDelayIsm( + void *input, + bool splitPreRendCldfb ) { int32_t latency_ns; input_ism *inputIsm; @@ -1444,7 +1436,7 @@ static void setRendInputDelayIsm( void *input ) { /* TODO tmu: verify what should be set for MASA prerendering */ latency_ns = max( latency_ns, - (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); @@ -2445,7 +2437,9 @@ static lfe_routing defaultLfeRouting( return routing; } -static void setRendInputDelayMc( void *input ) +static void setRendInputDelayMc( + void *input, + bool splitPreRendCldfb ) { int32_t latency_ns; input_mc *inputMc; @@ -2465,7 +2459,7 @@ static void setRendInputDelayMc( void *input ) { /* TODO tmu: verify what should be set for MASA prerendering */ latency_ns = max( latency_ns, - (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, latency_ns ); @@ -2816,7 +2810,9 @@ static ivas_error initSbaMasaRendering( return IVAS_ERR_OK; } -static void setRendInputDelaySba( void *input ) +static void setRendInputDelaySba( + void *input, + bool splitPreRendCldfb ) { int32_t latency_ns; input_sba *inputSba; @@ -2828,7 +2824,8 @@ static void setRendInputDelaySba( void *input ) if ( inputSba->cldfbRendWrapper.hCldfbRend != NULL ) { latency_ns = max( latency_ns, - inputSba->cldfbRendWrapper.binaural_latency_ns + IVAS_FB_DEC_DELAY_NS ); + inputSba->cldfbRendWrapper.binaural_latency_ns + + ( splitPreRendCldfb ? 0 : IVAS_FB_DEC_DELAY_NS ) ); } if ( inputSba->crendWrapper != NULL ) { @@ -2839,7 +2836,7 @@ static void setRendInputDelaySba( void *input ) { /* TODO tmu: verify what should be set for MASA prerendering */ latency_ns = max( latency_ns, - (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, latency_ns ); @@ -2929,7 +2926,9 @@ static void clearInputSba( return; } -static void setRendInputDelayMasa( void *input ) +static void setRendInputDelayMasa( + void *input, + bool splitPreRendCldfb ) { int32_t latency_ns; input_masa *inputMasa; @@ -2941,7 +2940,7 @@ static void setRendInputDelayMasa( void *input ) if ( inputMasa->hMasaExtRend != NULL && inputMasa->hMasaExtRend->renderer_type != RENDERER_DISABLE ) { latency_ns = max( latency_ns, - (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ); + (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); @@ -3734,8 +3733,10 @@ ivas_error IVAS_REND_AddInput( void *inputsArray; int32_t inputStructSize; ivas_error ( *activateInput )( void *, AUDIO_CONFIG, IVAS_REND_InputId, RENDER_CONFIG_DATA *, hrtf_handles * ); - void ( *setInputDelay )( void * ); + void ( *setInputDelay )( void *, bool ); int32_t inputIndex; + bool splitPreRendCldfb; + splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ); /* Validate function arguments */ if ( hIvasRend == NULL || inputId == NULL ) @@ -3799,7 +3800,7 @@ ivas_error IVAS_REND_AddInput( { return error; } - setInputDelay( (uint8_t *) inputsArray + inputStructSize * inputIndex ); + setInputDelay( (uint8_t *) inputsArray + inputStructSize * inputIndex, splitPreRendCldfb ); /* update global maximum delay after adding an input */ updateMaxGlobalDelayNs( hIvasRend ); -- GitLab From 787273dd9f4c1b6a20a7cb45470f4c05af04eecc Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 12:59:32 +0200 Subject: [PATCH 14/49] [fix] audioWriter not being opened for SPLIT_PCM after refactor --- apps/renderer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 0098ebbd6b..fb0af0b42b 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1447,9 +1447,9 @@ int main( goto cleanup; } } - else - { + if ( args.outConfig.audioConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) + { if ( AudioFileWriter_open( &audioWriter, args.outputFilePath, args.sampleRate, numOutChannels ) != IVAS_ERR_OK ) { fprintf( stderr, "\nFailed to open file: %s\n", args.outputFilePath ); -- GitLab From 3478ff504de2e77ac37c755896b751bd164f50c3 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 13:08:42 +0200 Subject: [PATCH 15/49] [fix] MSVC warning --- lib_rend/lib_rend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index a425332526..32de73bbe4 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1305,7 +1305,7 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) { latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; - latency_ns += splitPreRendCldfb ? 0.f : IVAS_FB_DEC_DELAY_NS; + latency_ns += splitPreRendCldfb ? 0 : IVAS_FB_DEC_DELAY_NS; max_latency_ns = max( max_latency_ns, latency_ns ); } else -- GitLab From 96df6025754b03d7c8a970e6add1f7de13520c50 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 13:19:16 +0200 Subject: [PATCH 16/49] [fix] MSVC build --- Workspace_msvc/lib_com.vcxproj | 2 +- Workspace_msvc/lib_rend.vcxproj | 2 +- Workspace_msvc/lib_rend.vcxproj.filters | 72 ++----------------------- 3 files changed, 5 insertions(+), 71 deletions(-) diff --git a/Workspace_msvc/lib_com.vcxproj b/Workspace_msvc/lib_com.vcxproj index 223f837a2e..c28b36a145 100644 --- a/Workspace_msvc/lib_com.vcxproj +++ b/Workspace_msvc/lib_com.vcxproj @@ -223,7 +223,7 @@ - + diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 8f94f7c662..9d6e9a8613 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -186,7 +186,7 @@ - + diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index 942c63712f..72c9ab5533 100644 --- a/Workspace_msvc/lib_rend.vcxproj.filters +++ b/Workspace_msvc/lib_rend.vcxproj.filters @@ -32,30 +32,12 @@ rend_c - - rend_c - - - rend_c - - - rend_c - - - rend_c - rend_c rend_c - - rend_c - - - rend_c - rend_c @@ -83,15 +65,6 @@ rend_c - - rend_c - - - rend_c - - - rend_c - rend_c @@ -113,9 +86,6 @@ rend_c - - rend_c - rend_c @@ -134,24 +104,6 @@ rend_c - - rend_c - - - rend_c - - - rend_c - - - rend_c - - - rend_c - - - rend_c - rend_c @@ -161,30 +113,15 @@ rend_c - - rend_c - - - rend_c - - + rend_c - + rend_c - - rend_h - - - rend_h - - - rend_h - rend_h @@ -203,10 +140,7 @@ rend_h - - rend_h - - + rend_h -- GitLab From 07b2309303157742edab9a523865eb85f8911cfe Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 13:49:46 +0200 Subject: [PATCH 17/49] [fix] incorrectly scaled value set for ISM metadata delay --- lib_rend/lib_rend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 32de73bbe4..ad631df681 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1372,7 +1372,7 @@ static ivas_error alignInputDelay( if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) { inputIsm = (input_ism *) inputBase; - inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs * 1000.f; + inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs / 1000.f; } } -- GitLab From d210182e0902db1195cbb83b6c433aa0e6d9e867 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 16:48:58 +0200 Subject: [PATCH 18/49] refactor IVAS_REND_GetSamples() and IVAS_REND_GetSplitBinauralBitstream() --- lib_rend/lib_rend.c | 245 +++++++++++++++++++++++++------------------- 1 file changed, 140 insertions(+), 105 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index ad631df681..ddf704aac9 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3749,7 +3749,14 @@ ivas_error IVAS_REND_AddInput( int16_t cldfb_in_flag; cldfb_in_flag = getCldfbRendFlag( hIvasRend, getAudioConfigType( inConfig ) ); - 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 ) + 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 ) { return error; } @@ -4644,7 +4651,14 @@ ivas_error IVAS_REND_FeedRenderConfig( hIvasRend->splitRendWrapper = NULL; } - 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 ) + 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 ) { return error; } @@ -7576,7 +7590,6 @@ static ivas_error getSamplesInternal( ivas_error error; int16_t numOutChannels; int16_t cldfb2tdSampleFact; - IVAS_REND_AudioBuffer outAudioOrig; /* Validate function arguments */ if ( hIvasRend == NULL || outAudio.data == NULL ) @@ -7646,24 +7659,9 @@ static ivas_error getSamplesInternal( return IVAS_ERR_WRONG_NUM_CHANNELS; } - /* Clear original output buffer */ + /* Clear output buffer */ set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); - outAudioOrig = outAudio; - /* Use internal buffer if outputting split rendering bitstream */ - if ( ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || - ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - int16_t num_poses_orig; - num_poses_orig = hIvasRend->splitRendWrapper->multiBinPoseData.num_poses; - outAudio = hIvasRend->splitRendEncBuffer; - ISAR_PRE_REND_GetMultiBinPoseData( &hIvasRend->hRendererConfig->split_rend_config, &hIvasRend->splitRendWrapper->multiBinPoseData, hIvasRend->headRotData.sr_pose_pred_axis ); - assert( num_poses_orig == hIvasRend->splitRendWrapper->multiBinPoseData.num_poses && "number of poses should not change dynamically" ); - - /* Clear output buffer for split rendering bitstream */ - set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); - } - if ( ( error = renderActiveInputsIsm( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) { return error; @@ -7684,73 +7682,26 @@ static ivas_error getSamplesInternal( return error; } - if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - ISAR_SPLIT_REND_BITS_DATA bits; - int16_t cldfb_in_flag; - float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; - int16_t ch; - int16_t i, ro_md_flag; - float *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; - - for ( ch = 0; ch < MAX_OUTPUT_CHANNELS; ch++ ) - { - tmpBinaural[ch] = tmpBinaural_buff[ch]; - } - - if ( outAudio.config.is_cldfb == 1 ) - { - cldfb_in_flag = 1; - copyBufferToCLDFBarray( outAudio, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); - } - else - { - cldfb_in_flag = 0; - copyBufferTo2dArray( outAudio, tmpBinaural_buff ); - } - - /* Encode split rendering bitstream */ - convertBitsBufferToInternalBitsBuff( *hBits, &bits ); - - ro_md_flag = 0; - for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) - { - if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) - { - ro_md_flag = 1; - break; - } - } + return IVAS_ERR_OK; +} - if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( hIvasRend->splitRendWrapper, - hIvasRend->headRotData.headPositions[0], - hIvasRend->hRendererConfig->split_rend_config.splitRendBitRate, - hIvasRend->hRendererConfig->split_rend_config.codec, - hIvasRend->hRendererConfig->split_rend_config.isar_frame_size_ms, - hIvasRend->hRendererConfig->split_rend_config.codec_frame_size_ms, - &bits, - Cldfb_RealBuffer_Binaural, - Cldfb_ImagBuffer_Binaural, - ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), - tmpBinaural, - 1, - cldfb_in_flag, - ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, - ro_md_flag ) ) != IVAS_ERR_OK ) - { - return error; - } - convertInternalBitsBuffToBitsBuffer( hBits, bits ); +/*-------------------------------------------------------------------* + * IVAS_REND_GetSamples() + * + * + *-------------------------------------------------------------------*/ - /* reset to outAudioOrig in case of PCM output */ - outAudio = outAudioOrig; +ivas_error IVAS_REND_GetSamples( + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ +) +{ + ivas_error error; - if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - accumulate2dArrayToBuffer( tmpBinaural_buff, &outAudio ); - } + if ( ( error = getSamplesInternal( hIvasRend, outAudio, NULL ) ) != IVAS_ERR_OK ) + { + return error; } if ( outAudio.config.is_cldfb == 0 ) @@ -7770,22 +7721,6 @@ static ivas_error getSamplesInternal( } -/*-------------------------------------------------------------------* - * IVAS_REND_GetSamples() - * - * - *-------------------------------------------------------------------*/ - -ivas_error IVAS_REND_GetSamples( - IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ - IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ -) -{ - - return getSamplesInternal( hIvasRend, outAudio, NULL ); -} - - /*-------------------------------------------------------------------* * IVAS_REND_GetSplitBinauralBitstream() * @@ -7798,23 +7733,123 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( IVAS_REND_BitstreamBuffer *hBits /* o : buffer for output bitstream */ ) { + ivas_error error; + int16_t ch; int16_t cldfb_in_flag; + int16_t i, ro_md_flag; + int16_t num_poses_orig; + float *tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS], tmpBinaural_buff[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + IVAS_REND_AudioBufferConfig *pSplitEncBufConfig; + ISAR_SPLIT_REND_CONFIG_HANDLE pSplitRendConfig; + ISAR_SPLIT_REND_BITS_DATA bits; + + for ( ch = 0; ch < MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS; ch++ ) + { + tmpBinaural[ch] = tmpBinaural_buff[ch]; + } cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); - hIvasRend->splitRendEncBuffer.config.is_cldfb = cldfb_in_flag; - if ( hIvasRend->hRendererConfig->split_rend_config.dof == 0 || hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) + pSplitEncBufConfig = &hIvasRend->splitRendEncBuffer.config; + pSplitRendConfig = &hIvasRend->hRendererConfig->split_rend_config; + + /* configure output buffer for the split rendering multi-poses */ + pSplitEncBufConfig->is_cldfb = cldfb_in_flag; + if ( pSplitRendConfig->dof == 0 || pSplitRendConfig->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) { - hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = outAudio.config.numSamplesPerChannel; + pSplitEncBufConfig->numSamplesPerChannel = outAudio.config.numSamplesPerChannel; } else { - hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = (int16_t) ( hIvasRend->sampleRateOut / FRAMES_PER_SEC ); + pSplitEncBufConfig->numSamplesPerChannel = (int16_t) ( hIvasRend->sampleRateOut / FRAMES_PER_SEC ); } - hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel *= cldfb_in_flag ? 2 : 1; + pSplitEncBufConfig->numSamplesPerChannel *= cldfb_in_flag ? 2 : 1; + + num_poses_orig = hIvasRend->splitRendWrapper->multiBinPoseData.num_poses; + ISAR_PRE_REND_GetMultiBinPoseData( pSplitRendConfig, + &hIvasRend->splitRendWrapper->multiBinPoseData, + hIvasRend->headRotData.sr_pose_pred_axis ); + assert( num_poses_orig == hIvasRend->splitRendWrapper->multiBinPoseData.num_poses && "number of poses should not change dynamically" ); + + /* Clear output buffer for split rendering bitstream */ + set_zero( hIvasRend->splitRendEncBuffer.data, pSplitEncBufConfig->numChannels * pSplitEncBufConfig->numSamplesPerChannel ); /* hIvasRend->splitRendEncBuffer used for BINAURAL_SPLIT_CODED output - outAudio used for BINAURAL_SPLIT_PCM output */ - return getSamplesInternal( hIvasRend, outAudio, hBits ); + outAudio used later for BINAURAL_SPLIT_PCM output */ + if ( ( error = getSamplesInternal( hIvasRend, + hIvasRend->splitRendEncBuffer, + NULL ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* copy outputs */ + if ( hIvasRend->splitRendEncBuffer.config.is_cldfb == 1 ) + { + cldfb_in_flag = 1; + copyBufferToCLDFBarray( hIvasRend->splitRendEncBuffer, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural ); + } + else + { + cldfb_in_flag = 0; + copyBufferTo2dArray( hIvasRend->splitRendEncBuffer, tmpBinaural_buff ); + } + + /* Encode split rendering bitstream */ + convertBitsBufferToInternalBitsBuff( *hBits, &bits ); + + ro_md_flag = 0; + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + { + if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + ro_md_flag = 1; + break; + } + } + + if ( ( error = ISAR_PRE_REND_MultiBinToSplitBinaural( hIvasRend->splitRendWrapper, + hIvasRend->headRotData.headPositions[0], + pSplitRendConfig->splitRendBitRate, + pSplitRendConfig->codec, + pSplitRendConfig->isar_frame_size_ms, + pSplitRendConfig->codec_frame_size_ms, + &bits, + Cldfb_RealBuffer_Binaural, + Cldfb_ImagBuffer_Binaural, + ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), + tmpBinaural, + 1, + cldfb_in_flag, + ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ? 1 : 0, + ro_md_flag ) ) != IVAS_ERR_OK ) + { + return error; + } + + convertInternalBitsBuffToBitsBuffer( hBits, bits ); + + /* copy over first pose data to outAudio */ + if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + accumulate2dArrayToBuffer( tmpBinaural_buff, &outAudio ); + } + + if ( outAudio.config.is_cldfb == 0 ) + { +#ifndef DISABLE_LIMITER +#ifdef DEBUGGING + hIvasRend->numClipping += +#endif + limitRendererOutput( hIvasRend->hLimiter, outAudio.data, outAudio.config.numSamplesPerChannel, IVAS_LIMITER_THRESHOLD ); +#endif + } + + /* update global cominbed orientation start index */ + ivas_combined_orientation_update_start_index( hIvasRend->hCombinedOrientationData, outAudio.config.numSamplesPerChannel ); + + return IVAS_ERR_OK; } -- GitLab From 5ef0184ac4d9c21d66a8481ed7ac8cb72e873c90 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 14 Jul 2025 17:10:15 +0200 Subject: [PATCH 19/49] [fix] unused parameter --- lib_rend/lib_rend.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index ddf704aac9..1265219f2b 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3744,7 +3744,7 @@ ivas_error IVAS_REND_AddInput( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) && hIvasRend->splitRendEncBuffer.data == NULL && hIvasRend->hRendererConfig != NULL ) + if ( hIvasRend->splitRendEncBuffer.data == NULL && hIvasRend->hRendererConfig != NULL ) { int16_t cldfb_in_flag; cldfb_in_flag = getCldfbRendFlag( hIvasRend, getAudioConfigType( inConfig ) ); @@ -7582,9 +7582,8 @@ ivas_error IVAS_REND_SetIsmMetadataDelay( *-------------------------------------------------------------------*/ static ivas_error getSamplesInternal( - IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ - IVAS_REND_AudioBuffer outAudio, /* i/o: buffer for output audio */ - IVAS_REND_BitstreamBuffer *hBits /*i/o: buffer for input/output bitstream. Needed in split rendering mode*/ + IVAS_REND_HANDLE hIvasRend, /* i/o: Renderer handle */ + IVAS_REND_AudioBuffer outAudio /* i/o: buffer for output audio */ ) { ivas_error error; @@ -7699,7 +7698,7 @@ ivas_error IVAS_REND_GetSamples( { ivas_error error; - if ( ( error = getSamplesInternal( hIvasRend, outAudio, NULL ) ) != IVAS_ERR_OK ) + if ( ( error = getSamplesInternal( hIvasRend, outAudio ) ) != IVAS_ERR_OK ) { return error; } @@ -7777,9 +7776,7 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( /* hIvasRend->splitRendEncBuffer used for BINAURAL_SPLIT_CODED output outAudio used later for BINAURAL_SPLIT_PCM output */ - if ( ( error = getSamplesInternal( hIvasRend, - hIvasRend->splitRendEncBuffer, - NULL ) ) != IVAS_ERR_OK ) + if ( ( error = getSamplesInternal( hIvasRend, hIvasRend->splitRendEncBuffer ) ) != IVAS_ERR_OK ) { return error; } -- GitLab From 28afcf833ee4fad922c3a10029e6e84b070b8323 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 16 Jul 2025 12:37:55 +0200 Subject: [PATCH 20/49] fix typos in comments --- lib_isar/lib_isar_pre_rend.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 09323f6eed..24e54aa760 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -53,8 +53,8 @@ *------------------------------------------------------------------------*/ ivas_error ISAR_PRE_REND_open( - SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renerer handle */ - ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i/o: Split renderer pre-renerer config */ + SPLIT_REND_WRAPPER *hSplitBinRend, /* i/o: Split renderer pre-renderer handle */ + ISAR_SPLIT_REND_CONFIG_DATA *pSplitRendConfig, /* i/o: Split renderer pre-renderer config */ const int32_t output_Fs, /* i : output sampling rate */ const int16_t cldfb_in_flag, /* i : Flag to indicate CLDFB or time doamin input */ const int16_t pcm_out_flag, /* i : Flag to indicate PCM output */ @@ -286,7 +286,7 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( const int16_t max_bands, /* i : CLDFB bands */ float *output[], /* i/o: PCM in/out buffer */ const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ - const int16_t cldfb_in_flag, /* i : Flag to indicate CLDFB or time doamin input */ + const int16_t cldfb_in_flag, /* i : Flag to indicate CLDFB or time domain input */ const int16_t pcm_out_flag, /* i : Flag to indicate PCM output */ const int16_t ro_md_flag /* i : Flag to indicate real only metadata for yaw */ ) -- GitLab From 3ff214577650e9b7b349a44934753240f04a3a12 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 16 Jul 2025 12:40:26 +0200 Subject: [PATCH 21/49] [fix] split rendering for combined formats with ext renderer; perform CLDFB analysis for ISM if needed --- lib_isar/lib_isar_pre_rend.c | 4 +- lib_rend/lib_rend.c | 156 +++++++++++++++++++++++------------ 2 files changed, 102 insertions(+), 58 deletions(-) diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 24e54aa760..d24bc94de7 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -94,9 +94,7 @@ ivas_error ISAR_PRE_REND_open( isCldfbNeeded = 1; } - hSplitBinRend->hCldfbHandles = NULL; - - if ( isCldfbNeeded ) + if ( isCldfbNeeded && hSplitBinRend->hCldfbHandles == NULL ) { if ( ( hSplitBinRend->hCldfbHandles = (CLDFB_HANDLES_WRAPPER_HANDLE) malloc( sizeof( CLDFB_HANDLES_WRAPPER ) ) ) == NULL ) { diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 1265219f2b..09fdeeccd1 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -192,7 +192,7 @@ typedef struct hrtf_handles struct IVAS_REND { - int32_t sampleRateOut; // TODO rename to sampleRate? + int32_t sampleRateOut; int32_t maxGlobalDelayNs; IVAS_LIMITER_HANDLE hLimiter; @@ -209,11 +209,12 @@ struct IVAS_REND AUDIO_CONFIG outputConfig; EFAP_WRAPPER efapOutWrapper; IVAS_LSSETUP_CUSTOM_STRUCT customLsOut; + + int16_t splitRendBFI; SPLIT_REND_WRAPPER *splitRendWrapper; IVAS_REND_AudioBuffer splitRendEncBuffer; IVAS_REND_HeadRotData headRotData; - int16_t splitRendBFI; EXTERNAL_ORIENTATION_HANDLE hExternalOrientationData; COMBINED_ORIENTATION_HANDLE hCombinedOrientationData; @@ -381,7 +382,7 @@ static void copyBufferToCLDFBarray( static void accumulateCLDFBArrayToBuffer( float re[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], float im[][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], - IVAS_REND_AudioBuffer *buffer ) + const IVAS_REND_AudioBuffer *buffer ) { uint32_t smplIdx, slotIdx; uint32_t numCldfbSamples, num_bands; @@ -3619,10 +3620,15 @@ static int16_t getCldfbRendFlag( const IVAS_REND_AudioConfigType new_configType ) { int16_t i; - int16_t numMasaInputs = 0, numSbaInputs = 0, numIsmInputs = 0, numMcInputs = 0; + int16_t numMasaInputs = 0, numSbaInputs = 0; int16_t isCldfbRend; isCldfbRend = 0; + /* This function is called during three different phases of renderer processing: + * - IVAS_REND_AddInput() + * - IVAS_REND_FeedRenderConfig() + * - IVAS_REND_GetSplitBinauralBitstream() + * Only the last case can assume all inputs are present for the current frame to be rendered */ if ( hIvasRend->hRendererConfig != NULL ) { for ( i = 0; i < RENDERER_MAX_MASA_INPUTS; ++i ) @@ -3633,20 +3639,7 @@ static int16_t getCldfbRendFlag( { numSbaInputs += ( hIvasRend->inputsSba[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_AMBISONICS ) ? 0 : 1; } - for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) - { - numIsmInputs += ( hIvasRend->inputsIsm[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) ? 0 : 1; - } - for ( i = 0; i < RENDERER_MAX_MC_INPUTS; ++i ) - { - numMcInputs += ( hIvasRend->inputsMc[i].base.inConfig == IVAS_AUDIO_CONFIG_INVALID && new_configType != IVAS_REND_AUDIO_CONFIG_TYPE_CHANNEL_BASED ) ? 0 : 1; - } - - if ( numIsmInputs > 0 || numMcInputs > 0 ) - { - isCldfbRend = 0; - } - else if ( ( numMasaInputs > 0 ) || ( numSbaInputs > 0 && hIvasRend->hRendererConfig->split_rend_config.rendererSelection == IVAS_BIN_RENDERER_TYPE_FASTCONV ) ) + if ( ( numMasaInputs > 0 ) || ( numSbaInputs > 0 && hIvasRend->hRendererConfig->split_rend_config.rendererSelection == IVAS_BIN_RENDERER_TYPE_FASTCONV ) ) { isCldfbRend = 1; } @@ -3661,7 +3654,7 @@ static int16_t getCldfbRendFlag( * *------------------------------------------------------------------------*/ -static ivas_error ivas_pre_rend_init( +static ivas_error isar_pre_rend_init( SPLIT_REND_WRAPPER *pSplitRendWrapper, IVAS_REND_AudioBuffer *pSplitRendEncBuffer, ISAR_SPLIT_REND_CONFIG_DATA *pSplit_rend_config, @@ -3671,9 +3664,12 @@ static ivas_error ivas_pre_rend_init( const int16_t cldfb_in_flag, const int16_t num_subframes ) { + bool realloc; ivas_error error; IVAS_REND_AudioBufferConfig bufConfig; + realloc = false; + if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) @@ -3685,31 +3681,43 @@ static ivas_error ivas_pre_rend_init( isar_renderSplitUpdateNoCorrectionPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData ); } - 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 ) + 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 ) { return error; } - /*allocate for CLDFB in and change to TD during process if needed*/ - bufConfig.numSamplesPerChannel = MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL; - bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; - bufConfig.is_cldfb = 1; - pSplitRendEncBuffer->config = bufConfig; - if ( ( pSplitRendEncBuffer->data = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) + /* If the cldfb_in_flag is different from what was previously allocated for the buffer, change the size */ + if ( pSplitRendEncBuffer->data != NULL && ( cldfb_in_flag != bufConfig.is_cldfb ) ) { - return IVAS_ERR_FAILED_ALLOC; + realloc = true; } - } - else - { - IVAS_REND_AudioBufferConfig bufConfig2; - bufConfig2.numSamplesPerChannel = 0; - bufConfig2.numChannels = 0; - bufConfig2.is_cldfb = 0; - pSplitRendEncBuffer->config = bufConfig2; - pSplitRendEncBuffer->data = NULL; + if ( pSplitRendEncBuffer->data == NULL || realloc ) + { + /* set buffer config */ + bufConfig.numSamplesPerChannel = cldfb_in_flag ? MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL : L_FRAME_MAX; + bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; + bufConfig.is_cldfb = cldfb_in_flag; + pSplitRendEncBuffer->config = bufConfig; + + /* allocate memory */ + if ( realloc ) + { + free( pSplitRendEncBuffer->data ); + } + + if ( ( pSplitRendEncBuffer->data = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) + { + return IVAS_ERR_FAILED_ALLOC; + } + } } return IVAS_ERR_OK; @@ -3744,12 +3752,12 @@ ivas_error IVAS_REND_AddInput( return IVAS_ERR_UNEXPECTED_NULL_POINTER; } - if ( hIvasRend->splitRendEncBuffer.data == NULL && hIvasRend->hRendererConfig != NULL ) + if ( hIvasRend->hRendererConfig != NULL ) { int16_t cldfb_in_flag; cldfb_in_flag = getCldfbRendFlag( hIvasRend, getAudioConfigType( inConfig ) ); - if ( ( error = ivas_pre_rend_init( hIvasRend->splitRendWrapper, + if ( ( error = isar_pre_rend_init( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, @@ -4651,7 +4659,7 @@ ivas_error IVAS_REND_FeedRenderConfig( hIvasRend->splitRendWrapper = NULL; } - if ( ( error = ivas_pre_rend_init( hIvasRend->splitRendWrapper, + if ( ( error = isar_pre_rend_init( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer, &hIvasRend->hRendererConfig->split_rend_config, hIvasRend->headRotData, @@ -5757,8 +5765,10 @@ static ivas_error renderIsmToSplitBinaural( const MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData; const SPLIT_REND_WRAPPER *pSplitRendWrapper; IVAS_QUATERNION originalHeadRot[MAX_PARAM_SPATIAL_SUBFRAMES]; - int16_t i; + int16_t i, ch, slot_idx, num_bands; float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; + float tmpBinaural_CldfbRe[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + float tmpBinaural_CldfbIm[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; int16_t output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; int16_t ism_md_subframe_update_ext; @@ -5819,16 +5829,43 @@ static ivas_error renderIsmToSplitBinaural( } /* Render */ - if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[pos_idx - 1], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, - NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[pos_idx - 1], + ismInput->base.inConfig, + NULL, + ismInput->base.ctx.pCombinedOrientationData, + &ismInput->currentPos, + NULL, + ism_md_subframe_update_ext, + *ismInput->base.ctx.pOutSampleRate, + output_frame, + tmpProcessing ) ) != IVAS_ERR_OK ) { return error; } - /* Copy rendered audio to tmp storage buffer. Copying directly to output would - * overwrite original audio, which is still needed for rendering next head pose. */ - mvr2r( tmpProcessing[0], tmpBinaural[2 * pos_idx], output_frame ); - mvr2r( tmpProcessing[1], tmpBinaural[2 * pos_idx + 1], output_frame ); + if ( outAudio.config.is_cldfb ) + { + /* Perform CLDFB analysis on rendered audio, since the output buffer is CLDFB domain */ + num_bands = (int16_t) ( ( BINAURAL_MAXBANDS * *ismInput->base.ctx.pOutSampleRate ) / 48000 ); + for ( ch = 0; ch < BINAURAL_CHANNELS; ch++ ) + { + for ( slot_idx = 0; slot_idx < IVAS_CLDFB_NO_COL_MAX; slot_idx++ ) + { + cldfbAnalysis_ts( &tmpProcessing[ch][num_bands * slot_idx], + &tmpBinaural_CldfbRe[BINAURAL_CHANNELS * pos_idx + ch][slot_idx][0], + &tmpBinaural_CldfbIm[BINAURAL_CHANNELS * pos_idx + ch][slot_idx][0], + num_bands, + ismInput->base.ctx.pSplitRendWrapper->hCldfbHandles->cldfbAna[pos_idx + ch] ); + } + } + } + else + { + /* Copy rendered audio to tmp storage buffer. Copying directly to output would + * overwrite original audio, which is still needed for rendering next head pose. */ + mvr2r( tmpProcessing[0], tmpBinaural[BINAURAL_CHANNELS * pos_idx], output_frame ); + mvr2r( tmpProcessing[1], tmpBinaural[BINAURAL_CHANNELS * pos_idx + 1], output_frame ); + } /* Overwrite processing buffer with original input audio again */ copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing ); @@ -5840,7 +5877,14 @@ static ivas_error renderIsmToSplitBinaural( pCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; } - accumulate2dArrayToBuffer( tmpBinaural, &outAudio ); + if ( outAudio.config.is_cldfb ) + { + accumulateCLDFBArrayToBuffer( tmpBinaural_CldfbRe, tmpBinaural_CldfbIm, &outAudio ); + } + else + { + accumulate2dArrayToBuffer( tmpBinaural, &outAudio ); + } pop_wmops(); /* Encoding to split rendering bitstream done at a higher level */ @@ -5875,11 +5919,13 @@ static ivas_error renderInputIsm( { ivas_error error; IVAS_REND_AudioBuffer inAudio; + int16_t cldfb2tdSampleFact; error = IVAS_ERR_OK; inAudio = ismInput->base.inputBuffer; - if ( ismInput->base.numNewSamplesPerChannel != outAudio.config.numSamplesPerChannel ) + cldfb2tdSampleFact = outAudio.config.is_cldfb ? 2 : 1; + if ( ismInput->base.numNewSamplesPerChannel * cldfb2tdSampleFact != outAudio.config.numSamplesPerChannel ) { return IVAS_ERROR( IVAS_ERR_INVALID_BUFFER_SIZE, "Mismatch between the number of input samples vs number of requested output samples - currently not allowed" ); } @@ -7653,7 +7699,9 @@ static ivas_error getSamplesInternal( return error; } - if ( numOutChannels != outAudio.config.numChannels && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + if ( numOutChannels != outAudio.config.numChannels && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && + hIvasRend->outputConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { return IVAS_ERR_WRONG_NUM_CHANNELS; } @@ -7753,12 +7801,13 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( pSplitEncBufConfig = &hIvasRend->splitRendEncBuffer.config; pSplitRendConfig = &hIvasRend->hRendererConfig->split_rend_config; - /* configure output buffer for the split rendering multi-poses */ + /* 0 DoF / No pose correction retains frame size */ pSplitEncBufConfig->is_cldfb = cldfb_in_flag; if ( pSplitRendConfig->dof == 0 || pSplitRendConfig->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ) { pSplitEncBufConfig->numSamplesPerChannel = outAudio.config.numSamplesPerChannel; } + /* Pose correction requires 20ms */ else { pSplitEncBufConfig->numSamplesPerChannel = (int16_t) ( hIvasRend->sampleRateOut / FRAMES_PER_SEC ); @@ -7771,11 +7820,8 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( hIvasRend->headRotData.sr_pose_pred_axis ); assert( num_poses_orig == hIvasRend->splitRendWrapper->multiBinPoseData.num_poses && "number of poses should not change dynamically" ); - /* Clear output buffer for split rendering bitstream */ - set_zero( hIvasRend->splitRendEncBuffer.data, pSplitEncBufConfig->numChannels * pSplitEncBufConfig->numSamplesPerChannel ); - - /* hIvasRend->splitRendEncBuffer used for BINAURAL_SPLIT_CODED output - outAudio used later for BINAURAL_SPLIT_PCM output */ + /* hIvasRend->splitRendEncBuffer contains multi-pose data for BINAURAL_SPLIT_CODED output + outAudio used later for main pose BINAURAL_SPLIT_PCM output */ if ( ( error = getSamplesInternal( hIvasRend, hIvasRend->splitRendEncBuffer ) ) != IVAS_ERR_OK ) { return error; -- GitLab From 514a6350fbe5c700a421523fe1c9b5310c24c9e5 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 16 Jul 2025 12:47:32 +0200 Subject: [PATCH 22/49] [fix] use correct variable to check buffer config state --- lib_rend/lib_rend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 5037b06da9..206ee946fd 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3666,7 +3666,7 @@ static ivas_error isar_pre_rend_init( /* If the cldfb_in_flag is different from what was previously allocated for the buffer, change the size */ - if ( pSplitRendEncBuffer->data != NULL && ( cldfb_in_flag != bufConfig.is_cldfb ) ) + if ( pSplitRendEncBuffer->data != NULL && ( cldfb_in_flag != pSplitRendEncBuffer->config.is_cldfb ) ) { realloc = true; } @@ -3674,9 +3674,9 @@ static ivas_error isar_pre_rend_init( if ( pSplitRendEncBuffer->data == NULL || realloc ) { /* set buffer config */ + bufConfig.is_cldfb = cldfb_in_flag; bufConfig.numSamplesPerChannel = cldfb_in_flag ? MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL : L_FRAME_MAX; bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; - bufConfig.is_cldfb = cldfb_in_flag; pSplitRendEncBuffer->config = bufConfig; /* allocate memory */ -- GitLab From 62a12c784946012fa2d6b00557d0b69804c768c3 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 16 Jul 2025 13:21:40 +0200 Subject: [PATCH 23/49] [fix] missing initialization for splitRendEncBuffer.config --- lib_rend/lib_rend.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 206ee946fd..896300be47 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3110,6 +3110,9 @@ ivas_error IVAS_REND_Open( isar_init_split_rend_handles( hIvasRend->splitRendWrapper ); } hIvasRend->splitRendEncBuffer.data = NULL; + hIvasRend->splitRendEncBuffer.config.is_cldfb = 0; + hIvasRend->splitRendEncBuffer.config.numChannels = 0; + hIvasRend->splitRendEncBuffer.config.numSamplesPerChannel = 0; for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) { -- GitLab From b2226e4afde8bc025974d1154604287b74a7fb5d Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 16 Jul 2025 13:51:57 +0200 Subject: [PATCH 24/49] [fix] sanitizer errors due to multiple calls to ISAR_PRE_REND_Open() --- lib_rend/lib_rend.c | 50 ++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 896300be47..81f9c0b0a8 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3645,7 +3645,14 @@ static ivas_error isar_pre_rend_init( realloc = false; - if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + /* only perform init if split rendering output */ + if ( outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && outConfig != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + return IVAS_ERR_OK; + } + + /* these function should only be called once during initial allocation */ + if ( pSplitRendEncBuffer->data == NULL ) { if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) { @@ -3666,32 +3673,33 @@ static ivas_error isar_pre_rend_init( { return error; } + } + + + /* We may need to change the allocated buffer size if a new input is added. + * If the cldfb_in_flag is different from what was previously allocated for the buffer, change the size */ + if ( pSplitRendEncBuffer->data != NULL && ( cldfb_in_flag != pSplitRendEncBuffer->config.is_cldfb ) ) + { + realloc = true; + } + if ( pSplitRendEncBuffer->data == NULL || realloc ) + { + /* set buffer config */ + bufConfig.is_cldfb = cldfb_in_flag; + bufConfig.numSamplesPerChannel = cldfb_in_flag ? MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL : L_FRAME_MAX; + bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; + pSplitRendEncBuffer->config = bufConfig; - /* If the cldfb_in_flag is different from what was previously allocated for the buffer, change the size */ - if ( pSplitRendEncBuffer->data != NULL && ( cldfb_in_flag != pSplitRendEncBuffer->config.is_cldfb ) ) + /* allocate memory */ + if ( realloc ) { - realloc = true; + free( pSplitRendEncBuffer->data ); } - if ( pSplitRendEncBuffer->data == NULL || realloc ) + if ( ( pSplitRendEncBuffer->data = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) { - /* set buffer config */ - bufConfig.is_cldfb = cldfb_in_flag; - bufConfig.numSamplesPerChannel = cldfb_in_flag ? MAX_CLDFB_BUFFER_LENGTH_PER_CHANNEL : L_FRAME_MAX; - bufConfig.numChannels = BINAURAL_CHANNELS * pSplitRendWrapper->multiBinPoseData.num_poses; - pSplitRendEncBuffer->config = bufConfig; - - /* allocate memory */ - if ( realloc ) - { - free( pSplitRendEncBuffer->data ); - } - - if ( ( pSplitRendEncBuffer->data = malloc( bufConfig.numChannels * bufConfig.numSamplesPerChannel * sizeof( float ) ) ) == NULL ) - { - return IVAS_ERR_FAILED_ALLOC; - } + return IVAS_ERR_FAILED_ALLOC; } } -- GitLab From 3bf28ecbcc9d37c24ccbc02d16ba7a6b0a3c4784 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Wed, 16 Jul 2025 14:55:09 +0200 Subject: [PATCH 25/49] [fix] wrong factor used for ISM metadata delay --- lib_rend/lib_rend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 81f9c0b0a8..7886c153c1 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1373,7 +1373,7 @@ static ivas_error alignInputDelay( if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) { inputIsm = (input_ism *) inputBase; - inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs / 1000.f; + inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs / 1e6f; } } -- GitLab From f4215bf1d140bdebe4597208f2d8fd4002bfef27 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 12:23:59 +0200 Subject: [PATCH 26/49] replace latencyNsToSamples with NS2SA --- lib_rend/lib_rend.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 7886c153c1..9d11409cba 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -268,13 +268,6 @@ static void freeInputBaseBufferData( return; } -static int16_t latencyNsToSamples( - int32_t sampleRate, - int32_t latency_ns ) -{ - return (int16_t) roundf( (float) ( latency_ns ) * ( sampleRate / 1000000000.f ) ); -} - static ivas_error allocateMcLfeDelayBuffer( float **lfeDelayBuffer, const int16_t data_size ) @@ -1347,7 +1340,7 @@ static ivas_error alignInputDelay( int16_t maxGlobalDelaySamples; uint32_t tmpSize; - maxGlobalDelaySamples = latencyNsToSamples( sampleRateOut, maxGlobalDelayNs ); + maxGlobalDelaySamples = NS2SA( sampleRateOut, maxGlobalDelayNs ); maxGlobalDelaySamples *= cldfb2tdSampleFact; /* open the delay buffer if it isn't already */ @@ -1436,7 +1429,7 @@ static void setRendInputDelayIsm( (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } - inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); + inputIsm->base.delayNumSamples = NS2SA( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); } @@ -2447,7 +2440,7 @@ static void setRendInputDelayMc( (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } - inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, latency_ns ); + inputMc->base.delayNumSamples = NS2SA( *inputMc->base.ctx.pOutSampleRate, latency_ns ); } static ivas_error setRendInputActiveMc( @@ -2816,7 +2809,7 @@ static void setRendInputDelaySba( (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } - inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, latency_ns ); + inputSba->base.delayNumSamples = NS2SA( *inputSba->base.ctx.pOutSampleRate, latency_ns ); } static ivas_error setRendInputActiveSba( @@ -2916,7 +2909,7 @@ static void setRendInputDelayMasa( (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } - inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); + inputMasa->base.delayNumSamples = NS2SA( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); } static ivas_error setRendInputActiveMasa( -- GitLab From 4e95bd875e2c2b3845cf46465b273c4163a1ec48 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 14:09:13 +0200 Subject: [PATCH 27/49] rename TD ring buffer functions and add comments --- lib_rend/ivas_prot_rend.h | 44 ++++++++++ lib_rend/ivas_td_ring_buffer.c | 147 ++++++++++++++++++++++++--------- lib_rend/ivas_td_ring_buffer.h | 106 ------------------------ lib_rend/lib_rend.c | 19 ++--- 4 files changed, 161 insertions(+), 155 deletions(-) delete mode 100644 lib_rend/ivas_td_ring_buffer.h diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index bb936d4b14..0ad2749468 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1582,6 +1582,50 @@ void ivas_rend_closeCldfbRend( CLDFB_REND_WRAPPER *pCldfbRend ); +/*----------------------------------------------------------------------------------* + * Time domain ring buffer prototypes + *----------------------------------------------------------------------------------*/ + +typedef struct TdRingBuf *TD_RINGBUF_HANDLE; + +ivas_error IVAS_TD_RINGBUF_Open( + TD_RINGBUF_HANDLE *ph, + uint32_t capacity_per_channel, + uint16_t num_channels +); + +void IVAS_TD_RINGBUF_Close( + TD_RINGBUF_HANDLE *ph +); + +void IVAS_TD_RINGBUF_Push( + TD_RINGBUF_HANDLE h, + const float *data, + uint32_t num_samples_per_channel +); + +void IVAS_TD_RINGBUF_PushZeros( + TD_RINGBUF_HANDLE h, + uint32_t num_samples_per_channel +); + +void IVAS_TD_RINGBUF_Pop( + TD_RINGBUF_HANDLE h, + float *data, + uint32_t num_samples_per_channel +); + +int16_t IVAS_TD_RINGBUF_IsEmpty( + const TD_RINGBUF_HANDLE h +); + +uint32_t IVAS_TD_RINGBUF_Size( + const TD_RINGBUF_HANDLE h +); + +void IVAS_TD_RINGBUF_Clear( + TD_RINGBUF_HANDLE h +); /* clang-format on */ diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c index 88d6003b20..a6de74ae70 100644 --- a/lib_rend/ivas_td_ring_buffer.c +++ b/lib_rend/ivas_td_ring_buffer.c @@ -33,7 +33,8 @@ #include #include #include "ivas_error_utils.h" -#include "ivas_td_ring_buffer.h" +#include "ivas_prot_rend.h" +#include "options.h" #include "wmc_auto.h" struct TdRingBuf @@ -46,7 +47,46 @@ struct TdRingBuf int16_t is_full; }; -ivas_error TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, uint32_t capacity_per_channel, uint16_t num_channels ) +/*-----------------------------------------------------------------------* + * Local function prototypes + *-----------------------------------------------------------------------*/ + +static uint32_t ivas_td_ringbuf_total_size( TD_RINGBUF_HANDLE h ) +{ + if ( h->is_full ) + { + return h->capacity; + } + + if ( h->read_pos <= h->write_pos ) + { + return h->write_pos - h->read_pos; + } + /* else wrap around */ + return h->write_pos + h->capacity - h->read_pos; +} + +static int16_t ivas_td_ringbuf_has_space_for_num_samples( TD_RINGBUF_HANDLE h, const uint32_t num_samples ) +{ + return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity ); +} + +/*-----------------------------------------------------------------------* + * Global function definitions + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * TD_RINGBUF_Open() + * + * Allocate a ring buffer for TD data with the given capacity of TD samples per channel. + * + * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise. + *---------------------------------------------------------------------*/ +ivas_error IVAS_TD_RINGBUF_Open( + TD_RINGBUF_HANDLE *ph, /* i/o: Ring buffer handle */ + const uint32_t capacity_per_channel, /* i : Number of samples stored per channel */ + const uint16_t num_channels /* i : Number of channels */ +) { TD_RINGBUF_HANDLE h; uint32_t capacity; @@ -75,7 +115,14 @@ ivas_error TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, uint32_t capacity_per_channel return IVAS_ERR_OK; } -void TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_Close() + * + * Dellocate TD ring buffer. The given handle will be set to NULL. + *---------------------------------------------------------------------*/ +void IVAS_TD_RINGBUF_Close( + TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */ +) { TD_RINGBUF_HANDLE h; @@ -101,33 +148,22 @@ void TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph ) return; } -/* Returns total number of buffered samples (includes number of channels) */ -static uint32_t total_size( TD_RINGBUF_HANDLE h ) -{ - if ( TD_RINGBUF_IsFull( h ) ) - { - return h->capacity; - } - - if ( h->read_pos <= h->write_pos ) - { - return h->write_pos - h->read_pos; - } - /* else wrap around */ - return h->write_pos + h->capacity - h->read_pos; -} - -static int16_t has_space_for_num_samples( TD_RINGBUF_HANDLE h, uint32_t num_samples ) -{ - return (int16_t) ( total_size( h ) + num_samples <= h->capacity ); -} - -void TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, uint32_t num_samples_per_channel ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_Push() + * + * Push samples onto the back of the TD ring buffer. + * Returns total number of buffered samples (includes number of channels) + *---------------------------------------------------------------------*/ +void IVAS_TD_RINGBUF_Push( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const float *data, /* i : Input data */ + const uint32_t num_samples_per_channel /* i : Number of samples per channel to store */ +) { uint32_t s; uint16_t c; - assert( has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); + assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); for ( s = 0; s < num_samples_per_channel; ++s ) { @@ -151,12 +187,20 @@ void TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, uint32_t num_sampl return; } -void TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, uint32_t num_samples_per_channel ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_PushZeros() + * + * Push zero samples onto the back of the TD ring buffer. + *---------------------------------------------------------------------*/ +void IVAS_TD_RINGBUF_PushZeros( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + const uint32_t num_samples_per_channel /* i : Number of zeros per channel to store */ +) { uint32_t s; uint16_t c; - assert( has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); + assert( ivas_td_ringbuf_has_space_for_num_samples( h, num_samples_per_channel * h->num_channels ) ); if ( !num_samples_per_channel ) { return; @@ -184,12 +228,21 @@ void TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, uint32_t num_samples_per_channel return; } -void TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, uint32_t num_samples_per_channel ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_Pop() + * + * Pop samples from the front of the TD ring buffer. + *---------------------------------------------------------------------*/ +void IVAS_TD_RINGBUF_Pop( + TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ + float *data, /* i : Output data */ + const uint32_t num_samples_per_channel /* i : Number of samples per channel to retrieve */ +) { uint32_t s; uint16_t c; - assert( total_size( h ) >= num_samples_per_channel * h->num_channels ); + assert( ivas_td_ringbuf_total_size( h ) >= num_samples_per_channel * h->num_channels ); for ( s = 0; s < num_samples_per_channel; ++s ) { @@ -213,22 +266,38 @@ void TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, uint32_t num_samples_per_ return; } -int16_t TD_RINGBUF_IsEmpty( TD_RINGBUF_HANDLE h ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_IsEmpty() + * + * Returns 1 if the ring buffer is empty, or 0 otherwise. + *---------------------------------------------------------------------*/ +int16_t IVAS_TD_RINGBUF_IsEmpty( + const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ +) { return (int16_t) ( h->read_pos == h->write_pos && !h->is_full ); } -int16_t TD_RINGBUF_IsFull( TD_RINGBUF_HANDLE h ) -{ - return h->is_full; -} - -uint32_t TD_RINGBUF_Size( TD_RINGBUF_HANDLE h ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_Size() + * + * Returns number of buffered samples per channel. + *---------------------------------------------------------------------*/ +uint32_t IVAS_TD_RINGBUF_Size( + const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ +) { - return total_size( h ) / (uint32_t) h->num_channels; + return ivas_td_ringbuf_total_size( h ) / (uint32_t) h->num_channels; } -void TD_RINGBUF_Clear( TD_RINGBUF_HANDLE h ) +/*---------------------------------------------------------------------* + * TD_RINGBUF_Clear() + * + * Remove all samples from the buffer. + *---------------------------------------------------------------------*/ +void IVAS_TD_RINGBUF_Clear( + TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ +) { h->read_pos = h->write_pos; h->is_full = 0; diff --git a/lib_rend/ivas_td_ring_buffer.h b/lib_rend/ivas_td_ring_buffer.h deleted file mode 100644 index 4670f88fab..0000000000 --- a/lib_rend/ivas_td_ring_buffer.h +++ /dev/null @@ -1,106 +0,0 @@ -/****************************************************************************************************** - - (C) 2022-2025 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. - -*******************************************************************************************************/ - -#ifndef IVAS_TD_RING_BUFFER_H -#define IVAS_TD_RING_BUFFER_H - -#include "ivas_error.h" -#include - -typedef struct TdRingBuf *TD_RINGBUF_HANDLE; - -/*---------------------------------------------------------------------* - * TD_RINGBUF_Open() - * - * Allocate a ring buffer for TD data with the given capacity of TD samples per channel. - * - * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise. - *---------------------------------------------------------------------*/ -ivas_error TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, uint32_t capacity_per_channel, uint16_t num_channels ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_Close() - * - * Dellocate TD ring buffer. The given handle will be set to NULL. - *---------------------------------------------------------------------*/ -void TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_Push() - * - * Push samples onto the back of the TD ring buffer. - *---------------------------------------------------------------------*/ -void TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, uint32_t num_samples_per_channel ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_PushZeros() - * - * Push zero samples onto the back of the TD ring buffer. - *---------------------------------------------------------------------*/ -void TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, uint32_t num_samples_per_channel ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_Pop() - * - * Pop samples from the front of the TD ring buffer. - *---------------------------------------------------------------------*/ -void TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, uint32_t num_samples_per_channel ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_IsEmpty() - * - * Returns 1 if the ring buffer is empty, or 0 otherwise. - *---------------------------------------------------------------------*/ -int16_t TD_RINGBUF_IsEmpty( TD_RINGBUF_HANDLE h ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_IsFull() - * - * Returns 1 if the ring buffer is full, or 0 otherwise. - *---------------------------------------------------------------------*/ -int16_t TD_RINGBUF_IsFull( TD_RINGBUF_HANDLE h ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_Size() - * - * Returns number of buffered samples per channel. - *---------------------------------------------------------------------*/ -uint32_t TD_RINGBUF_Size( TD_RINGBUF_HANDLE h ); - -/*---------------------------------------------------------------------* - * TD_RINGBUF_Clear() - * - * Remove all samples from the buffer. - *---------------------------------------------------------------------*/ -void TD_RINGBUF_Clear( TD_RINGBUF_HANDLE h ); - -#endif /* IVAS_TD_RING_BUFFER_H */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 9d11409cba..f340f4a3b8 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -40,7 +40,6 @@ #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_rend.h" -#include "ivas_td_ring_buffer.h" #include #include #include @@ -1349,7 +1348,7 @@ static ivas_error alignInputDelay( /* buffer has to accomodate maxGlobalDelaySamples + 2 * frameSize */ tmpSize = maxGlobalDelaySamples; tmpSize += 2 * inputAudio.config.numSamplesPerChannel; - if ( ( error = TD_RINGBUF_Open( &inputBase->delayBuffer, + if ( ( error = IVAS_TD_RINGBUF_Open( &inputBase->delayBuffer, tmpSize, inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) { @@ -1359,7 +1358,7 @@ static ivas_error alignInputDelay( /* for the first frame we need to push zeros to align the input delay to the global delay * and then push a frame of actual data */ tmpSize = maxGlobalDelaySamples - inputBase->delayNumSamples * cldfb2tdSampleFact; - TD_RINGBUF_PushZeros( inputBase->delayBuffer, + IVAS_TD_RINGBUF_PushZeros( inputBase->delayBuffer, tmpSize ); /* for ISM inputs, ensure the metadata sync delay is updated */ @@ -1371,12 +1370,12 @@ static ivas_error alignInputDelay( } /* push in the new input data and pop to retrieve a complete input frame */ - TD_RINGBUF_Push( inputBase->delayBuffer, + IVAS_TD_RINGBUF_Push( inputBase->delayBuffer, inputAudio.data, inputAudio.config.numSamplesPerChannel ); - TD_RINGBUF_Pop( inputBase->delayBuffer, + IVAS_TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, - flushInputs ? TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); + flushInputs ? IVAS_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); return IVAS_ERR_OK; } @@ -1544,7 +1543,7 @@ static void clearInputIsm( rendCtx = inputIsm->base.ctx; freeInputBaseBufferData( &inputIsm->base.inputBuffer.data ); - TD_RINGBUF_Close( &inputIsm->base.delayBuffer ); + IVAS_TD_RINGBUF_Close( &inputIsm->base.delayBuffer ); initRendInputBase( &inputIsm->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2543,7 +2542,7 @@ static void clearInputMc( freeMcLfeDelayBuffer( &inputMc->lfeDelayBuffer ); freeInputBaseBufferData( &inputMc->bufferData ); - TD_RINGBUF_Close( &inputMc->base.delayBuffer ); + IVAS_TD_RINGBUF_Close( &inputMc->base.delayBuffer ); initRendInputBase( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2875,7 +2874,7 @@ static void clearInputSba( rendCtx = inputSba->base.ctx; freeInputBaseBufferData( &inputSba->bufferData ); - TD_RINGBUF_Close( &inputSba->base.delayBuffer ); + IVAS_TD_RINGBUF_Close( &inputSba->base.delayBuffer ); initRendInputBase( &inputSba->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2974,7 +2973,7 @@ static void clearInputMasa( rendCtx = inputMasa->base.ctx; freeInputBaseBufferData( &inputMasa->bufferData ); - TD_RINGBUF_Close( &inputMasa->base.delayBuffer ); + IVAS_TD_RINGBUF_Close( &inputMasa->base.delayBuffer ); masaPrerendClose( &inputMasa->hMasaPrerend ); freeMasaExtRenderer( &inputMasa->hMasaExtRend ); -- GitLab From ee4a0f8d28c8ec122dbeac1a9813dcf6e21ad1ab Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 14:13:10 +0200 Subject: [PATCH 28/49] update comment with new function name --- lib_rend/lib_rend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index f340f4a3b8..f6b774d52c 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3616,7 +3616,7 @@ static int16_t getCldfbRendFlag( } /*------------------------------------------------------------------------- - * Function ivas_pre_rend_init() + * Function isar_pre_rend_init() * * *------------------------------------------------------------------------*/ -- GitLab From a3f4c871031d3421d11cd464c4d305e1e65dcc12 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 14:32:42 +0200 Subject: [PATCH 29/49] [revert] whitespace changes --- apps/renderer.c | 117 ++++++++------------------------------------ lib_rend/lib_rend.c | 29 ++--------- 2 files changed, 25 insertions(+), 121 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 8a3b28f54c..82924ce492 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -824,20 +824,12 @@ int main( if ( args.sceneDescriptionInput ) { /* With scene description input, inputFilePath is the path to the scene description file. Parse it. */ - parseSceneDescriptionFile( args.inputFilePath, - audioFilePath, - &args.inConfig, - positionProvider, - masaReaders, - lfeRoutingConfigs ); + parseSceneDescriptionFile( args.inputFilePath, audioFilePath, &args.inConfig, positionProvider, masaReaders, lfeRoutingConfigs ); } else { /* With single-format input, all information is given on command line. */ - setupWithSingleFormatInput( args, - audioFilePath, - positionProvider, - masaReaders ); + setupWithSingleFormatInput( args, audioFilePath, positionProvider, masaReaders ); } /* Check that there is allowed configuration for MASA format output */ @@ -903,15 +895,7 @@ int main( const int16_t frameSize_smpls = (int16_t) ( ( args.render_framesize ) * args.sampleRate * 5 / ( 1000 ) ); - if ( ( error = IVAS_REND_Open( &hIvasRend, - args.sampleRate, - args.outConfig.audioConfig, - !isEmptyString( args.customHrtfFilePath ), - args.nonDiegeticPan, - args.nonDiegeticPanGain, - args.Opt_Headrotation, - args.Opt_ExternalOrientation, - (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_Open( &hIvasRend, args.sampleRate, args.outConfig.audioConfig, !isEmptyString( args.customHrtfFilePath ), args.nonDiegeticPan, args.nonDiegeticPanGain, args.Opt_Headrotation, args.Opt_ExternalOrientation, (int16_t) args.render_framesize ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError opening renderer handle: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1234,9 +1218,7 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, - mcIds[i], - args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, mcIds[i], args.inputGainGlobal * dBToLin( args.inConfig.multiChannelBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1269,11 +1251,7 @@ int main( /* set panning gains for input LFE */ else if ( args.lfePanningEnabled ) { - if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, - mcIds[i], - args.lfeConfigGain, - args.lfeConfigAzimuth, - args.lfeConfigElevation ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], args.lfeConfigGain, args.lfeConfigAzimuth, args.lfeConfigElevation ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputLfePos failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1302,11 +1280,7 @@ int main( /* set position based gains */ else { - if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, - mcIds[i], - lfeRoutingConfigs[i]->lfe_gain_dB, - lfeRoutingConfigs[i]->lfe_azi, - lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputLfePos( hIvasRend, mcIds[i], lfeRoutingConfigs[i]->lfe_gain_dB, lfeRoutingConfigs[i]->lfe_azi, lfeRoutingConfigs[i]->lfe_ele ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputLfePos failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1324,9 +1298,7 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, - ismIds[i], - args.inputGainGlobal * dBToLin( args.inConfig.audioObjects[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, ismIds[i], args.inputGainGlobal * dBToLin( args.inConfig.audioObjects[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1347,9 +1319,7 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, - sbaIds[i], - args.inputGainGlobal * dBToLin( args.inConfig.ambisonicsBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, sbaIds[i], args.inputGainGlobal * dBToLin( args.inConfig.ambisonicsBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1364,9 +1334,7 @@ int main( goto cleanup; } - if ( ( error = IVAS_REND_SetInputGain( hIvasRend, - masaIds[i], - args.inputGainGlobal * dBToLin( args.inConfig.masaBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetInputGain( hIvasRend, masaIds[i], args.inputGainGlobal * dBToLin( args.inConfig.masaBuses[i].gain_dB ) ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nIVAS_REND_SetInputGain failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1398,11 +1366,7 @@ int main( if ( cldfb_in_flag ) { - if ( ( error = IVAS_REND_openCldfb( cldfbAna, - cldfbSyn, - totalNumInChannels, - numOutChannels, - args.sampleRate ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_openCldfb( cldfbAna, cldfbSyn, totalNumInChannels, numOutChannels, args.sampleRate ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_openCldfb(): %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1433,16 +1397,7 @@ int main( goto cleanup; } - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, - outFile, - delayNumSamples_temp, - delayTimeScale_temp, - bitsBuffer.config.codec, - bitsBuffer.config.poseCorrection, - bitsBuffer.config.codec_frame_size_ms, - bitsBuffer.config.isar_frame_size_ms, - args.sampleRate, - bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nCould not open split rend metadata file %s\n", outFile ); goto cleanup; @@ -1544,9 +1499,7 @@ int main( args.aeSequence.selected = 0; } args.aeSequence.frameCounter = 0; - if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, - args.aeSequence.pID[args.aeSequence.selected], - &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) + if ( ( error = RenderConfigReader_getAcousticEnvironment( renderConfigReader, args.aeSequence.pID[args.aeSequence.selected], &renderConfig.roomAcoustics ) ) == IVAS_ERR_OK ) { if ( RenderConfigReader_checkValues( &renderConfig ) != IVAS_ERR_OK ) { @@ -1675,12 +1628,7 @@ int main( int16_t numFramesToTargetOrientation[IVAS_MAX_PARAM_SPATIAL_SUBFRAMES]; for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { - if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, - &quatBuffer[sf_idx], - &enableHeadRotation[sf_idx], - &enableExternalOrientation[sf_idx], - &enableRotationInterpolation[sf_idx], - &numFramesToTargetOrientation[sf_idx] ) ) != IVAS_ERR_OK ) + if ( ( error = ExternalOrientationFileReading( externalOrientationFileReader, &quatBuffer[sf_idx], &enableHeadRotation[sf_idx], &enableExternalOrientation[sf_idx], &enableRotationInterpolation[sf_idx], &numFramesToTargetOrientation[sf_idx] ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in External Orientation File Reading: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1688,13 +1636,7 @@ int main( } for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { - if ( ( error = IVAS_REND_SetExternalOrientation( hIvasRend, - &quatBuffer[sf_idx], - enableHeadRotation[sf_idx], - enableExternalOrientation[sf_idx], - enableRotationInterpolation[sf_idx], - numFramesToTargetOrientation[sf_idx], - sf_idx ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_REND_SetExternalOrientation( hIvasRend, &quatBuffer[sf_idx], enableHeadRotation[sf_idx], enableExternalOrientation[sf_idx], enableRotationInterpolation[sf_idx], numFramesToTargetOrientation[sf_idx], sf_idx ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError setting External Orientation: %s\n", ivas_error_to_string( error ) ); goto cleanup; @@ -1717,9 +1659,7 @@ int main( fprintf( stderr, "\nIVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, - (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, - numChannels ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.multiChannelBuses[i].inputChannelIndex, numChannels ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, mcIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { @@ -1734,9 +1674,7 @@ int main( { if ( i == 0 ) { - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, - (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, - args.inConfig.numAudioObjects ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, args.inConfig.numAudioObjects ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { @@ -1753,9 +1691,7 @@ int main( } else { - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, - (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, - 1 ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.audioObjects[i].inputChannelIndex, 1 ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, ismIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { @@ -1778,9 +1714,7 @@ int main( fprintf( stderr, "\nIVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, - (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, - numChannels ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.ambisonicsBuses[i].inputChannelIndex, numChannels ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, sbaIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { @@ -1796,9 +1730,7 @@ int main( fprintf( stderr, "IVAS_REND_GetInputNumChannels failed: %s\n", ivas_error_to_string( error ) ); goto cleanup; } - IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, - (int16_t) args.inConfig.masaBuses[i].inputChannelIndex, - numChannels ); + IVAS_REND_ReadOnlyAudioBuffer tmpBuffer = getReadOnlySubBuffer( inBuffer, (int16_t) args.inConfig.masaBuses[i].inputChannelIndex, numChannels ); if ( ( error = IVAS_REND_FeedInputAudio( hIvasRend, masaIds[i], tmpBuffer, flushRendererLastFrame ) ) != IVAS_ERR_OK ) { @@ -1848,12 +1780,7 @@ int main( /* Convert from float to int and from packed to interleaved. * Values in outFloatBuffer are guaranteed to be within range INT16_MIN:INT16_MAX */ - convertOutputBuffer( outFloatBuffer, - outBuffer.config.numSamplesPerChannel, - num_out_channels, - outInt16Buffer, - cldfb_in_flag, - cldfbSyn ); + convertOutputBuffer( outFloatBuffer, outBuffer.config.numSamplesPerChannel, num_out_channels, outInt16Buffer, cldfb_in_flag, cldfbSyn ); if ( delayNumSamples == -1 ) { @@ -1888,9 +1815,7 @@ int main( { if ( delayNumSamples * num_out_channels < outBufferSize ) { - if ( AudioFileWriter_write( audioWriter, - &outInt16Buffer[delayNumSamples * num_out_channels], - outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) + if ( AudioFileWriter_write( audioWriter, &outInt16Buffer[delayNumSamples * num_out_channels], outBufferSize - ( delayNumSamples * num_out_channels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError writing audio file %s\n", args.outputFilePath ); goto cleanup; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index f6b774d52c..a14ba924a4 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -3655,13 +3655,7 @@ static ivas_error isar_pre_rend_init( isar_renderSplitUpdateNoCorrectionPoseData( pSplit_rend_config, &pSplitRendWrapper->multiBinPoseData ); } - 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 ) + 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 ) { return error; } @@ -4634,14 +4628,7 @@ ivas_error IVAS_REND_FeedRenderConfig( hIvasRend->splitRendWrapper = NULL; } - if ( ( error = isar_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 ) + if ( ( error = isar_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 ) { return error; } @@ -5804,16 +5791,8 @@ static ivas_error renderIsmToSplitBinaural( } /* Render */ - if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[pos_idx - 1], - ismInput->base.inConfig, - NULL, - ismInput->base.ctx.pCombinedOrientationData, - &ismInput->currentPos, - NULL, - ism_md_subframe_update_ext, - *ismInput->base.ctx.pOutSampleRate, - output_frame, - tmpProcessing ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_td_binaural_renderer_ext( ( pos_idx == 0 ) ? &ismInput->tdRendWrapper : &ismInput->splitTdRendWrappers[pos_idx - 1], ismInput->base.inConfig, NULL, ismInput->base.ctx.pCombinedOrientationData, &ismInput->currentPos, + NULL, ism_md_subframe_update_ext, *ismInput->base.ctx.pOutSampleRate, output_frame, tmpProcessing ) ) != IVAS_ERR_OK ) { return error; } -- GitLab From d5de3ae85ab73f2de2a51357bb45bc2db240d0fb Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 14:38:35 +0200 Subject: [PATCH 30/49] clang-format --- apps/renderer.c | 2 +- lib_rend/lib_rend.c | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 82924ce492..3a95fe62ef 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1397,7 +1397,7 @@ int main( goto cleanup; } - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nCould not open split rend metadata file %s\n", outFile ); goto cleanup; diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index a14ba924a4..5cc554bfc1 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1349,8 +1349,8 @@ static ivas_error alignInputDelay( tmpSize = maxGlobalDelaySamples; tmpSize += 2 * inputAudio.config.numSamplesPerChannel; if ( ( error = IVAS_TD_RINGBUF_Open( &inputBase->delayBuffer, - tmpSize, - inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) + tmpSize, + inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) { return error; } @@ -1359,7 +1359,7 @@ static ivas_error alignInputDelay( * and then push a frame of actual data */ tmpSize = maxGlobalDelaySamples - inputBase->delayNumSamples * cldfb2tdSampleFact; IVAS_TD_RINGBUF_PushZeros( inputBase->delayBuffer, - tmpSize ); + tmpSize ); /* for ISM inputs, ensure the metadata sync delay is updated */ if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) @@ -1371,11 +1371,11 @@ static ivas_error alignInputDelay( /* push in the new input data and pop to retrieve a complete input frame */ IVAS_TD_RINGBUF_Push( inputBase->delayBuffer, - inputAudio.data, - inputAudio.config.numSamplesPerChannel ); + inputAudio.data, + inputAudio.config.numSamplesPerChannel ); IVAS_TD_RINGBUF_Pop( inputBase->delayBuffer, - inputBase->inputBuffer.data, - flushInputs ? IVAS_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); + inputBase->inputBuffer.data, + flushInputs ? IVAS_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); return IVAS_ERR_OK; } -- GitLab From 7e984fb26f2fb134017aa59e5b5214cad25a742d Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 14:38:51 +0200 Subject: [PATCH 31/49] update MSVC solution to reflect file removal --- Workspace_msvc/lib_rend.vcxproj | 1 - Workspace_msvc/lib_rend.vcxproj.filters | 1 - 2 files changed, 2 deletions(-) diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 9d6e9a8613..854c99a979 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -186,7 +186,6 @@ - diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index 72c9ab5533..bd5ef00ad2 100644 --- a/Workspace_msvc/lib_rend.vcxproj.filters +++ b/Workspace_msvc/lib_rend.vcxproj.filters @@ -140,7 +140,6 @@ rend_h - rend_h -- GitLab From 348300c36e5bd7141609975855cf8724b3f506e5 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 21 Jul 2025 15:47:40 +0200 Subject: [PATCH 32/49] [fix] MSVC compiler issues --- Workspace_msvc/lib_rend.vcxproj.filters | 2 -- lib_rend/ivas_prot_rend.h | 12 ++++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index bd5ef00ad2..2d1d7d46c0 100644 --- a/Workspace_msvc/lib_rend.vcxproj.filters +++ b/Workspace_msvc/lib_rend.vcxproj.filters @@ -140,8 +140,6 @@ rend_h - rend_h - diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 0ad2749468..a15431c38b 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1590,8 +1590,8 @@ typedef struct TdRingBuf *TD_RINGBUF_HANDLE; ivas_error IVAS_TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, - uint32_t capacity_per_channel, - uint16_t num_channels + const uint32_t capacity_per_channel, + const uint16_t num_channels ); void IVAS_TD_RINGBUF_Close( @@ -1601,18 +1601,18 @@ void IVAS_TD_RINGBUF_Close( void IVAS_TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, - uint32_t num_samples_per_channel + const uint32_t num_samples_per_channel ); void IVAS_TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, - uint32_t num_samples_per_channel + const uint32_t num_samples_per_channel ); void IVAS_TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, - uint32_t num_samples_per_channel + const uint32_t num_samples_per_channel ); int16_t IVAS_TD_RINGBUF_IsEmpty( @@ -1620,7 +1620,7 @@ int16_t IVAS_TD_RINGBUF_IsEmpty( ); uint32_t IVAS_TD_RINGBUF_Size( - const TD_RINGBUF_HANDLE h + const TD_RINGBUF_HANDLE h ); void IVAS_TD_RINGBUF_Clear( -- GitLab From c813b41278132011038e7b176b712fe772a9671d Mon Sep 17 00:00:00 2001 From: vaclav Date: Mon, 21 Jul 2025 16:11:28 +0200 Subject: [PATCH 33/49] formal improvements --- apps/renderer.c | 16 ++------ lib_rend/ivas_prot_rend.h | 28 +++++++------- lib_rend/ivas_stat_rend.h | 16 ++++++++ lib_rend/ivas_td_ring_buffer.c | 70 ++++++++++++++++++++-------------- lib_rend/lib_rend.c | 31 +++++++-------- 5 files changed, 88 insertions(+), 73 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 3a95fe62ef..8f699597aa 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1376,16 +1376,14 @@ int main( if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { char *outFile = args.outMetadataFilePath; + if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) { outFile = args.outputFilePath; audioWriter = NULL; } - if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, - &bitsBuffer.config.codec, - &bitsBuffer.config.poseCorrection, - &bitsBuffer.config.codec_frame_size_ms, - &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) + + if ( ( error = IVAS_REND_GetSplitRendBitstreamHeader( hIvasRend, &bitsBuffer.config.codec, &bitsBuffer.config.poseCorrection, &bitsBuffer.config.codec_frame_size_ms, &bitsBuffer.config.isar_frame_size_ms ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_GetSplitRendBitstreamHeader()!\n" ); goto cleanup; @@ -1537,13 +1535,7 @@ int main( /* Convert from int to float and from interleaved to packed */ if ( !flushRendererLastFrame ) { - convertInputBuffer( inpInt16Buffer, - numSamplesRead, - inBuffer.config.numSamplesPerChannel, - num_in_channels, - inFloatBuffer, - inBuffer.config.is_cldfb, - cldfbAna ); + convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); } int16_t num_subframes, sf_idx; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 0ad2749468..56aa8451d1 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1586,44 +1586,42 @@ void ivas_rend_closeCldfbRend( * Time domain ring buffer prototypes *----------------------------------------------------------------------------------*/ -typedef struct TdRingBuf *TD_RINGBUF_HANDLE; - -ivas_error IVAS_TD_RINGBUF_Open( +ivas_error ivas_TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, - uint32_t capacity_per_channel, - uint16_t num_channels + const uint32_t capacity_per_channel, + const uint16_t num_channels ); -void IVAS_TD_RINGBUF_Close( +void ivas_TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph ); -void IVAS_TD_RINGBUF_Push( +void ivas_TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, const float *data, - uint32_t num_samples_per_channel + const uint32_t num_samples_per_channel ); -void IVAS_TD_RINGBUF_PushZeros( +void ivas_TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, - uint32_t num_samples_per_channel + const uint32_t num_samples_per_channel ); -void IVAS_TD_RINGBUF_Pop( +void ivas_TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, float *data, - uint32_t num_samples_per_channel + const uint32_t num_samples_per_channel ); -int16_t IVAS_TD_RINGBUF_IsEmpty( +int16_t ivas_TD_RINGBUF_IsEmpty( const TD_RINGBUF_HANDLE h ); -uint32_t IVAS_TD_RINGBUF_Size( +uint32_t ivas_TD_RINGBUF_Size( const TD_RINGBUF_HANDLE h ); -void IVAS_TD_RINGBUF_Clear( +void ivas_TD_RINGBUF_Clear( TD_RINGBUF_HANDLE h ); diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index e990c336f6..69fcb30fb8 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -1371,6 +1371,22 @@ typedef struct } CLDFB_REND_WRAPPER; +/*----------------------------------------------------------------------------------* + * Time domain ring buffer structure + *----------------------------------------------------------------------------------*/ + +typedef struct +{ + float *data; /* samples in interleaved layout */ + uint32_t capacity; + uint16_t num_channels; + uint32_t write_pos; + uint32_t read_pos; + int16_t is_full; + +} TD_RINGBUF_DATA, *TD_RINGBUF_HANDLE; + + /*----------------------------------------------------------------------------------* * MASA external renderer structure *----------------------------------------------------------------------------------*/ diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c index a6de74ae70..718c6cd5cc 100644 --- a/lib_rend/ivas_td_ring_buffer.c +++ b/lib_rend/ivas_td_ring_buffer.c @@ -37,21 +37,13 @@ #include "options.h" #include "wmc_auto.h" -struct TdRingBuf -{ - float *data; /* samples in interleaved layout */ - uint32_t capacity; - uint16_t num_channels; - uint32_t write_pos; - uint32_t read_pos; - int16_t is_full; -}; /*-----------------------------------------------------------------------* * Local function prototypes *-----------------------------------------------------------------------*/ -static uint32_t ivas_td_ringbuf_total_size( TD_RINGBUF_HANDLE h ) +static uint32_t ivas_td_ringbuf_total_size( + TD_RINGBUF_HANDLE h ) { if ( h->is_full ) { @@ -66,23 +58,28 @@ static uint32_t ivas_td_ringbuf_total_size( TD_RINGBUF_HANDLE h ) return h->write_pos + h->capacity - h->read_pos; } -static int16_t ivas_td_ringbuf_has_space_for_num_samples( TD_RINGBUF_HANDLE h, const uint32_t num_samples ) + +static int16_t ivas_td_ringbuf_has_space_for_num_samples( + TD_RINGBUF_HANDLE h, + const uint32_t num_samples ) { return (int16_t) ( ivas_td_ringbuf_total_size( h ) + num_samples <= h->capacity ); } + /*-----------------------------------------------------------------------* * Global function definitions *-----------------------------------------------------------------------*/ /*---------------------------------------------------------------------* - * TD_RINGBUF_Open() + * ivas_TD_RINGBUF_Open() * * Allocate a ring buffer for TD data with the given capacity of TD samples per channel. * * May return IVAS_ERR_FAILED_ALLOC on failed allocation, or IVAS_ERR_OK otherwise. *---------------------------------------------------------------------*/ -ivas_error IVAS_TD_RINGBUF_Open( + +ivas_error ivas_TD_RINGBUF_Open( TD_RINGBUF_HANDLE *ph, /* i/o: Ring buffer handle */ const uint32_t capacity_per_channel, /* i : Number of samples stored per channel */ const uint16_t num_channels /* i : Number of channels */ @@ -90,9 +87,10 @@ ivas_error IVAS_TD_RINGBUF_Open( { TD_RINGBUF_HANDLE h; uint32_t capacity; + capacity = capacity_per_channel * num_channels; - h = malloc( sizeof( struct TdRingBuf ) ); + h = malloc( sizeof( TD_RINGBUF_DATA ) ); if ( h == NULL ) { return IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Failed to allocate memory for TD ring buffer\n" ); @@ -115,12 +113,15 @@ ivas_error IVAS_TD_RINGBUF_Open( return IVAS_ERR_OK; } + /*---------------------------------------------------------------------* - * TD_RINGBUF_Close() + * ivas_TD_RINGBUF_Close() * * Dellocate TD ring buffer. The given handle will be set to NULL. + *---------------------------------------------------------------------*/ -void IVAS_TD_RINGBUF_Close( + +void ivas_TD_RINGBUF_Close( TD_RINGBUF_HANDLE *ph /* i/o: Ring buffer handle */ ) { @@ -148,13 +149,15 @@ void IVAS_TD_RINGBUF_Close( return; } + /*---------------------------------------------------------------------* - * TD_RINGBUF_Push() + * ivas_TD_RINGBUF_Push() * * Push samples onto the back of the TD ring buffer. * Returns total number of buffered samples (includes number of channels) *---------------------------------------------------------------------*/ -void IVAS_TD_RINGBUF_Push( + +void ivas_TD_RINGBUF_Push( TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ const float *data, /* i : Input data */ const uint32_t num_samples_per_channel /* i : Number of samples per channel to store */ @@ -187,12 +190,14 @@ void IVAS_TD_RINGBUF_Push( return; } + /*---------------------------------------------------------------------* - * TD_RINGBUF_PushZeros() + * ivas_TD_RINGBUF_PushZeros() * * Push zero samples onto the back of the TD ring buffer. *---------------------------------------------------------------------*/ -void IVAS_TD_RINGBUF_PushZeros( + +void ivas_TD_RINGBUF_PushZeros( TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ const uint32_t num_samples_per_channel /* i : Number of zeros per channel to store */ ) @@ -228,12 +233,14 @@ void IVAS_TD_RINGBUF_PushZeros( return; } + /*---------------------------------------------------------------------* - * TD_RINGBUF_Pop() + * ivas_TD_RINGBUF_Pop() * * Pop samples from the front of the TD ring buffer. *---------------------------------------------------------------------*/ -void IVAS_TD_RINGBUF_Pop( + +void ivas_TD_RINGBUF_Pop( TD_RINGBUF_HANDLE h, /* i/o: Ring buffer handle */ float *data, /* i : Output data */ const uint32_t num_samples_per_channel /* i : Number of samples per channel to retrieve */ @@ -266,40 +273,47 @@ void IVAS_TD_RINGBUF_Pop( return; } + /*---------------------------------------------------------------------* - * TD_RINGBUF_IsEmpty() + * ivas_TD_RINGBUF_IsEmpty() * * Returns 1 if the ring buffer is empty, or 0 otherwise. *---------------------------------------------------------------------*/ -int16_t IVAS_TD_RINGBUF_IsEmpty( + +int16_t ivas_TD_RINGBUF_IsEmpty( const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ ) { return (int16_t) ( h->read_pos == h->write_pos && !h->is_full ); } + /*---------------------------------------------------------------------* - * TD_RINGBUF_Size() + * ivas_TD_RINGBUF_Size() * * Returns number of buffered samples per channel. *---------------------------------------------------------------------*/ -uint32_t IVAS_TD_RINGBUF_Size( + +uint32_t ivas_TD_RINGBUF_Size( const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ ) { return ivas_td_ringbuf_total_size( h ) / (uint32_t) h->num_channels; } + /*---------------------------------------------------------------------* - * TD_RINGBUF_Clear() + * ivas_TD_RINGBUF_Clear() * * Remove all samples from the buffer. *---------------------------------------------------------------------*/ -void IVAS_TD_RINGBUF_Clear( + +void ivas_TD_RINGBUF_Clear( TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ ) { h->read_pos = h->write_pos; h->is_full = 0; + return; } diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 5cc554bfc1..a0956b157f 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1348,9 +1348,7 @@ static ivas_error alignInputDelay( /* buffer has to accomodate maxGlobalDelaySamples + 2 * frameSize */ tmpSize = maxGlobalDelaySamples; tmpSize += 2 * inputAudio.config.numSamplesPerChannel; - if ( ( error = IVAS_TD_RINGBUF_Open( &inputBase->delayBuffer, - tmpSize, - inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_TD_RINGBUF_Open( &inputBase->delayBuffer, tmpSize, inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) { return error; } @@ -1358,8 +1356,7 @@ static ivas_error alignInputDelay( /* for the first frame we need to push zeros to align the input delay to the global delay * and then push a frame of actual data */ tmpSize = maxGlobalDelaySamples - inputBase->delayNumSamples * cldfb2tdSampleFact; - IVAS_TD_RINGBUF_PushZeros( inputBase->delayBuffer, - tmpSize ); + ivas_TD_RINGBUF_PushZeros( inputBase->delayBuffer, tmpSize ); /* for ISM inputs, ensure the metadata sync delay is updated */ if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) @@ -1370,12 +1367,8 @@ static ivas_error alignInputDelay( } /* push in the new input data and pop to retrieve a complete input frame */ - IVAS_TD_RINGBUF_Push( inputBase->delayBuffer, - inputAudio.data, - inputAudio.config.numSamplesPerChannel ); - IVAS_TD_RINGBUF_Pop( inputBase->delayBuffer, - inputBase->inputBuffer.data, - flushInputs ? IVAS_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); + ivas_TD_RINGBUF_Push( inputBase->delayBuffer, inputAudio.data, inputAudio.config.numSamplesPerChannel ); + ivas_TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, flushInputs ? ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); return IVAS_ERR_OK; } @@ -1543,7 +1536,7 @@ static void clearInputIsm( rendCtx = inputIsm->base.ctx; freeInputBaseBufferData( &inputIsm->base.inputBuffer.data ); - IVAS_TD_RINGBUF_Close( &inputIsm->base.delayBuffer ); + ivas_TD_RINGBUF_Close( &inputIsm->base.delayBuffer ); initRendInputBase( &inputIsm->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2542,7 +2535,7 @@ static void clearInputMc( freeMcLfeDelayBuffer( &inputMc->lfeDelayBuffer ); freeInputBaseBufferData( &inputMc->bufferData ); - IVAS_TD_RINGBUF_Close( &inputMc->base.delayBuffer ); + ivas_TD_RINGBUF_Close( &inputMc->base.delayBuffer ); initRendInputBase( &inputMc->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2874,7 +2867,7 @@ static void clearInputSba( rendCtx = inputSba->base.ctx; freeInputBaseBufferData( &inputSba->bufferData ); - IVAS_TD_RINGBUF_Close( &inputSba->base.delayBuffer ); + ivas_TD_RINGBUF_Close( &inputSba->base.delayBuffer ); initRendInputBase( &inputSba->base, IVAS_AUDIO_CONFIG_INVALID, 0, rendCtx, NULL, 0 ); @@ -2973,7 +2966,7 @@ static void clearInputMasa( rendCtx = inputMasa->base.ctx; freeInputBaseBufferData( &inputMasa->bufferData ); - IVAS_TD_RINGBUF_Close( &inputMasa->base.delayBuffer ); + ivas_TD_RINGBUF_Close( &inputMasa->base.delayBuffer ); masaPrerendClose( &inputMasa->hMasaPrerend ); freeMasaExtRenderer( &inputMasa->hMasaExtRend ); @@ -3661,7 +3654,6 @@ static ivas_error isar_pre_rend_init( } } - /* We may need to change the allocated buffer size if a new input is added. * If the cldfb_in_flag is different from what was previously allocated for the buffer, change the size */ if ( pSplitRendEncBuffer->data != NULL && ( cldfb_in_flag != pSplitRendEncBuffer->config.is_cldfb ) ) @@ -3789,7 +3781,6 @@ ivas_error IVAS_REND_AddInput( /* update global maximum delay after adding an input */ updateMaxGlobalDelayNs( hIvasRend ); - return IVAS_ERR_OK; } @@ -4522,6 +4513,7 @@ ivas_error IVAS_REND_FeedRenderConfig( if ( pMasaInput->hMasaExtRend->hDiracDecBin[0] != NULL && pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb != NULL ) { ivas_binaural_reverb_close( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb ); + if ( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hDiracDecBin[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, @@ -4539,6 +4531,7 @@ ivas_error IVAS_REND_FeedRenderConfig( if ( pMasaInput->hMasaExtRend->hReverb != NULL ) { ivas_binaural_reverb_close( &pMasaInput->hMasaExtRend->hReverb ); + if ( ( error = ivas_binaural_reverb_init( &pMasaInput->hMasaExtRend->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, pMasaInput->hMasaExtRend->hSpatParamRendCom->num_freq_bands, @@ -4571,6 +4564,7 @@ ivas_error IVAS_REND_FeedRenderConfig( return error; } } + if ( pMcInput->crendWrapper != NULL && pMcInput->crendWrapper->hCrend[0] && pMcInput->crendWrapper->hCrend[0]->hReverb != NULL ) { if ( ( error = ivas_reverb_open( &pMcInput->crendWrapper->hCrend[0]->hReverb, hIvasRend->hHrtfs.hHrtfStatistics, hRenderConfig, *pMcInput->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) @@ -4621,6 +4615,7 @@ ivas_error IVAS_REND_FeedRenderConfig( { int16_t cldfb_in_flag; cldfb_in_flag = getCldfbRendFlag( hIvasRend, IVAS_REND_AUDIO_CONFIG_TYPE_UNKNOWN ); + if ( hIvasRend->splitRendWrapper != NULL ) { ISAR_PRE_REND_close( hIvasRend->splitRendWrapper, &hIvasRend->splitRendEncBuffer ); @@ -7815,7 +7810,7 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( &bits, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, - ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), + (const int16_t) ( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, 1, cldfb_in_flag, -- GitLab From 5bf174aab1b94e5d5f81de9aba6b99e9f93a4d91 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Tue, 29 Jul 2025 09:55:26 +0200 Subject: [PATCH 34/49] [fix] delay for MASA and MASA prerendering --- lib_rend/lib_rend.c | 28 ++++++++-------------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index a0956b157f..a0a2d2e3ea 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1414,12 +1414,6 @@ static void setRendInputDelayIsm( latency_ns = max( latency_ns, inputIsm->crendWrapper->binaural_latency_ns ); } - if ( inputIsm->hOMasa != NULL ) - { - /* TODO tmu: verify what should be set for MASA prerendering */ - latency_ns = max( latency_ns, - (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); - } inputIsm->base.delayNumSamples = NS2SA( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); } @@ -2425,12 +2419,6 @@ static void setRendInputDelayMc( latency_ns = max( latency_ns, inputMc->crendWrapper->binaural_latency_ns ); } - if ( inputMc->hMcMasa != NULL ) - { - /* TODO tmu: verify what should be set for MASA prerendering */ - latency_ns = max( latency_ns, - (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); - } inputMc->base.delayNumSamples = NS2SA( *inputMc->base.ctx.pOutSampleRate, latency_ns ); } @@ -2794,12 +2782,6 @@ static void setRendInputDelaySba( latency_ns = max( latency_ns, inputSba->crendWrapper->binaural_latency_ns ); } - if ( inputSba->hDirAC != NULL ) - { - /* TODO tmu: verify what should be set for MASA prerendering */ - latency_ns = max( latency_ns, - (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); - } inputSba->base.delayNumSamples = NS2SA( *inputSba->base.ctx.pOutSampleRate, latency_ns ); } @@ -2895,8 +2877,14 @@ static void setRendInputDelayMasa( inputMasa = (input_masa *) input; /* set the rendering delay in InputBase */ - if ( inputMasa->hMasaExtRend != NULL && inputMasa->hMasaExtRend->renderer_type != RENDERER_DISABLE ) + if ( ( inputMasa->base.inConfig == IVAS_AUDIO_CONFIG_MASA1 && *inputMasa->base.ctx.pOutConfig == IVAS_AUDIO_CONFIG_MONO ) || + ( getAudioConfigType( *inputMasa->base.ctx.pOutConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) ) + { + return; /* no delay */ + } + else { + /* no delay applied for split rendering */ latency_ns = max( latency_ns, (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } @@ -7810,7 +7798,7 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( &bits, Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, - (const int16_t) ( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), + ( const int16_t )( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ), tmpBinaural, 1, cldfb_in_flag, -- GitLab From d0d086a09081356dd8c5c74aa96eab906541fd25 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Tue, 29 Jul 2025 10:48:21 +0200 Subject: [PATCH 35/49] silence unused parameter warning --- lib_rend/lib_rend.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index a0a2d2e3ea..4fbb3b4f90 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1405,6 +1405,7 @@ static void setRendInputDelayIsm( latency_ns = 0; inputIsm = (input_ism *) input; + (void) ( splitPreRendCldfb ); /* unused */ /* set the rendering delay in InputBase */ latency_ns = max( latency_ns, @@ -2407,6 +2408,7 @@ static void setRendInputDelayMc( { int32_t latency_ns; input_mc *inputMc; + (void) ( splitPreRendCldfb ); /* unused */ latency_ns = 0; inputMc = (input_mc *) input; -- GitLab From 0da9153cbce85aec210c5f9aee489795def9e03b Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Tue, 29 Jul 2025 18:38:20 +0200 Subject: [PATCH 36/49] [fix] accidental revert of change while reverting whitespace changes --- apps/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer.c b/apps/renderer.c index 8f699597aa..8d79ff7e08 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1395,7 +1395,7 @@ int main( goto cleanup; } - if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, args.outMetadataFilePath, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) + if ( ( error = split_rend_writer_open( &hSplitRendFileReadWrite, outFile, delayNumSamples_temp, delayTimeScale_temp, bitsBuffer.config.codec, bitsBuffer.config.poseCorrection, bitsBuffer.config.codec_frame_size_ms, bitsBuffer.config.isar_frame_size_ms, args.sampleRate, bitsBuffer.config.lc3plus_highres ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nCould not open split rend metadata file %s\n", outFile ); goto cleanup; -- GitLab From a264e336773af6b5bf477ddafd761800dca4964d Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Tue, 29 Jul 2025 18:41:33 +0200 Subject: [PATCH 37/49] [cleanup] remove unused functions --- lib_rend/ivas_prot_rend.h | 8 -------- lib_rend/ivas_td_ring_buffer.c | 31 ------------------------------- 2 files changed, 39 deletions(-) diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 6c1426ba5b..2268f62add 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -1613,18 +1613,10 @@ void ivas_TD_RINGBUF_Pop( const uint32_t num_samples_per_channel /* i : Number of samples per channel to retrieve*/ ); -int16_t ivas_TD_RINGBUF_IsEmpty( - const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ -); - uint32_t ivas_TD_RINGBUF_Size( const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ ); -void ivas_TD_RINGBUF_Clear( - TD_RINGBUF_HANDLE h /* i/o: Ring buffer handle */ -); - /* clang-format on */ #endif /* IVAS_PROT_REND_H */ diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c index b2a920f50f..5c9c6089bb 100644 --- a/lib_rend/ivas_td_ring_buffer.c +++ b/lib_rend/ivas_td_ring_buffer.c @@ -274,20 +274,6 @@ void ivas_TD_RINGBUF_Pop( } -/*---------------------------------------------------------------------* - * ivas_TD_RINGBUF_IsEmpty() - * - * Returns 1 if the ring buffer is empty, or 0 otherwise. - *---------------------------------------------------------------------*/ - -int16_t ivas_TD_RINGBUF_IsEmpty( - const TD_RINGBUF_HANDLE h /* i : Ring buffer handle */ -) -{ - return (int16_t) ( h->read_pos == h->write_pos && !h->is_full ); -} - - /*---------------------------------------------------------------------* * ivas_TD_RINGBUF_Size() * @@ -300,20 +286,3 @@ uint32_t ivas_TD_RINGBUF_Size( { return ivas_td_ringbuf_total_size( h ) / (uint32_t) h->num_channels; } - - -/*---------------------------------------------------------------------* - * ivas_TD_RINGBUF_Clear() - * - * Remove all samples from the buffer. - *---------------------------------------------------------------------*/ - -void ivas_TD_RINGBUF_Clear( - TD_RINGBUF_HANDLE h /* i/o: Ring buffer handle */ -) -{ - h->read_pos = h->write_pos; - h->is_full = 0; - - return; -} -- GitLab From cfa8c6f822d268167067dc9d10adf30a42ee1e1c Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 09:59:18 +0200 Subject: [PATCH 38/49] rework the push/pop of the renderer delay buffers to be clearer; don't push in new data while flushing inputs --- lib_rend/lib_rend.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index d3d53eaa9a..ef3d7f59f4 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1337,6 +1337,7 @@ static ivas_error alignInputDelay( ivas_error error; input_ism *inputIsm; int16_t maxGlobalDelaySamples; + int32_t numSamplesToPush, numSamplesToPop; uint32_t tmpSize; maxGlobalDelaySamples = NS2SA( sampleRateOut, maxGlobalDelayNs ); @@ -1366,9 +1367,13 @@ static ivas_error alignInputDelay( } } - /* push in the new input data and pop to retrieve a complete input frame */ - ivas_TD_RINGBUF_Push( inputBase->delayBuffer, inputAudio.data, inputAudio.config.numSamplesPerChannel ); - ivas_TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, flushInputs ? ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel ); + /* push in the new input data and pop to retrieve a complete input frame + * if we are flushing the inputs, we don't push in any new data */ + numSamplesToPush = flushInputs ? 0 : inputAudio.config.numSamplesPerChannel; + numSamplesToPop = flushInputs ? ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel; + + ivas_TD_RINGBUF_Push( inputBase->delayBuffer, inputAudio.data, numSamplesToPush ); + ivas_TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, numSamplesToPop ); return IVAS_ERR_OK; } -- GitLab From 1226b82b9319d9fbe8f40a07d173eb9cdac04c06 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 10:01:05 +0200 Subject: [PATCH 39/49] Revert "replace latencyNsToSamples with NS2SA" This reverts commit f4215bf1d140bdebe4597208f2d8fd4002bfef27. --- lib_rend/lib_rend.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index ef3d7f59f4..5c4fa1a445 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -267,6 +267,13 @@ static void freeInputBaseBufferData( return; } +static int16_t latencyNsToSamples( + int32_t sampleRate, + int32_t latency_ns ) +{ + return (int16_t) roundf( (float) ( latency_ns ) * ( sampleRate / 1000000000.f ) ); +} + static ivas_error allocateMcLfeDelayBuffer( float **lfeDelayBuffer, const int16_t data_size ) @@ -1340,7 +1347,7 @@ static ivas_error alignInputDelay( int32_t numSamplesToPush, numSamplesToPop; uint32_t tmpSize; - maxGlobalDelaySamples = NS2SA( sampleRateOut, maxGlobalDelayNs ); + maxGlobalDelaySamples = latencyNsToSamples( sampleRateOut, maxGlobalDelayNs ); maxGlobalDelaySamples *= cldfb2tdSampleFact; /* open the delay buffer if it isn't already */ @@ -1421,7 +1428,7 @@ static void setRendInputDelayIsm( inputIsm->crendWrapper->binaural_latency_ns ); } - inputIsm->base.delayNumSamples = NS2SA( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); + inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); } @@ -2427,7 +2434,7 @@ static void setRendInputDelayMc( inputMc->crendWrapper->binaural_latency_ns ); } - inputMc->base.delayNumSamples = NS2SA( *inputMc->base.ctx.pOutSampleRate, latency_ns ); + inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, latency_ns ); } static ivas_error setRendInputActiveMc( @@ -2790,7 +2797,7 @@ static void setRendInputDelaySba( inputSba->crendWrapper->binaural_latency_ns ); } - inputSba->base.delayNumSamples = NS2SA( *inputSba->base.ctx.pOutSampleRate, latency_ns ); + inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, latency_ns ); } static ivas_error setRendInputActiveSba( @@ -2896,7 +2903,7 @@ static void setRendInputDelayMasa( (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); } - inputMasa->base.delayNumSamples = NS2SA( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); + inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); } static ivas_error setRendInputActiveMasa( -- GitLab From d372d423e729421a633645d478c409f35e4e3a9c Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 10:32:53 +0200 Subject: [PATCH 40/49] cleanup/refactor delay computation functions into get/setInputDelay and use these in getMaxGlobalDelayNs --- lib_rend/lib_rend.c | 262 ++++++++++++++++++++++++-------------------- 1 file changed, 146 insertions(+), 116 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 5c4fa1a445..2ef4a2cbdf 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1267,6 +1267,141 @@ static bool isIoConfigPairSupported( } +static int32_t getRendInputDelayIsm( + const input_ism *inputIsm, + bool splitPreRendCldfb ) +{ + int32_t latency_ns; + latency_ns = 0; + (void) ( splitPreRendCldfb ); /* unused */ + + /* set the rendering delay in InputBase */ + latency_ns = max( latency_ns, + inputIsm->tdRendWrapper.binaural_latency_ns ); + if ( inputIsm->crendWrapper != NULL ) + { + latency_ns = max( latency_ns, + inputIsm->crendWrapper->binaural_latency_ns ); + } + + return latency_ns; +} + + +static void setRendInputDelayIsm( + void *input, + bool splitPreRendCldfb ) +{ + input_ism *inputIsm; + inputIsm = (input_ism *) input; + + inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, + getRendInputDelayIsm( inputIsm, splitPreRendCldfb ) ); +} + + +static int32_t getRendInputDelayMc( + const input_mc *inputMc, + bool splitPreRendCldfb ) +{ + int32_t latency_ns; + latency_ns = 0; + (void) ( splitPreRendCldfb ); /* unused */ + + latency_ns = max( latency_ns, + inputMc->tdRendWrapper.binaural_latency_ns ); + if ( inputMc->crendWrapper != NULL ) + { + latency_ns = max( latency_ns, + inputMc->crendWrapper->binaural_latency_ns ); + } + + return latency_ns; +} + + +static void setRendInputDelayMc( + void *input, + bool splitPreRendCldfb ) +{ + input_mc *inputMc; + inputMc = (input_mc *) input; + + inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, + getRendInputDelayMc( inputMc, splitPreRendCldfb ) ); +} + + +static int32_t getRendInputDelaySba( + const input_sba *inputSba, + bool splitPreRendCldfb ) +{ + int32_t latency_ns; + latency_ns = 0; + + if ( inputSba->cldfbRendWrapper.hCldfbRend != NULL ) + { + latency_ns = max( latency_ns, + inputSba->cldfbRendWrapper.binaural_latency_ns + + ( splitPreRendCldfb ? 0 : IVAS_FB_DEC_DELAY_NS ) ); + } + if ( inputSba->crendWrapper != NULL ) + { + latency_ns = max( latency_ns, + inputSba->crendWrapper->binaural_latency_ns ); + } + + return latency_ns; +} + + +static void setRendInputDelaySba( + void *input, + bool splitPreRendCldfb ) +{ + input_sba *inputSba; + inputSba = (input_sba *) input; + + inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, + getRendInputDelaySba( inputSba, splitPreRendCldfb ) ); +} + + +static int32_t getRendInputDelayMasa( + const input_masa *inputMasa, + bool splitPreRendCldfb ) +{ + int32_t latency_ns; + + latency_ns = 0; + + if ( ( inputMasa->base.inConfig == IVAS_AUDIO_CONFIG_MASA1 && *inputMasa->base.ctx.pOutConfig == IVAS_AUDIO_CONFIG_MONO ) || + ( getAudioConfigType( *inputMasa->base.ctx.pOutConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) ) + { + return 0; /* no delay */ + } + else + { + /* no delay applied for split rendering */ + latency_ns = max( latency_ns, + (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); + } + return latency_ns; +} + + +static void setRendInputDelayMasa( + void *input, + bool splitPreRendCldfb ) +{ + input_masa *inputMasa; + inputMasa = (input_masa *) input; + + inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, + getRendInputDelayMasa( inputMasa, splitPreRendCldfb ) ); +} + + static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { int16_t i; @@ -1282,8 +1417,7 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { if ( hIvasRend->inputsIsm[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { - latency_ns = max( ( hIvasRend->inputsIsm[i].crendWrapper != NULL ) ? hIvasRend->inputsIsm[i].crendWrapper->binaural_latency_ns : 0, - hIvasRend->inputsIsm[i].tdRendWrapper.binaural_latency_ns ); + latency_ns = getRendInputDelayIsm( &hIvasRend->inputsIsm[i], splitPreRendCldfb ); max_latency_ns = max( max_latency_ns, latency_ns ); } } @@ -1292,8 +1426,7 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { if ( hIvasRend->inputsMc[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { - latency_ns = max( ( hIvasRend->inputsMc[i].crendWrapper != NULL ) ? hIvasRend->inputsMc[i].crendWrapper->binaural_latency_ns : 0, - hIvasRend->inputsMc[i].tdRendWrapper.binaural_latency_ns ); + latency_ns = getRendInputDelayMc( &hIvasRend->inputsMc[i], splitPreRendCldfb ); max_latency_ns = max( max_latency_ns, latency_ns ); } } @@ -1302,17 +1435,8 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { if ( hIvasRend->inputsSba[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { - if ( hIvasRend->inputsSba[i].cldfbRendWrapper.hCldfbRend != NULL ) - { - latency_ns = hIvasRend->inputsSba[i].cldfbRendWrapper.binaural_latency_ns; - latency_ns += splitPreRendCldfb ? 0 : IVAS_FB_DEC_DELAY_NS; - max_latency_ns = max( max_latency_ns, latency_ns ); - } - else - { - latency_ns = ( hIvasRend->inputsSba[i].crendWrapper != NULL ) ? hIvasRend->inputsSba[i].crendWrapper->binaural_latency_ns : 0; - max_latency_ns = max( max_latency_ns, latency_ns ); - } + latency_ns = getRendInputDelaySba( &hIvasRend->inputsSba[i], splitPreRendCldfb ); + max_latency_ns = max( max_latency_ns, latency_ns ); } } @@ -1320,7 +1444,7 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) { if ( hIvasRend->inputsMasa[i].base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) { - latency_ns = splitPreRendCldfb ? 0 : (int32_t) ( (float) IVAS_FB_DEC_DELAY_NS + 0.5f ); + latency_ns = getRendInputDelayMasa( &hIvasRend->inputsMasa[i], splitPreRendCldfb ); max_latency_ns = max( max_latency_ns, latency_ns ); } } @@ -1328,7 +1452,8 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) return max_latency_ns; } -static void updateMaxGlobalDelayNs( IVAS_REND_HANDLE hIvasRend ) + +static void setMaxGlobalDelayNs( IVAS_REND_HANDLE hIvasRend ) { hIvasRend->maxGlobalDelayNs = getMaxGlobalDelayNs( (IVAS_REND_CONST_HANDLE) hIvasRend ); } @@ -1408,29 +1533,6 @@ static ivas_error initIsmMasaRendering( return IVAS_ERR_OK; } -static void setRendInputDelayIsm( - void *input, - bool splitPreRendCldfb ) -{ - int32_t latency_ns; - input_ism *inputIsm; - - latency_ns = 0; - inputIsm = (input_ism *) input; - (void) ( splitPreRendCldfb ); /* unused */ - - /* set the rendering delay in InputBase */ - latency_ns = max( latency_ns, - inputIsm->tdRendWrapper.binaural_latency_ns ); - if ( inputIsm->crendWrapper != NULL ) - { - latency_ns = max( latency_ns, - inputIsm->crendWrapper->binaural_latency_ns ); - } - - inputIsm->base.delayNumSamples = latencyNsToSamples( *inputIsm->base.ctx.pOutSampleRate, latency_ns ); -} - static ivas_error setRendInputActiveIsm( void *input, @@ -2414,28 +2516,6 @@ static lfe_routing defaultLfeRouting( return routing; } -static void setRendInputDelayMc( - void *input, - bool splitPreRendCldfb ) -{ - int32_t latency_ns; - input_mc *inputMc; - (void) ( splitPreRendCldfb ); /* unused */ - - latency_ns = 0; - inputMc = (input_mc *) input; - - /* set the rendering delay in InputBase */ - latency_ns = max( latency_ns, - inputMc->tdRendWrapper.binaural_latency_ns ); - if ( inputMc->crendWrapper != NULL ) - { - latency_ns = max( latency_ns, - inputMc->crendWrapper->binaural_latency_ns ); - } - - inputMc->base.delayNumSamples = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, latency_ns ); -} static ivas_error setRendInputActiveMc( void *input, @@ -2774,31 +2854,6 @@ static ivas_error initSbaMasaRendering( return IVAS_ERR_OK; } -static void setRendInputDelaySba( - void *input, - bool splitPreRendCldfb ) -{ - int32_t latency_ns; - input_sba *inputSba; - - latency_ns = 0; - inputSba = (input_sba *) input; - - /* set the rendering delay in InputBase */ - if ( inputSba->cldfbRendWrapper.hCldfbRend != NULL ) - { - latency_ns = max( latency_ns, - inputSba->cldfbRendWrapper.binaural_latency_ns + - ( splitPreRendCldfb ? 0 : IVAS_FB_DEC_DELAY_NS ) ); - } - if ( inputSba->crendWrapper != NULL ) - { - latency_ns = max( latency_ns, - inputSba->crendWrapper->binaural_latency_ns ); - } - - inputSba->base.delayNumSamples = latencyNsToSamples( *inputSba->base.ctx.pOutSampleRate, latency_ns ); -} static ivas_error setRendInputActiveSba( void *input, @@ -2880,31 +2935,6 @@ static void clearInputSba( return; } -static void setRendInputDelayMasa( - void *input, - bool splitPreRendCldfb ) -{ - int32_t latency_ns; - input_masa *inputMasa; - - latency_ns = 0; - inputMasa = (input_masa *) input; - - /* set the rendering delay in InputBase */ - if ( ( inputMasa->base.inConfig == IVAS_AUDIO_CONFIG_MASA1 && *inputMasa->base.ctx.pOutConfig == IVAS_AUDIO_CONFIG_MONO ) || - ( getAudioConfigType( *inputMasa->base.ctx.pOutConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_MASA ) ) - { - return; /* no delay */ - } - else - { - /* no delay applied for split rendering */ - latency_ns = max( latency_ns, - (int32_t) ( ( splitPreRendCldfb ? 0 : (float) IVAS_FB_DEC_DELAY_NS + 0.5f ) ) ); - } - - inputMasa->base.delayNumSamples = latencyNsToSamples( *inputMasa->base.ctx.pOutSampleRate, latency_ns ); -} static ivas_error setRendInputActiveMasa( void *input, @@ -3856,8 +3886,8 @@ ivas_error IVAS_REND_AddInput( setInputDelay( (uint8_t *) inputsArray + inputStructSize * inputIndex, splitPreRendCldfb ); #endif - /* update global maximum delay after adding an input */ - updateMaxGlobalDelayNs( hIvasRend ); + /* set global maximum delay after adding an input */ + setMaxGlobalDelayNs( hIvasRend ); return IVAS_ERR_OK; } @@ -4111,8 +4141,8 @@ ivas_error IVAS_REND_RemoveInput( return IVAS_ERR_INVALID_INPUT_FORMAT; } - /* update global maximum delay after removing an input */ - updateMaxGlobalDelayNs( hIvasRend ); + /* set global maximum delay after removing an input */ + setMaxGlobalDelayNs( hIvasRend ); return IVAS_ERR_OK; } -- GitLab From 5bac0898089afed35d37108d203c943b8b68a5e9 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 11:15:08 +0200 Subject: [PATCH 41/49] [fix] extra frame being written for split-pre rendering --- apps/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer.c b/apps/renderer.c index 8d79ff7e08..58d479a9b7 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1793,7 +1793,7 @@ int main( zeroPad = delayNumSamples; } - if ( is_split_pre_rend_mode( &args ) ) + if ( is_split_pre_rend_mode( &args ) && !flushRendererLastFrame ) { if ( split_rend_write_bitstream_to_file( hSplitRendFileReadWrite, bitsBuffer.bits, &bitsBuffer.config.bitsRead, &bitsBuffer.config.bitsWritten ) != IVAS_ERR_OK ) -- GitLab From 679e045c2cd704fc86a8c408270e5b94992166a8 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 11:39:11 +0200 Subject: [PATCH 42/49] [fix] extra frame written for MASA metadata --- apps/renderer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/renderer.c b/apps/renderer.c index 58d479a9b7..f3b3862650 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1824,7 +1824,7 @@ int main( bitsBuffer.config.bitsWritten = 0; /* Write MASA metadata for MASA outputs */ - if ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA1 || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) + if ( !flushRendererLastFrame && ( args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA1 || args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) ) { IVAS_REND_AudioConfigType inputType1; IVAS_REND_AudioConfigType inputType2; -- GitLab From ce28c8510e97cd1e4abc721c670e96d48a987748 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 12:48:08 +0200 Subject: [PATCH 43/49] [fix] missing set_zero for BINAURAL_SPLIT_PCM main head pose output --- lib_rend/lib_rend.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 2ef4a2cbdf..32ba183fd1 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -7933,6 +7933,8 @@ ivas_error IVAS_REND_GetSplitBinauralBitstream( /* copy over first pose data to outAudio */ if ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { + /* set outAudio to zero - getSamplesInternal only cleared splitRendEncBuffer */ + set_zero( outAudio.data, outAudio.config.numChannels * outAudio.config.numSamplesPerChannel ); accumulate2dArrayToBuffer( tmpBinaural_buff, &outAudio ); } -- GitLab From 1f51477b12d7eaa0416b6be6ed493b1fbc302ee8 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 12:49:23 +0200 Subject: [PATCH 44/49] [opt] only allocate the delay ring buffer if needed + fix typo --- lib_rend/lib_rend.c | 61 ++++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 32ba183fd1..95759f627e 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1470,42 +1470,57 @@ static ivas_error alignInputDelay( input_ism *inputIsm; int16_t maxGlobalDelaySamples; int32_t numSamplesToPush, numSamplesToPop; - uint32_t tmpSize; + uint32_t ringBufferSize, preDelay; maxGlobalDelaySamples = latencyNsToSamples( sampleRateOut, maxGlobalDelayNs ); maxGlobalDelaySamples *= cldfb2tdSampleFact; - /* open the delay buffer if it isn't already */ + /* check if we need to open the delay buffer */ if ( inputBase->delayBuffer == NULL ) { /* buffer has to accomodate maxGlobalDelaySamples + 2 * frameSize */ - tmpSize = maxGlobalDelaySamples; - tmpSize += 2 * inputAudio.config.numSamplesPerChannel; - if ( ( error = ivas_TD_RINGBUF_Open( &inputBase->delayBuffer, tmpSize, inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) - { - return error; - } + ringBufferSize = maxGlobalDelaySamples + 2 * inputAudio.config.numSamplesPerChannel; - /* for the first frame we need to push zeros to align the input delay to the global delay - * and then push a frame of actual data */ - tmpSize = maxGlobalDelaySamples - inputBase->delayNumSamples * cldfb2tdSampleFact; - ivas_TD_RINGBUF_PushZeros( inputBase->delayBuffer, tmpSize ); + /* pre delay for this input is maximum delay - input delay */ + preDelay = maxGlobalDelaySamples - inputBase->delayNumSamples * cldfb2tdSampleFact; - /* for ISM inputs, ensure the metadata sync delay is updated */ - if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) + if ( preDelay > 0 ) { - inputIsm = (input_ism *) inputBase; - inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs / 1e6f; + if ( ( error = ivas_TD_RINGBUF_Open( &inputBase->delayBuffer, ringBufferSize, inputAudio.config.numChannels ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* for the first frame we need to push zeros to align the input delay to the global delay + * and then push a frame of actual data */ + ivas_TD_RINGBUF_PushZeros( inputBase->delayBuffer, preDelay ); + + /* for ISM inputs, ensure the metadata sync delay is updated */ + if ( getAudioConfigType( inputBase->inConfig ) == IVAS_REND_AUDIO_CONFIG_TYPE_OBJECT_BASED ) + { + inputIsm = (input_ism *) inputBase; + inputIsm->ism_metadata_delay_ms = maxGlobalDelayNs / 1e6f; + } } } - /* push in the new input data and pop to retrieve a complete input frame - * if we are flushing the inputs, we don't push in any new data */ - numSamplesToPush = flushInputs ? 0 : inputAudio.config.numSamplesPerChannel; - numSamplesToPop = flushInputs ? ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel; + if ( inputBase->delayBuffer != NULL ) + { + /* push in the new input data and pop to retrieve a complete input frame + * if we are flushing the inputs, we don't push in any new data */ + numSamplesToPush = flushInputs ? 0 : inputAudio.config.numSamplesPerChannel; + numSamplesToPop = flushInputs ? ivas_TD_RINGBUF_Size( inputBase->delayBuffer ) : (uint32_t) inputAudio.config.numSamplesPerChannel; - ivas_TD_RINGBUF_Push( inputBase->delayBuffer, inputAudio.data, numSamplesToPush ); - ivas_TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, numSamplesToPop ); + ivas_TD_RINGBUF_Push( inputBase->delayBuffer, inputAudio.data, numSamplesToPush ); + ivas_TD_RINGBUF_Pop( inputBase->delayBuffer, inputBase->inputBuffer.data, numSamplesToPop ); + } + else + { + /* delay buffer isn't open - we don't need it */ + mvr2r( inputAudio.data, + inputBase->inputBuffer.data, + inputAudio.config.numSamplesPerChannel * inputAudio.config.numChannels ); + } return IVAS_ERR_OK; } @@ -3715,7 +3730,7 @@ static ivas_error isar_pre_rend_init( return IVAS_ERR_OK; } - /* these function should only be called once during initial allocation */ + /* these functions should only be called once during initial allocation */ if ( pSplitRendEncBuffer->data == NULL ) { if ( pSplit_rend_config->poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) -- GitLab From 558eada9fee7cee5b76a6c1e39903946d6705f01 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Thu, 31 Jul 2025 14:10:55 +0200 Subject: [PATCH 45/49] [fix] update condition for splitPreRendCldfb to check pose correction mode --- lib_rend/lib_rend.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 95759f627e..6c4d98e7f3 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1410,7 +1410,8 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) bool splitPreRendCldfb; max_latency_ns = 0; - splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ); + splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && + hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode != ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ); /* Compute the maximum delay across all inputs */ for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) @@ -3803,7 +3804,8 @@ ivas_error IVAS_REND_AddInput( void ( *setInputDelay )( void *, bool ); int32_t inputIndex; bool splitPreRendCldfb; - splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ); + splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && + hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode != ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ); /* Validate function arguments */ if ( hIvasRend == NULL || inputId == NULL ) -- GitLab From bd921fadc25d551b1db6a2f9681287a64aa2121b Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 4 Aug 2025 10:19:28 +0200 Subject: [PATCH 46/49] use latencyNsToSamples in IVAS_REND_GetDelay() and initMcBinauralRendering() --- lib_rend/lib_rend.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 6c4d98e7f3..237dc8f7a9 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -2433,7 +2433,7 @@ static ivas_error initMcBinauralRendering( /* determine binaural delay ( used for aligning LFE to output signal ) */ binauralDelayNs = max( ( inputMc->crendWrapper != NULL ) ? inputMc->crendWrapper->binaural_latency_ns : 0, inputMc->tdRendWrapper.binaural_latency_ns ); - inputMc->binauralDelaySmp = (int16_t) roundf( (float) binauralDelayNs * *inputMc->base.ctx.pOutSampleRate / 1000000000.f ); + inputMc->binauralDelaySmp = latencyNsToSamples( *inputMc->base.ctx.pOutSampleRate, binauralDelayNs ); if ( inputMc->binauralDelaySmp > MAX_BIN_DELAY_SAMPLES ) { @@ -4250,7 +4250,7 @@ ivas_error IVAS_REND_GetDelay( max_latency_ns = getMaxGlobalDelayNs( hIvasRend ); - *nSamples = (int16_t) roundf( (float) max_latency_ns * *timeScale / 1000000000.f ); + *nSamples = latencyNsToSamples( hIvasRend->sampleRateOut, max_latency_ns ); return IVAS_ERR_OK; } -- GitLab From efc7d2f09d75c78d4f1f5f262d0badf28b8f1eb3 Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 4 Aug 2025 10:28:54 +0200 Subject: [PATCH 47/49] set input buffer to zero when flushing last renderer frame --- apps/renderer.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/renderer.c b/apps/renderer.c index 36809390ae..ecb32c716b 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -1537,6 +1537,10 @@ int main( { convertInputBuffer( inpInt16Buffer, numSamplesRead, inBuffer.config.numSamplesPerChannel, num_in_channels, inFloatBuffer, inBuffer.config.is_cldfb, cldfbAna ); } + else + { + memset( inBuffer.data, 0, inBuffer.config.numChannels * inBuffer.config.numSamplesPerChannel * sizeof( float ) ); + } int16_t num_subframes, sf_idx; num_subframes = (int16_t) args.render_framesize; -- GitLab From 252f032d389e77008a8c1175b0a2aeef3886af3f Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 6 Aug 2025 11:12:32 +1000 Subject: [PATCH 48/49] potential fix for delay alignment in split rendering mode --- lib_rend/lib_rend.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 237dc8f7a9..7042efd459 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1410,8 +1410,8 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) bool splitPreRendCldfb; max_latency_ns = 0; - splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && - hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode != ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ); + /*assumes that input has been added which means codec has been set to either lcld or lc3plus (even if render config specified default)*/ + splitPreRendCldfb = ( hIvasRend->hRendererConfig->split_rend_config.codec == ISAR_SPLIT_REND_CODEC_LCLD ); /* Compute the maximum delay across all inputs */ for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) @@ -3804,8 +3804,6 @@ ivas_error IVAS_REND_AddInput( void ( *setInputDelay )( void *, bool ); int32_t inputIndex; bool splitPreRendCldfb; - splitPreRendCldfb = ( hIvasRend->outputConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && - hIvasRend->hRendererConfig->split_rend_config.poseCorrectionMode != ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE ); /* Validate function arguments */ if ( hIvasRend == NULL || inputId == NULL ) @@ -3831,6 +3829,9 @@ ivas_error IVAS_REND_AddInput( } } + /*assumes that input has been added which means codec has been set to either lcld or lc3plus (even if render config specified default)*/ + splitPreRendCldfb = ( hIvasRend->hRendererConfig->split_rend_config.codec == ISAR_SPLIT_REND_CODEC_LCLD ); + #ifdef CODE_IMPROVEMENTS inputType = getAudioConfigType( inConfig ); switch ( inputType ) -- GitLab From 6869f126cd254b166493844b8285edce266bf5f6 Mon Sep 17 00:00:00 2001 From: rtyag Date: Wed, 6 Aug 2025 11:44:06 +1000 Subject: [PATCH 49/49] fix crash for no split rend cases --- lib_rend/lib_rend.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 7042efd459..d95e8cdd7b 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1411,7 +1411,14 @@ static int32_t getMaxGlobalDelayNs( IVAS_REND_CONST_HANDLE hIvasRend ) max_latency_ns = 0; /*assumes that input has been added which means codec has been set to either lcld or lc3plus (even if render config specified default)*/ - splitPreRendCldfb = ( hIvasRend->hRendererConfig->split_rend_config.codec == ISAR_SPLIT_REND_CODEC_LCLD ); + if ( hIvasRend->hRendererConfig != NULL ) + { + splitPreRendCldfb = ( hIvasRend->hRendererConfig->split_rend_config.codec == ISAR_SPLIT_REND_CODEC_LCLD ); + } + else + { + splitPreRendCldfb = false; + } /* Compute the maximum delay across all inputs */ for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; i++ ) @@ -3804,6 +3811,7 @@ ivas_error IVAS_REND_AddInput( void ( *setInputDelay )( void *, bool ); int32_t inputIndex; bool splitPreRendCldfb; + splitPreRendCldfb = false; /* Validate function arguments */ if ( hIvasRend == NULL || inputId == NULL ) @@ -3827,10 +3835,11 @@ ivas_error IVAS_REND_AddInput( { return error; } + + /*assumes that input has been added which means codec has been set to either lcld or lc3plus (even if render config specified default)*/ + splitPreRendCldfb = ( hIvasRend->hRendererConfig->split_rend_config.codec == ISAR_SPLIT_REND_CODEC_LCLD ); } - /*assumes that input has been added which means codec has been set to either lcld or lc3plus (even if render config specified default)*/ - splitPreRendCldfb = ( hIvasRend->hRendererConfig->split_rend_config.codec == ISAR_SPLIT_REND_CODEC_LCLD ); #ifdef CODE_IMPROVEMENTS inputType = getAudioConfigType( inConfig ); -- GitLab