From 86a53981b8e69c17dd1328eb477e8a356f52efcd Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 20 Feb 2026 13:08:40 +0100 Subject: [PATCH 01/11] Fix indexing bug --- 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 0c5f595ac5..dcb2693185 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6139,7 +6139,7 @@ static ivas_error renderIsmToSplitBinaural( &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] ); + ismInput->base.ctx.pSplitRendWrapper->hCldfbHandles->cldfbAna[BINAURAL_CHANNELS * pos_idx + ch] ); } } } -- GitLab From cb742fd1445e09e4941aeee8f3fb9c1ebb03a582 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Mon, 23 Feb 2026 10:38:57 +0100 Subject: [PATCH 02/11] [WIP] do not reuse CLDFB handles for rendering different ISMs --- lib_rend/lib_rend.c | 102 ++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 27 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index dcb2693185..4750c8df8d 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6067,6 +6067,10 @@ static ivas_error renderIsmToSplitBinaural( push_wmops( "renderIsmToSplitBinaural" ); + assert( !outAudio.config.is_cldfb && + "ISM renderering only supports TD output. If CLDFB output was requested, " + "we convert to CLDFB higher up the stack after rendering all ISMs" ); + pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper; pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; @@ -6127,29 +6131,30 @@ static ivas_error renderIsmToSplitBinaural( return error; } - 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[BINAURAL_CHANNELS * pos_idx + ch] ); - } - } - } - else - { + // 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++ ) + // { + // fprintf( stderr, " channel %d, using CLDFB handle %d\n", ch, BINAURAL_CHANNELS * pos_idx + 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[BINAURAL_CHANNELS * 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 ); @@ -6161,14 +6166,14 @@ static ivas_error renderIsmToSplitBinaural( pCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; } - if ( outAudio.config.is_cldfb ) - { - accumulateCLDFBArrayToBuffer( tmpBinaural_CldfbRe, tmpBinaural_CldfbIm, &outAudio ); - } - else - { + // 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 */ @@ -6275,6 +6280,18 @@ static ivas_error renderActiveInputsIsm( int16_t i; input_ism *pCurrentInput; ivas_error error; + IVAS_REND_AudioBuffer tmp_td_audio_buf; + float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; + + // ISM renderering only supports TD output. If CLDFB output was requested, we first render + // to TD in a tmp buffer and then convert to CLDFB. + if ( outAudio.config.is_cldfb ) + { + tmp_td_audio_buf.config = outAudio.config; + tmp_td_audio_buf.config.numSamplesPerChannel /= 2; + tmp_td_audio_buf.config.is_cldfb = false; + tmp_td_audio_buf.data = tmpBinaural; + } for ( i = 0, pCurrentInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pCurrentInput ) { @@ -6284,12 +6301,43 @@ static ivas_error renderActiveInputsIsm( continue; } - if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) + if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio.config.is_cldfb ? tmp_td_audio_buf : outAudio ) ) != IVAS_ERR_OK ) { return error; } } + if ( outAudio.config.is_cldfb ) + { + // TODO: move up + int16_t ch, slot_idx; + float* td_read_ptr = tmp_td_audio_buf.data; + float* cldfb_write_ptr = outAudio.data; + int16_t slot_len = 60; // TODO: compute? + + for ( ch = 0; ch < outAudio.config.numChannels; ++ch ) + { + for ( slot_idx = 0; slot_idx < IVAS_CLDFB_NO_COL_MAX; ++slot_idx ) + { + float re[CLDFB_NO_CHANNELS_MAX]; + float im[CLDFB_NO_CHANNELS_MAX]; + + cldfbAnalysis_ts( td_read_ptr, + re, + im, + slot_len, + hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna[ch] ); + + td_read_ptr += slot_len; + + v_add( re, cldfb_write_ptr, cldfb_write_ptr, slot_len ); + cldfb_write_ptr += slot_len; + v_add( im, cldfb_write_ptr, cldfb_write_ptr, slot_len ); + cldfb_write_ptr += slot_len; + } + } + } + return IVAS_ERR_OK; } -- GitLab From ba11fad682baa7f78fa7dc27d5428baeb19129af Mon Sep 17 00:00:00 2001 From: Archit Tamarapu Date: Mon, 23 Feb 2026 11:41:21 +0100 Subject: [PATCH 03/11] [fix] missing set_zero and introduce FIX_BASOP_2283_OMASA_SR --- lib_com/options.h | 1 + lib_rend/lib_rend.c | 94 +++++++++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 38 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 1cfb4c9f24..abb04562b8 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -171,6 +171,7 @@ /* any switch which is non-be wrt. TS 26.258 V3.0 */ #define FIX_2432_ISM_SPIKES_16KHZ /* VA: basop issue 2432: fix spikes in ISM decoding at 16kHz output sampling rate */ +#define FIX_BASOP_2283_OMASA_SR /* FhG: basop issue 2283: fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 4750c8df8d..6647e6788a 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6067,9 +6067,11 @@ static ivas_error renderIsmToSplitBinaural( push_wmops( "renderIsmToSplitBinaural" ); +#ifdef FIX_BASOP_2283_OMASA_SR assert( !outAudio.config.is_cldfb && - "ISM renderering only supports TD output. If CLDFB output was requested, " - "we convert to CLDFB higher up the stack after rendering all ISMs" ); + "ISM renderering only supports TD output. If CLDFB output was requested, " + "we convert to CLDFB higher up the stack after rendering all ISMs" ); +#endif pSplitRendWrapper = ismInput->base.ctx.pSplitRendWrapper; pMultiBinPoseData = &pSplitRendWrapper->multiBinPoseData; @@ -6131,30 +6133,33 @@ static ivas_error renderIsmToSplitBinaural( return error; } - // 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++ ) - // { - // fprintf( stderr, " channel %d, using CLDFB handle %d\n", ch, BINAURAL_CHANNELS * pos_idx + 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[BINAURAL_CHANNELS * pos_idx + ch] ); - // } - // } - // } - // else - // { +#ifndef FIX_BASOP_2283_OMASA_SR + 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 + { +#endif /* 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 ); - // } +#ifndef FIX_BASOP_2283_OMASA_SR + } +#endif /* Overwrite processing buffer with original input audio again */ copyBufferTo2dArray( ismInput->base.inputBuffer, tmpProcessing ); @@ -6166,14 +6171,18 @@ static ivas_error renderIsmToSplitBinaural( pCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; } - // if ( outAudio.config.is_cldfb ) - // { - // accumulateCLDFBArrayToBuffer( tmpBinaural_CldfbRe, tmpBinaural_CldfbIm, &outAudio ); - // } - // else - // { +#ifndef FIX_BASOP_2283_OMASA_SR + if ( outAudio.config.is_cldfb ) + { + accumulateCLDFBArrayToBuffer( tmpBinaural_CldfbRe, tmpBinaural_CldfbIm, &outAudio ); + } + else + { +#endif accumulate2dArrayToBuffer( tmpBinaural, &outAudio ); - // } +#ifndef FIX_BASOP_2283_OMASA_SR + } +#endif pop_wmops(); /* Encoding to split rendering bitstream done at a higher level */ @@ -6280,6 +6289,7 @@ static ivas_error renderActiveInputsIsm( int16_t i; input_ism *pCurrentInput; ivas_error error; +#ifdef FIX_BASOP_2283_OMASA_SR IVAS_REND_AudioBuffer tmp_td_audio_buf; float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; @@ -6291,7 +6301,9 @@ static ivas_error renderActiveInputsIsm( tmp_td_audio_buf.config.numSamplesPerChannel /= 2; tmp_td_audio_buf.config.is_cldfb = false; tmp_td_audio_buf.data = tmpBinaural; + set_zero( tmpBinaural, MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k ); } +#endif for ( i = 0, pCurrentInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pCurrentInput ) { @@ -6301,19 +6313,24 @@ static ivas_error renderActiveInputsIsm( continue; } +#ifdef FIX_BASOP_2283_OMASA_SR if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio.config.is_cldfb ? tmp_td_audio_buf : outAudio ) ) != IVAS_ERR_OK ) +#else + if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) +#endif { return error; } } +#ifdef FIX_BASOP_2283_OMASA_SR if ( outAudio.config.is_cldfb ) { // TODO: move up int16_t ch, slot_idx; - float* td_read_ptr = tmp_td_audio_buf.data; - float* cldfb_write_ptr = outAudio.data; - int16_t slot_len = 60; // TODO: compute? + float *td_read_ptr = tmp_td_audio_buf.data; + float *cldfb_write_ptr = outAudio.data; + int16_t num_bands = (int16_t) ( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ); for ( ch = 0; ch < outAudio.config.numChannels; ++ch ) { @@ -6325,18 +6342,19 @@ static ivas_error renderActiveInputsIsm( cldfbAnalysis_ts( td_read_ptr, re, im, - slot_len, + num_bands, hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna[ch] ); - td_read_ptr += slot_len; + td_read_ptr += CLDFB_NO_CHANNELS_MAX; - v_add( re, cldfb_write_ptr, cldfb_write_ptr, slot_len ); - cldfb_write_ptr += slot_len; - v_add( im, cldfb_write_ptr, cldfb_write_ptr, slot_len ); - cldfb_write_ptr += slot_len; + v_add( re, cldfb_write_ptr, cldfb_write_ptr, num_bands ); + cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; + v_add( im, cldfb_write_ptr, cldfb_write_ptr, num_bands ); + cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; } } } +#endif return IVAS_ERR_OK; } -- GitLab From bf5bf1059fbaed4e49bdc25916b6adf1d1bc69e0 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 11:38:27 +0100 Subject: [PATCH 04/11] Refactor CLDFB analysis on audio buffers into a helper function --- lib_rend/lib_rend.c | 94 +++++++++++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 28 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 6647e6788a..3c215e0cb6 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -454,6 +454,65 @@ static void accumulate2dArrayToBuffer( return; } + +#ifdef FIX_BASOP_2283_OMASA_SR +/*-------------------------------------------------------------------* + * audio_buffer_td_to_cldfb() + * + * Performs CLDFB analysis on contents of td_buffer and mixes the result into cldfb_buffer. + * + * This function **does not** clear the destination buffer before writing. + * + * The number of valid CLDFB handles in cldfbAna must be a least equal to the number of channels + * in the audio buffers. + *-------------------------------------------------------------------*/ +static void audio_buffer_td_to_cldfb( + IVAS_REND_AudioBuffer td_buffer, + IVAS_REND_AudioBuffer cldfb_buffer, + int32_t fs, + HANDLE_CLDFB_FILTER_BANK* cldfbAna +) +{ + int16_t ch, slot_idx; + float *td_read_ptr; + float *cldfb_write_ptr; + int16_t num_bands; + + assert( !td_buffer.config.is_cldfb ); + assert( cldfb_buffer.config.is_cldfb ); + + assert( td_buffer.config.numChannels == cldfb_buffer.config.numChannels ); + assert( td_buffer.config.numSamplesPerChannel == cldfb_buffer.config.numSamplesPerChannel * 2 ); + + td_read_ptr = td_buffer.data; + cldfb_write_ptr = cldfb_buffer.data; + num_bands = (int16_t) ( ( BINAURAL_MAXBANDS * fs ) / 48000 ); + + for ( ch = 0; ch < cldfb_buffer.config.numChannels; ++ch ) + { + for ( slot_idx = 0; slot_idx < IVAS_CLDFB_NO_COL_MAX; ++slot_idx ) + { + float re[CLDFB_NO_CHANNELS_MAX]; + float im[CLDFB_NO_CHANNELS_MAX]; + + cldfbAnalysis_ts( td_read_ptr, + re, + im, + num_bands, + cldfbAna[ch] ); + + td_read_ptr += CLDFB_NO_CHANNELS_MAX; + + v_add( re, cldfb_write_ptr, cldfb_write_ptr, num_bands ); + cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; + v_add( im, cldfb_write_ptr, cldfb_write_ptr, num_bands ); + cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; + } + } +} +#endif + + /*-------------------------------------------------------------------* * limitRendererOutput() * @@ -6314,7 +6373,9 @@ static ivas_error renderActiveInputsIsm( } #ifdef FIX_BASOP_2283_OMASA_SR - if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio.config.is_cldfb ? tmp_td_audio_buf : outAudio ) ) != IVAS_ERR_OK ) + if ( ( error = renderInputIsm( pCurrentInput, + hIvasRend->outputConfig, + outAudio.config.is_cldfb ? tmp_td_audio_buf : outAudio ) ) != IVAS_ERR_OK ) #else if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) #endif @@ -6326,33 +6387,10 @@ static ivas_error renderActiveInputsIsm( #ifdef FIX_BASOP_2283_OMASA_SR if ( outAudio.config.is_cldfb ) { - // TODO: move up - int16_t ch, slot_idx; - float *td_read_ptr = tmp_td_audio_buf.data; - float *cldfb_write_ptr = outAudio.data; - int16_t num_bands = (int16_t) ( ( BINAURAL_MAXBANDS * hIvasRend->sampleRateOut ) / 48000 ); - - for ( ch = 0; ch < outAudio.config.numChannels; ++ch ) - { - for ( slot_idx = 0; slot_idx < IVAS_CLDFB_NO_COL_MAX; ++slot_idx ) - { - float re[CLDFB_NO_CHANNELS_MAX]; - float im[CLDFB_NO_CHANNELS_MAX]; - - cldfbAnalysis_ts( td_read_ptr, - re, - im, - num_bands, - hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna[ch] ); - - td_read_ptr += CLDFB_NO_CHANNELS_MAX; - - v_add( re, cldfb_write_ptr, cldfb_write_ptr, num_bands ); - cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; - v_add( im, cldfb_write_ptr, cldfb_write_ptr, num_bands ); - cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; - } - } + audio_buffer_td_to_cldfb( tmp_td_audio_buf, + outAudio, + hIvasRend->sampleRateOut, + hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna ); } #endif -- GitLab From 432faa6ba63e75f87ce0930b4badcc74c5afdd91 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 11:41:54 +0100 Subject: [PATCH 05/11] Rename preprocessor define --- lib_com/options.h | 2 +- lib_rend/lib_rend.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index abb04562b8..a98c35bec4 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -171,7 +171,7 @@ /* any switch which is non-be wrt. TS 26.258 V3.0 */ #define FIX_2432_ISM_SPIKES_16KHZ /* VA: basop issue 2432: fix spikes in ISM decoding at 16kHz output sampling rate */ -#define FIX_BASOP_2283_OMASA_SR /* FhG: basop issue 2283: fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ +#define FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /* FhG: basop issue 2436 (related to 2283): fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 3c215e0cb6..707086fd7d 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -455,7 +455,7 @@ static void accumulate2dArrayToBuffer( } -#ifdef FIX_BASOP_2283_OMASA_SR +#ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /*-------------------------------------------------------------------* * audio_buffer_td_to_cldfb() * @@ -6126,7 +6126,7 @@ static ivas_error renderIsmToSplitBinaural( push_wmops( "renderIsmToSplitBinaural" ); -#ifdef FIX_BASOP_2283_OMASA_SR +#ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR assert( !outAudio.config.is_cldfb && "ISM renderering only supports TD output. If CLDFB output was requested, " "we convert to CLDFB higher up the stack after rendering all ISMs" ); @@ -6192,7 +6192,7 @@ static ivas_error renderIsmToSplitBinaural( return error; } -#ifndef FIX_BASOP_2283_OMASA_SR +#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { /* Perform CLDFB analysis on rendered audio, since the output buffer is CLDFB domain */ @@ -6216,7 +6216,7 @@ static ivas_error renderIsmToSplitBinaural( * 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 ); -#ifndef FIX_BASOP_2283_OMASA_SR +#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR } #endif @@ -6230,7 +6230,7 @@ static ivas_error renderIsmToSplitBinaural( pCombinedOrientationData->Quaternions[i] = originalHeadRot[i]; } -#ifndef FIX_BASOP_2283_OMASA_SR +#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { accumulateCLDFBArrayToBuffer( tmpBinaural_CldfbRe, tmpBinaural_CldfbIm, &outAudio ); @@ -6239,7 +6239,7 @@ static ivas_error renderIsmToSplitBinaural( { #endif accumulate2dArrayToBuffer( tmpBinaural, &outAudio ); -#ifndef FIX_BASOP_2283_OMASA_SR +#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR } #endif pop_wmops(); @@ -6348,7 +6348,7 @@ static ivas_error renderActiveInputsIsm( int16_t i; input_ism *pCurrentInput; ivas_error error; -#ifdef FIX_BASOP_2283_OMASA_SR +#ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR IVAS_REND_AudioBuffer tmp_td_audio_buf; float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; @@ -6372,7 +6372,7 @@ static ivas_error renderActiveInputsIsm( continue; } -#ifdef FIX_BASOP_2283_OMASA_SR +#ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio.config.is_cldfb ? tmp_td_audio_buf : outAudio ) ) != IVAS_ERR_OK ) @@ -6384,7 +6384,7 @@ static ivas_error renderActiveInputsIsm( } } -#ifdef FIX_BASOP_2283_OMASA_SR +#ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { audio_buffer_td_to_cldfb( tmp_td_audio_buf, -- GitLab From ce95387eefd08a5b71ea50634f3624f6c0bb09f6 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 11:43:32 +0100 Subject: [PATCH 06/11] Remove unused variables --- lib_rend/lib_rend.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 707086fd7d..992c0ba3d3 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6116,10 +6116,13 @@ 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, ch, slot_idx, num_bands; + int16_t i; float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][L_FRAME48k]; +#ifndef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR + int16_t ch, slot_idx, num_bands; 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]; +#endif int16_t output_frame = ismInput->base.inputBuffer.config.numSamplesPerChannel; COMBINED_ORIENTATION_HANDLE pCombinedOrientationData; int16_t ism_md_subframe_update_ext; -- GitLab From e7abdf52758e4a3f6813c0564ea5c9862413efef Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 11:51:54 +0100 Subject: [PATCH 07/11] Fix assert check --- 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 992c0ba3d3..534f7a68e0 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -482,7 +482,7 @@ static void audio_buffer_td_to_cldfb( assert( cldfb_buffer.config.is_cldfb ); assert( td_buffer.config.numChannels == cldfb_buffer.config.numChannels ); - assert( td_buffer.config.numSamplesPerChannel == cldfb_buffer.config.numSamplesPerChannel * 2 ); + assert( td_buffer.config.numSamplesPerChannel * 2 == cldfb_buffer.config.numSamplesPerChannel ); td_read_ptr = td_buffer.data; cldfb_write_ptr = cldfb_buffer.data; -- GitLab From 6c616034b62b93925d0e8ec38338c3de86e7cac1 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 12:30:01 +0100 Subject: [PATCH 08/11] Fix formatting --- lib_com/options.h | 2 +- lib_rend/lib_rend.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index a98c35bec4..f23737ba9a 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -171,7 +171,7 @@ /* any switch which is non-be wrt. TS 26.258 V3.0 */ #define FIX_2432_ISM_SPIKES_16KHZ /* VA: basop issue 2432: fix spikes in ISM decoding at 16kHz output sampling rate */ -#define FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /* FhG: basop issue 2436 (related to 2283): fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ +#define FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR /* FhG: basop issue 2436 (related to basop 2283): fix garbage output for >1 object OMASA with extrend as ISAR prerenderer */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 534f7a68e0..1b72750f41 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -470,8 +470,7 @@ static void audio_buffer_td_to_cldfb( IVAS_REND_AudioBuffer td_buffer, IVAS_REND_AudioBuffer cldfb_buffer, int32_t fs, - HANDLE_CLDFB_FILTER_BANK* cldfbAna -) + HANDLE_CLDFB_FILTER_BANK *cldfbAna ) { int16_t ch, slot_idx; float *td_read_ptr; -- GitLab From c9d35820a3a750cbf3beb31c38d23288e99a1b45 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 14:22:39 +0100 Subject: [PATCH 09/11] Try to fix MSVC's false-positive warning and WMC tool causing build problems --- lib_rend/lib_rend.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 63df40fde6..ceb667ec3f 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6357,18 +6357,24 @@ static ivas_error renderActiveInputsIsm( input_ism *pCurrentInput; ivas_error error; #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR - IVAS_REND_AudioBuffer tmp_td_audio_buf; - float tmpBinaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; - - // ISM renderering only supports TD output. If CLDFB output was requested, we first render - // to TD in a tmp buffer and then convert to CLDFB. + IVAS_REND_AudioBuffer work_buffer; + float tmp_td_binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; + + // By default (TD output), use outAudio as work_buffer. This means we render individual ISMs + // directly to outAudio, since the `data` member of both these structs is pointing to the same memory. + // Initializing this way also fixes MSVC's false-positive warning about work_buffer being used + // without initialization in code below, as well as some WMC tool instrumentation problems. + work_buffer = outAudio; + + // ISM rendering only supports TD output. If CLDFB output was requested, we first render + // to TD in a temporary buffer and then convert to CLDFB. We do this by swapping out the + // underlying memory of work_buffer and modifying its config to TD. if ( outAudio.config.is_cldfb ) { - tmp_td_audio_buf.config = outAudio.config; - tmp_td_audio_buf.config.numSamplesPerChannel /= 2; - tmp_td_audio_buf.config.is_cldfb = false; - tmp_td_audio_buf.data = tmpBinaural; - set_zero( tmpBinaural, MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k ); + work_buffer.config.numSamplesPerChannel /= 2; + work_buffer.config.is_cldfb = false; + work_buffer.data = tmp_td_binaural; + set_zero( tmp_td_binaural, MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k ); } #endif @@ -6383,7 +6389,7 @@ static ivas_error renderActiveInputsIsm( #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, - outAudio.config.is_cldfb ? tmp_td_audio_buf : outAudio ) ) != IVAS_ERR_OK ) + work_buffer ) ) != IVAS_ERR_OK ) #else if ( ( error = renderInputIsm( pCurrentInput, hIvasRend->outputConfig, outAudio ) ) != IVAS_ERR_OK ) #endif @@ -6395,7 +6401,7 @@ static ivas_error renderActiveInputsIsm( #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR if ( outAudio.config.is_cldfb ) { - audio_buffer_td_to_cldfb( tmp_td_audio_buf, + audio_buffer_td_to_cldfb( work_buffer, outAudio, hIvasRend->sampleRateOut, hIvasRend->splitRendWrapper->hCldfbHandles->cldfbAna ); -- GitLab From d6b5a1d4a88db69dbbaf16728edb099d17deea69 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 14:41:42 +0100 Subject: [PATCH 10/11] Do not try to render ISMs if there are none to render --- lib_rend/lib_rend.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index ceb667ec3f..5ac7347b42 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -6357,9 +6357,24 @@ static ivas_error renderActiveInputsIsm( input_ism *pCurrentInput; ivas_error error; #ifdef FIX_BASOP_2436_REUSED_CLDFB_IN_OMASA_SR + int16_t num_active_inputs; IVAS_REND_AudioBuffer work_buffer; float tmp_td_binaural[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS * L_FRAME48k]; + // Early return in case there are no active ISM inputs + num_active_inputs = 0; + for ( i = 0, pCurrentInput = hIvasRend->inputsIsm; i < RENDERER_MAX_ISM_INPUTS; ++i, ++pCurrentInput ) + { + if ( pCurrentInput->base.inConfig != IVAS_AUDIO_CONFIG_INVALID ) + { + ++num_active_inputs; + } + } + if ( num_active_inputs == 0 ) + { + return IVAS_ERR_OK; + } + // By default (TD output), use outAudio as work_buffer. This means we render individual ISMs // directly to outAudio, since the `data` member of both these structs is pointing to the same memory. // Initializing this way also fixes MSVC's false-positive warning about work_buffer being used -- GitLab From 3e444092757f518ee1e752fc0f2c22474f00a308 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Thu, 26 Feb 2026 15:26:05 +0100 Subject: [PATCH 11/11] Do not hardcode frame size in audio_buffer_td_to_cldfb --- lib_rend/lib_rend.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 5ac7347b42..d31a2cd795 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -475,7 +475,7 @@ static void audio_buffer_td_to_cldfb( int16_t ch, slot_idx; float *td_read_ptr; float *cldfb_write_ptr; - int16_t num_bands; + int16_t num_bands, num_slots; assert( !td_buffer.config.is_cldfb ); assert( cldfb_buffer.config.is_cldfb ); @@ -485,11 +485,13 @@ static void audio_buffer_td_to_cldfb( td_read_ptr = td_buffer.data; cldfb_write_ptr = cldfb_buffer.data; - num_bands = (int16_t) ( ( BINAURAL_MAXBANDS * fs ) / 48000 ); + num_bands = (int16_t) ( ( CLDFB_NO_CHANNELS_MAX * fs ) / 48000 ); + assert( td_buffer.config.numSamplesPerChannel % num_bands == 0 ); + num_slots = td_buffer.config.numSamplesPerChannel / num_bands; for ( ch = 0; ch < cldfb_buffer.config.numChannels; ++ch ) { - for ( slot_idx = 0; slot_idx < IVAS_CLDFB_NO_COL_MAX; ++slot_idx ) + for ( slot_idx = 0; slot_idx < num_slots; ++slot_idx ) { float re[CLDFB_NO_CHANNELS_MAX]; float im[CLDFB_NO_CHANNELS_MAX]; @@ -500,12 +502,12 @@ static void audio_buffer_td_to_cldfb( num_bands, cldfbAna[ch] ); - td_read_ptr += CLDFB_NO_CHANNELS_MAX; + td_read_ptr += num_bands; v_add( re, cldfb_write_ptr, cldfb_write_ptr, num_bands ); - cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; + cldfb_write_ptr += num_bands; v_add( im, cldfb_write_ptr, cldfb_write_ptr, num_bands ); - cldfb_write_ptr += CLDFB_NO_CHANNELS_MAX; + cldfb_write_ptr += num_bands; } } } -- GitLab