From 9ecd5e2171c449ff7c52e879d1eed7f29508bc2a Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 26 May 2026 11:21:01 +0200 Subject: [PATCH 1/8] proper flushing of SR audio data --- apps/decoder.c | 27 ++++++++++++++++++------ lib_com/options.h | 3 ++- lib_dec/lib_dec.c | 53 +++++++++++++++++++++++++++++++++++++++++------ lib_dec/lib_dec.h | 3 +++ 4 files changed, 73 insertions(+), 13 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index 6edb2e1ea..80a0e7d6b 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -2917,18 +2917,29 @@ static ivas_error decodeG192( } /* flush remaining audio */ - if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + splitRendBits, +#endif + &nSamplesFlushed ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; } - /* Write current frame */ - if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, nSamplesFlushed * nOutChannels ) ) != IVAS_ERR_OK ) +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + if ( !isSplitCoded ) { - fprintf( stderr, "\nOutput audio file writer error\n" ); - goto cleanup; +#endif + /* Write current frame */ + if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, nSamplesFlushed * nOutChannels ) ) != IVAS_ERR_OK ) + { + fprintf( stderr, "\nOutput audio file writer error\n" ); + goto cleanup; + } +#ifdef FIX_1342_PROPER_FLUSH_IN_SR } +#endif /* Write ISM metadata to external file(s) */ if ( decodedGoodFrame && arg.outputConfig == IVAS_AUDIO_CONFIG_EXTERNAL ) @@ -3846,7 +3857,11 @@ static ivas_error decodeVoIP( int16_t nSamplesFlushed = 0; /* flush remaining audio */ - if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + splitRendBits, +#endif + &nSamplesFlushed ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; diff --git a/lib_com/options.h b/lib_com/options.h index 5c079fce2..b29eb62c5 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -159,7 +159,8 @@ /* only BE switches wrt wrt. TS 26.258 V3.0 */ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ -#define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering */ +/*#define TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR*/ /* FhG: Temporary workaround for incorrect implementation of decoder flush with split rendering; disabled, superseded by FIX_1342_PROPER_FLUSH_IN_SR */ +#define FIX_1342_PROPER_FLUSH_IN_SR /* FhG: Proper implementation of decoder flush with split rendering, using isar_render_poses + isar_generate_metadata_and_bitstream */ #define NONBE_1122_KEEP_EVS_MODE_UNCHANGED /* FhG: Disables fix for issue 1122 in EVS mode to keep BE tests green. This switch should be removed once the 1122 fix is added to EVS via a CR. */ #define FIX_FLOAT_1539_G192_FORMAT_SWITCH /* Nokia: reintroduce format switching for g192 bitstreams */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 7199ae4e6..e7d484a22 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4311,11 +4311,14 @@ static void update_voip_rendered20ms( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_Flush( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ - const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ - void *pcmBuf, /* o : output synthesis signal */ - int16_t *nSamplesFlushed /* o : number of samples flushed */ + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ + const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ + void *pcmBuf, /* o : output synthesis signal */ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits; NULL when not applicable */ +#endif + int16_t *nSamplesFlushed /* o : number of samples flushed */ ) { ivas_error error; @@ -4339,7 +4342,45 @@ ivas_error IVAS_DEC_Flush( error = IVAS_ERR_OK; if ( nSamplesToRender > 0 && hIvasDec->st_ivas->ivas_format != MONO_FORMAT ) { - error = ivas_dec_render( hIvasDec->st_ivas, nSamplesToRender, &nSamplesFlushedLocal, &hIvasDec->nSamplesAvailableNext, pcm_type_API_to_internal( pcmType ), pcmBuf ); +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + if ( is_split_rendering_enabled( hIvasDec->st_ivas->hDecoderConfig, hIvasDec->st_ivas->hRenderConfig ) ) + { + int16_t i, nOutSamples = 0; + bool needNewFrame; + const int16_t splitFrameSize = isar_get_frame_size( hIvasDec->st_ivas ); + float head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; + float *p_head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + + for ( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) + { + p_head_pose_buf[i] = head_pose_buf[i]; + } + + /* Render remaining buffered audio into the SR ring buffers using the + correctly-sized internal float buffer to avoid writing beyond the end of the pcmBuf */ + if ( ( error = isar_render_poses( hIvasDec, splitFrameSize, &nOutSamples, &needNewFrame ) ) != IVAS_ERR_OK ) + { + return error; + } + + *nSamplesFlushed = nOutSamples; + + /* Flush the remaing audio output in SR mode. Metadata generation is handled during normal decoding */ + if ( hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec( hIvasDec->st_ivas->hLimiter, p_head_pose_buf, hIvasDec->st_ivas->hDecoderConfig->nchan_out, nOutSamples, hIvasDec->st_ivas->BER_detect ); +#endif + ivas_syn_output( p_head_pose_buf, nOutSamples, hIvasDec->st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf ); + } + } + else + { +#endif + error = ivas_dec_render( hIvasDec->st_ivas, nSamplesToRender, &nSamplesFlushedLocal, &hIvasDec->nSamplesAvailableNext, pcm_type_API_to_internal( pcmType ), pcmBuf ); +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + } +#endif } else { diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index 9f00f39e7..eb5e980a5 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -335,6 +335,9 @@ ivas_error IVAS_DEC_Flush( const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ void *pcmBuf, /* o : output synthesis signal */ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits; NULL when not applicable */ +#endif int16_t *nSamplesFlushed /* o : number of samples flushed */ ); -- GitLab From 20a0cfb1082dac9472b18d090db8308b43c3ac8e Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 26 May 2026 12:52:22 +0200 Subject: [PATCH 2/8] clang format --- apps/decoder.c | 18 +++++++++--------- lib_dec/lib_dec.c | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index 80a0e7d6b..a36ba6cca 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -2918,10 +2918,10 @@ static ivas_error decodeG192( /* flush remaining audio */ if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, -#ifdef FIX_1342_PROPER_FLUSH_IN_SR - splitRendBits, -#endif - &nSamplesFlushed ) ) != IVAS_ERR_OK ) +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + splitRendBits, +#endif + &nSamplesFlushed ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -2930,14 +2930,14 @@ static ivas_error decodeG192( #ifdef FIX_1342_PROPER_FLUSH_IN_SR if ( !isSplitCoded ) { -#endif +#endif /* Write current frame */ if ( ( error = AudioFileWriter_write( afWriter, pcmBuf, nSamplesFlushed * nOutChannels ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nOutput audio file writer error\n" ); goto cleanup; } -#ifdef FIX_1342_PROPER_FLUSH_IN_SR +#ifdef FIX_1342_PROPER_FLUSH_IN_SR } #endif @@ -3859,9 +3859,9 @@ static ivas_error decodeVoIP( /* flush remaining audio */ if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, #ifdef FIX_1342_PROPER_FLUSH_IN_SR - splitRendBits, -#endif - &nSamplesFlushed ) ) != IVAS_ERR_OK ) + splitRendBits, +#endif + &nSamplesFlushed ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index e7d484a22..f7b81908e 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4311,14 +4311,14 @@ static void update_voip_rendered20ms( *---------------------------------------------------------------------*/ ivas_error IVAS_DEC_Flush( - IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ - const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ - const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ - void *pcmBuf, /* o : output synthesis signal */ -#ifdef FIX_1342_PROPER_FLUSH_IN_SR + IVAS_DEC_HANDLE hIvasDec, /* i/o: IVAS decoder handle */ + const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ + const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ + void *pcmBuf, /* o : output synthesis signal */ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits; NULL when not applicable */ -#endif - int16_t *nSamplesFlushed /* o : number of samples flushed */ +#endif + int16_t *nSamplesFlushed /* o : number of samples flushed */ ) { ivas_error error; @@ -4376,11 +4376,11 @@ ivas_error IVAS_DEC_Flush( } else { -#endif +#endif error = ivas_dec_render( hIvasDec->st_ivas, nSamplesToRender, &nSamplesFlushedLocal, &hIvasDec->nSamplesAvailableNext, pcm_type_API_to_internal( pcmType ), pcmBuf ); #ifdef FIX_1342_PROPER_FLUSH_IN_SR } -#endif +#endif } else { -- GitLab From b602250cd5fe7429bf6304bcc3d693867ea7d4f2 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 26 May 2026 13:15:23 +0200 Subject: [PATCH 3/8] remove unused structure --- apps/decoder.c | 12 ++---------- lib_dec/lib_dec.c | 3 --- lib_dec/lib_dec.h | 3 --- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index a36ba6cca..0370b2b96 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -2917,11 +2917,7 @@ static ivas_error decodeG192( } /* flush remaining audio */ - if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, -#ifdef FIX_1342_PROPER_FLUSH_IN_SR - splitRendBits, -#endif - &nSamplesFlushed ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; @@ -3857,11 +3853,7 @@ static ivas_error decodeVoIP( int16_t nSamplesFlushed = 0; /* flush remaining audio */ - if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, -#ifdef FIX_1342_PROPER_FLUSH_IN_SR - splitRendBits, -#endif - &nSamplesFlushed ) ) != IVAS_ERR_OK ) + if ( ( error = IVAS_DEC_Flush( hIvasDec, nOutSamples, IVAS_DEC_PCM_INT16, (void *) pcmBuf, &nSamplesFlushed ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_DEC_VoIP_Flush: %s\n", IVAS_DEC_GetErrorMessage( error ) ); goto cleanup; diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index f7b81908e..b7aca5136 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4315,9 +4315,6 @@ ivas_error IVAS_DEC_Flush( const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ void *pcmBuf, /* o : output synthesis signal */ -#ifdef FIX_1342_PROPER_FLUSH_IN_SR - ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits; NULL when not applicable */ -#endif int16_t *nSamplesFlushed /* o : number of samples flushed */ ) { diff --git a/lib_dec/lib_dec.h b/lib_dec/lib_dec.h index eb5e980a5..9f00f39e7 100644 --- a/lib_dec/lib_dec.h +++ b/lib_dec/lib_dec.h @@ -335,9 +335,6 @@ ivas_error IVAS_DEC_Flush( const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ void *pcmBuf, /* o : output synthesis signal */ -#ifdef FIX_1342_PROPER_FLUSH_IN_SR - ISAR_SPLIT_REND_BITS_DATA *splitRendBits, /* o : output split rendering bits; NULL when not applicable */ -#endif int16_t *nSamplesFlushed /* o : number of samples flushed */ ); -- GitLab From 43f3e899384e9fbcf33258960533d1ad0e2dfd6f Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 26 May 2026 14:03:54 +0200 Subject: [PATCH 4/8] clang format --- lib_dec/lib_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index b7aca5136..520ef8b19 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4315,7 +4315,7 @@ ivas_error IVAS_DEC_Flush( const int16_t nSamplesPerChannel, /* i : number of samples per channel requested to be written to output buffer */ const IVAS_DEC_PCM_TYPE pcmType, /* i : type for the decoded PCM resolution */ void *pcmBuf, /* o : output synthesis signal */ - int16_t *nSamplesFlushed /* o : number of samples flushed */ + int16_t *nSamplesFlushed /* o : number of samples flushed */ ) { ivas_error error; -- GitLab From 278f78f2c685f391057270205b4c0707e73cd0a6 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Tue, 26 May 2026 15:08:30 +0200 Subject: [PATCH 5/8] need to populate p_head_pose_buf - needed by ivas_syn_output --- lib_dec/lib_dec.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 520ef8b19..0ffc790b2 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4362,13 +4362,35 @@ ivas_error IVAS_DEC_Flush( *nSamplesFlushed = nOutSamples; - /* Flush the remaing audio output in SR mode. Metadata generation is handled during normal decoding */ + /* Flush the remaining audio output in SR mode. + For BINAURAL_SPLIT_PCM, generate metadata and binaural PCM from the ring buffer. + The ISAR metadata output is discarded (flush frames are not written to the metadata file). */ if ( hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { + Decoder_Struct *st_ivas_flush = hIvasDec->st_ivas; + ISAR_SPLIT_REND_BITS_DATA flushSplitRendBits; + uint8_t flushBitsBuf[ISAR_MAX_SPLIT_REND_BITS_BUFFER_SIZE_IN_BYTES]; + + flushSplitRendBits.bits_buf = flushBitsBuf; + flushSplitRendBits.bits_read = 0; + flushSplitRendBits.bits_written = 0; + flushSplitRendBits.buf_len = ISAR_MAX_SPLIT_REND_BITS_BUFFER_SIZE_IN_BYTES; + flushSplitRendBits.codec = ISAR_SPLIT_REND_CODEC_DEFAULT; + flushSplitRendBits.pose_correction = ISAR_SPLIT_REND_POSE_CORRECTION_MODE_NONE; + flushSplitRendBits.codec_frame_size_ms = 0; + flushSplitRendBits.isar_frame_size_ms = 0; + flushSplitRendBits.lc3plus_highres = 0; + + /* Pop from ring buffer and generate binaural PCM into p_head_pose_buf */ + if ( ( error = isar_generate_metadata_and_bitstream( st_ivas_flush, p_head_pose_buf, nOutSamples, &flushSplitRendBits ) ) != IVAS_ERR_OK ) + { + return error; + } + #ifndef DISABLE_LIMITER - ivas_limiter_dec( hIvasDec->st_ivas->hLimiter, p_head_pose_buf, hIvasDec->st_ivas->hDecoderConfig->nchan_out, nOutSamples, hIvasDec->st_ivas->BER_detect ); + ivas_limiter_dec( st_ivas_flush->hLimiter, p_head_pose_buf, st_ivas_flush->hDecoderConfig->nchan_out, nOutSamples, st_ivas_flush->BER_detect ); #endif - ivas_syn_output( p_head_pose_buf, nOutSamples, hIvasDec->st_ivas->hDecoderConfig->nchan_out, (int16_t *) pcmBuf ); + ivas_syn_output( p_head_pose_buf, nOutSamples, st_ivas_flush->hDecoderConfig->nchan_out, (int16_t *) pcmBuf ); } } else -- GitLab From 73cb32e1067ccb974555babe4d0cefce1c23dcbe Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 27 May 2026 15:06:13 +0200 Subject: [PATCH 6/8] fix crash due to runnig loop beyond num_cldfb_slots --- lib_dec/lib_dec.c | 7 ++++++- lib_isar/isar_prot.h | 4 ++++ lib_isar/isar_splitRendererPre.c | 27 ++++++++++++++++++++++++++- lib_isar/lib_isar_pre_rend.c | 4 ++++ 4 files changed, 40 insertions(+), 2 deletions(-) diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 0ffc790b2..bbf7d4f96 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -2176,7 +2176,11 @@ static ivas_error isar_generate_metadata_and_bitstream( Quaternion, st_ivas->hRenderConfig->split_rend_config.splitRendBitRate, st_ivas->hRenderConfig->split_rend_config.codec, +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + (int16_t) ( (int32_t) nSamples * 1000 / (int32_t) st_ivas->hDecoderConfig->output_Fs ), +#else st_ivas->hRenderConfig->split_rend_config.isar_frame_size_ms, +#endif st_ivas->hRenderConfig->split_rend_config.codec_frame_size_ms, splitRendBits, p_Cldfb_RealBuffer_Binaural, @@ -4365,7 +4369,8 @@ ivas_error IVAS_DEC_Flush( /* Flush the remaining audio output in SR mode. For BINAURAL_SPLIT_PCM, generate metadata and binaural PCM from the ring buffer. The ISAR metadata output is discarded (flush frames are not written to the metadata file). */ - if ( hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + if ( hIvasDec->st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM && + hIvasDec->hasBeenFedFirstGoodFrame && nOutSamples > 0 ) { Decoder_Struct *st_ivas_flush = hIvasDec->st_ivas; ISAR_SPLIT_REND_BITS_DATA flushSplitRendBits; diff --git a/lib_isar/isar_prot.h b/lib_isar/isar_prot.h index 1ba51ecd5..020881f29 100644 --- a/lib_isar/isar_prot.h +++ b/lib_isar/isar_prot.h @@ -277,6 +277,10 @@ void isar_rend_CldfbSplitPreRendProcess( const int32_t target_md_bits, /* i : ISAR MD bitrate */ const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ const int16_t ro_md_flag /* i : real only metadata for yaw flag */ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + , + const int16_t num_cldfb_slots /* i : actual number of valid CLDFB columns */ +#endif ); ivas_error isar_renderMultiTDBinToSplitBinaural( diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 242d29ac4..f787f4dca 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -53,7 +53,11 @@ * Local function declarations *---------------------------------------------------------------------*/ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR +static void isar_SplitRenderer_GetRotMd( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, float *Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], float *Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], const int16_t low_res, const int16_t ro_md_flag, const int16_t num_cldfb_slots ); +#else static void isar_SplitRenderer_GetRotMd( ISAR_BIN_HR_SPLIT_PRE_REND_HANDLE hBinHrSplitPreRend, MULTI_BIN_REND_POSE_DATA *pMultiBinPoseData, float *Cldfb_RealBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], float *Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], const int16_t low_res, const int16_t ro_md_flag ); +#endif /*------------------------------------------------------------------------- @@ -1351,6 +1355,10 @@ static void isar_SplitRenderer_GetRotMd( float *Cldfb_ImagBuffer_Ref_Binaural[][CLDFB_NO_COL_MAX], /* o : Reference Binaural signals */ const int16_t low_res, const int16_t ro_md_flag /* i : Flag to indicate real only metadata for yaw */ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + , + const int16_t num_cldfb_slots /* i : actual number of valid CLDFB columns in the input buffers */ +#endif ) { float cov_ii_re[BINAURAL_CHANNELS][BINAURAL_CHANNELS]; @@ -1371,7 +1379,11 @@ static void isar_SplitRenderer_GetRotMd( if ( low_res ) { +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + num_slots = num_cldfb_slots; +#else num_slots = CLDFB_NO_COL_MAX; +#endif num_subframes = 1; } else @@ -1439,11 +1451,19 @@ void isar_rend_CldfbSplitPreRendProcess( const int32_t target_md_bits, /* i : ISAR MD bitrate */ const int16_t low_res_pre_rend_rot, /* i : low time resolution pre-renderer flag */ const int16_t ro_md_flag /* i : real only metadata for yaw flag */ +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + , + const int16_t num_cldfb_slots /* i : actual number of valid CLDFB columns */ +#endif ) { push_wmops( "isar_rend_CldfbSplitPreRendProcess" ); +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + isar_SplitRenderer_GetRotMd( hBinHrSplitPreRend, pMultiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, low_res_pre_rend_rot, ro_md_flag, num_cldfb_slots ); +#else isar_SplitRenderer_GetRotMd( hBinHrSplitPreRend, pMultiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, low_res_pre_rend_rot, ro_md_flag ); +#endif isar_SplitRenderer_quant_code( hBinHrSplitPreRend, headPosition, pMultiBinPoseData, pBits, low_res_pre_rend_rot, ro_md_flag, target_md_bits ); @@ -1985,7 +2005,12 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( pBits, target_md_bits, low_res_pre_rend_rot, - ro_md_flag ); + ro_md_flag +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + , + (int16_t) num_slots +#endif + ); } if ( pcm_out_flag == 0 ) diff --git a/lib_isar/lib_isar_pre_rend.c b/lib_isar/lib_isar_pre_rend.c index 6ba81ec70..66b71eb9d 100644 --- a/lib_isar/lib_isar_pre_rend.c +++ b/lib_isar/lib_isar_pre_rend.c @@ -341,7 +341,11 @@ ivas_error ISAR_PRE_REND_MultiBinToSplitBinaural( target_md_bits = isar_get_split_rend_md_target_brate( SplitRendBitRate, pcm_out_flag ) * L_FRAME48k / 48000; +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag, (int16_t) ( isar_frame_size_ms * 1000000 / CLDFB_SLOT_NS ) ); +#else isar_rend_CldfbSplitPreRendProcess( hSplitBin->hBinHrSplitPreRend, headPosition, &hSplitBin->multiBinPoseData, Cldfb_In_BinReal, Cldfb_In_BinImag, pBits, target_md_bits, low_res_pre_rend_rot, ro_md_flag ); +#endif } if ( pcm_out_flag == 0 ) -- GitLab From acb442b09f9fe9eef767f40e822fad05b2d924e0 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 27 May 2026 15:22:01 +0200 Subject: [PATCH 7/8] Fix C4701: initialize num_slots to 0 to silence MSVC uninitialized variable warning --- lib_isar/isar_splitRendererPre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index f787f4dca..11201308d 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -1917,7 +1917,7 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( int16_t j; float *p_Cldfb_In_BinReal[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; float *p_Cldfb_In_BinImag[MAX_HEAD_ROT_POSES * BINAURAL_CHANNELS][CLDFB_NO_COL_MAX]; - int32_t num_slots; + int32_t num_slots = 0; push_wmops( "isar_renderMultiTDBinToSplitBinaural" ); -- GitLab From 39102f53606765b78a2386172d109cf55168ab14 Mon Sep 17 00:00:00 2001 From: Vladimir Malenovsky Date: Wed, 27 May 2026 18:14:47 +0200 Subject: [PATCH 8/8] fix crash in LC3+ high-res mode --- lib_dec/lib_dec.c | 3 +++ lib_isar/isar_splitRendererPre.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index bbf7d4f96..d4a631ffd 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4352,8 +4352,11 @@ ivas_error IVAS_DEC_Flush( float head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES][L_FRAME48k]; float *p_head_pose_buf[BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES]; + /* Zero-initialise so that ivas_limiter_dec never reads uninitialised memory + (e.g. when the ring buffer provides fewer samples than the nominal frame size) */ for ( i = 0; i < BINAURAL_CHANNELS * MAX_HEAD_ROT_POSES; ++i ) { + set_zero( head_pose_buf[i], L_FRAME48k ); p_head_pose_buf[i] = head_pose_buf[i]; } diff --git a/lib_isar/isar_splitRendererPre.c b/lib_isar/isar_splitRendererPre.c index 11201308d..6e8690669 100644 --- a/lib_isar/isar_splitRendererPre.c +++ b/lib_isar/isar_splitRendererPre.c @@ -1396,6 +1396,12 @@ static void isar_SplitRenderer_GetRotMd( for ( sf_idx = 0; sf_idx < num_subframes; sf_idx++ ) { start_slot_idx = sf_idx * num_slots; +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + if ( start_slot_idx >= num_cldfb_slots ) + { + break; + } +#endif for ( b = 0; b < num_md_bands; b++ ) { if ( ( b < SPLIT_REND_RO_MD_BAND_THRESH ) || ( !ro_md_flag && b < COMPLEX_MD_BAND_THRESH ) ) @@ -1945,7 +1951,21 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( /* Artificially delay input to head pose correction analysis by LC3plus coding delay, so that audio and metadata are in sync after decoding */ mvr2r( hSplitBin->lc3plusDelayBuffers[i] + frame_size, hSplitBin->lc3plusDelayBuffers[i], (int16_t) hSplitBin->lc3plusDelaySamples ); in_delayed[i] = hSplitBin->lc3plusDelayBuffers[i]; +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + { + /* During flush the actual number of new samples may be less than the nominal frame size. + * Only copy the available samples and zero-fill the rest to avoid reading uninitialised memory. */ + int16_t actual_samples_lc3 = (int16_t) ( (int32_t) hSplitBin->hLc3plusEnc->config.samplerate * isar_frame_size_ms / 1000 ); + mvr2r( in[i], hSplitBin->lc3plusDelayBuffers[i] + hSplitBin->lc3plusDelaySamples, actual_samples_lc3 ); + if ( actual_samples_lc3 < frame_size ) + { + set_zero( hSplitBin->lc3plusDelayBuffers[i] + hSplitBin->lc3plusDelaySamples + actual_samples_lc3, + frame_size - actual_samples_lc3 ); + } + } +#else mvr2r( in[i], hSplitBin->lc3plusDelayBuffers[i] + hSplitBin->lc3plusDelaySamples, frame_size ); +#endif } } else @@ -1958,7 +1978,14 @@ ivas_error isar_renderMultiTDBinToSplitBinaural( if ( ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) || ( !useLc3plus && !pcm_out_flag ) ) { +#ifdef FIX_1342_PROPER_FLUSH_IN_SR + /* During flush, use only the actual number of valid CLDFB slots derived from isar_frame_size_ms */ + num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) + ? (int32_t) ( (int32_t) isar_frame_size_ms * 1000000L / CLDFB_SLOT_NS ) + : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ); +#else num_slots = ( hSplitBin->multiBinPoseData.poseCorrectionMode == ISAR_SPLIT_REND_POSE_CORRECTION_MODE_CLDFB ) ? CLDFB_NO_COL_MAX : ( hSplitBin->hSplitBinLCLDEnc->iNumBlocks * hSplitBin->hSplitBinLCLDEnc->iNumIterations ); +#endif num_cldfb_bands = hSplitBin->hCldfbHandles->cldfbAna[0]->no_channels; /* CLDFB Analysis*/ -- GitLab