From fd0cc99c84873f1c7159b0ed0721d06b7b2db839 Mon Sep 17 00:00:00 2001 From: Tommy Vaillancourt Date: Fri, 23 May 2025 14:35:26 -0400 Subject: [PATCH 01/61] possible fix to #1328 --- lib_com/options.h | 2 +- lib_dec/acelp_core_dec.c | 6 ++++++ lib_enc/acelp_core_enc.c | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/lib_com/options.h b/lib_com/options.h index f7ce57b4bd..92d8e6685e 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -172,7 +172,7 @@ #define NONBE_1244_FIX_SWB_BWE_MEMORY /* VA: issue 1244: fix to SWB BWE memory in case of switching from FB coding - pending a review by Huawei */ #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 NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0 */ /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c index 46a3ec3014..13702e3d67 100644 --- a/lib_dec/acelp_core_dec.c +++ b/lib_dec/acelp_core_dec.c @@ -1424,6 +1424,12 @@ ivas_error acelp_core_dec( if ( !st->ppp_mode_dec && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { +#ifdef NONBE_1328_FIX_NON_LINEARITY + if ( st->hBWE_TD->bwe_non_lin_prev_scale > 0.1f && st->element_mode > EVS_MONO && ( st->coder_type <= UNVOICED ) ) + { + st->hBWE_TD->bwe_non_lin_prev_scale = 0.025f; + } +#endif non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); } diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index cf43042ce0..198d720f64 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -701,6 +701,12 @@ ivas_error acelp_core_enc( if ( !st->Opt_SC_VBR && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { +#ifdef NONBE_1328_FIX_NON_LINEARITY + if ( st->hBWE_TD->bwe_non_lin_prev_scale > 0.1f && st->element_mode > EVS_MONO && ( st->coder_type <= UNVOICED ) ) + { + st->hBWE_TD->bwe_non_lin_prev_scale = 0.025f; + } +#endif /* Apply a non linearity to the SHB excitation */ non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); } -- GitLab From 4599af5b16105ff44f5d332c9134c6cfc3d62369 Mon Sep 17 00:00:00 2001 From: malenov Date: Tue, 10 Jun 2025 14:36:45 +0200 Subject: [PATCH 02/61] alternative fix to prevent excessive re-scaling of BWE excitation signal --- lib_com/swb_tbe_com.c | 5 ++++- lib_dec/acelp_core_dec.c | 6 ------ lib_enc/acelp_core_enc.c | 6 ------ 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/lib_com/swb_tbe_com.c b/lib_com/swb_tbe_com.c index a8d88c2b0f..096fc02250 100644 --- a/lib_com/swb_tbe_com.c +++ b/lib_com/swb_tbe_com.c @@ -1410,8 +1410,11 @@ void non_linearity( scale = 0.67f; } - +#ifdef NONBE_1328_FIX_NON_LINEARITY + if ( *prev_scale <= 0.0 || *prev_scale > 256.0f * scale ) +#else if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) +#endif { scale_step = 1.0; *prev_scale = scale; diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c index 13702e3d67..46a3ec3014 100644 --- a/lib_dec/acelp_core_dec.c +++ b/lib_dec/acelp_core_dec.c @@ -1424,12 +1424,6 @@ ivas_error acelp_core_dec( if ( !st->ppp_mode_dec && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { -#ifdef NONBE_1328_FIX_NON_LINEARITY - if ( st->hBWE_TD->bwe_non_lin_prev_scale > 0.1f && st->element_mode > EVS_MONO && ( st->coder_type <= UNVOICED ) ) - { - st->hBWE_TD->bwe_non_lin_prev_scale = 0.025f; - } -#endif non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); } diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index 198d720f64..cf43042ce0 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -701,12 +701,6 @@ ivas_error acelp_core_enc( if ( !st->Opt_SC_VBR && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { -#ifdef NONBE_1328_FIX_NON_LINEARITY - if ( st->hBWE_TD->bwe_non_lin_prev_scale > 0.1f && st->element_mode > EVS_MONO && ( st->coder_type <= UNVOICED ) ) - { - st->hBWE_TD->bwe_non_lin_prev_scale = 0.025f; - } -#endif /* Apply a non linearity to the SHB excitation */ non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); } -- GitLab From 5f95717bbffc48107a30a41dfb2fe8980ce74bc8 Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 11:58:23 +0200 Subject: [PATCH 03/61] issue 1330: memory savings in the JBM decoder; under FIX_1330_JBM_MEMORY --- lib_com/ivas_prot.h | 10 +++++ lib_com/ivas_tools.c | 12 +++++ lib_com/options.h | 2 + lib_dec/ivas_init_dec.c | 34 +++++++++++++-- lib_dec/ivas_ism_dec.c | 16 ++++++- lib_dec/ivas_ism_renderer.c | 22 ++++++++-- lib_dec/ivas_jbm_dec.c | 27 ++++++++++++ lib_dec/ivas_masa_dec.c | 8 ++++ lib_dec/ivas_mct_dec.c | 6 ++- lib_dec/ivas_omasa_dec.c | 34 +++++++++++++-- lib_dec/ivas_osba_dec.c | 8 ++++ lib_dec/ivas_sba_dec.c | 5 ++- lib_rend/ivas_output_init.c | 87 +++++++++++++++++++++++++++++++------ 13 files changed, 243 insertions(+), 28 deletions(-) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 8121030b1c..c4ef05e123 100755 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -309,7 +309,13 @@ ivas_error ivas_init_decoder( ivas_error ivas_output_buff_dec( float *p_output_f[], /* i/o: output audio buffers */ const int16_t nchan_out_buff_old, /* i : previous frame number of output channels*/ +#ifdef FIX_1330_JBM_MEMORY + const int16_t nchan_out_buff, /* i : number of output channels */ + const int16_t Opt_tsm, /* i : TSM option flag */ + DECODER_TC_BUFFER_HANDLE hTcBuffer /* i : TSM buffer handle */ +#else const int16_t nchan_out_buff /* i : number of output channels */ +#endif ); ivas_error stereo_dmx_evs_init_encoder( @@ -5823,8 +5829,12 @@ void ivas_omasa_separate_object_render_jbm( const uint16_t nSamplesRendered, /* i : number of samples rendered */ float input_f[][L_FRAME48k], /* i : separated object signal */ float *output_f[], /* o : rendered time signal */ +#ifdef FIX_1330_JBM_MEMORY + const int16_t subframes_rendered /* i : number of subframes rendered */ +#else const int16_t subframes_rendered, /* i : number of subframes rendered */ const int16_t slots_rendered /* i : number of CLDFB slots rendered */ +#endif ); void ivas_omasa_encode_masa_to_total( diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index baa98da6b7..d2dde26fb5 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -198,12 +198,24 @@ void ivas_buffer_deinterleaved_to_interleaved( ) { int16_t ch, m; +#ifdef FIX_1330_JBM_MEMORY + float buffer[MAX_TRANSPORT_CHANNELS][L_FRAME48k]; + + for ( ch = 0; ch < n_channels; ch++ ) + { + mvr2r( audio[ch], buffer[ch], frame_length ); + } +#endif for ( ch = 0; ch < n_channels; ch++ ) { for ( m = 0; m < frame_length; m++ ) { +#ifdef FIX_1330_JBM_MEMORY + audio_out[m * n_channels + ch] = buffer[ch][m]; +#else audio_out[m * n_channels + ch] = audio[ch][m]; +#endif } } diff --git a/lib_com/options.h b/lib_com/options.h index 88467e1090..df668e606c 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -162,6 +162,8 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ +#define FIX_1330_JBM_MEMORY /* VA: issue 1330: memory savings in the JBM decoder */ + /* #################### End BE switches ################################## */ diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index a303c6d65b..0424ced917 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2363,7 +2363,7 @@ ivas_error ivas_init_decoder( } } - if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) && st_ivas->hDecoderConfig->Opt_tsm ) + if ( ( st_ivas->ivas_format == MASA_FORMAT || st_ivas->ivas_format == MASA_ISM_FORMAT ) && hDecoderConfig->Opt_tsm ) { if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { @@ -2378,7 +2378,18 @@ ivas_error ivas_init_decoder( * Allocate floating-point output audio buffers *-----------------------------------------------------------------*/ - k = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); + k = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); +#ifdef FIX_1330_JBM_MEMORY + for ( n = 0; n < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; n++ ) + { + st_ivas->p_output_f[n] = NULL; + } + + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, 0, k, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } +#else for ( n = 0; n < k; n++ ) { /* note: these are intra-frame heap memories */ @@ -2392,7 +2403,7 @@ ivas_error ivas_init_decoder( { st_ivas->p_output_f[n] = NULL; } - +#endif return error; } @@ -2849,12 +2860,27 @@ void ivas_destroy_dec( /* Limiter struct */ ivas_limiter_close( &( st_ivas->hLimiter ) ); +#ifdef FIX_1330_JBM_MEMORY + /* JBM decoding: floating-point output audio buffers are shared with bufeers from 'hTcBuffer' */ + if ( st_ivas->hDecoderConfig->Opt_tsm ) + { + int16_t nchan_tc_jbm = max( st_ivas->hTcBuffer->nchan_transport_jbm, st_ivas->hTcBuffer->nchan_buffer_full ); + + for ( i = 0; i < nchan_tc_jbm; i++ ) + { + st_ivas->p_output_f[i] = NULL; + } + } + + /* Decoder configuration structure */ +#endif if ( st_ivas->hDecoderConfig != NULL ) { free( st_ivas->hDecoderConfig ); st_ivas->hDecoderConfig = NULL; } + /* JBM TC buffer structure */ ivas_jbm_dec_tc_buffer_close( &st_ivas->hTcBuffer ); if ( st_ivas->hJbmMetadata != NULL ) @@ -2863,7 +2889,7 @@ void ivas_destroy_dec( st_ivas->hJbmMetadata = NULL; } - /* floating-point output audio buffers */ + /* floating-point output audio buffers */ for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { if ( st_ivas->p_output_f[i] != NULL ) diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index a76db36306..64f8d15dab 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -266,17 +266,17 @@ static ivas_error ivas_ism_bitrate_switching_dec( return error; } +#ifndef FIX_1330_JBM_MEMORY /*-----------------------------------------------------------------* * floating-point output audio buffers *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) { return error; } - +#endif /*-----------------------------------------------------------------* * JBM TC buffers *-----------------------------------------------------------------*/ @@ -316,6 +316,18 @@ static ivas_error ivas_ism_bitrate_switching_dec( mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpatParamRendCom->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } +#ifdef FIX_1330_JBM_MEMORY + + /*-----------------------------------------------------------------* + * floating-point output audio buffers + *-----------------------------------------------------------------*/ + + nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + { + return error; + } +#endif return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 3d18fea93b..55a77e0ba8 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -193,6 +193,7 @@ void ivas_ism_render_sf( ism_md_subframe_update_jbm = st_ivas->hTcBuffer->nb_subframes - 2; } +#ifndef FIX_1330_JBM_MEMORY if ( st_ivas->hDecoderConfig->Opt_tsm ) { for ( i = 0; i < num_objects; i++ ) @@ -202,12 +203,15 @@ void ivas_ism_render_sf( } else { +#endif for ( i = 0; i < num_objects; i++ ) { mvr2r( &output_f[i][tc_offset], tc_local[i], n_samples_to_render ); p_tc[i] = tc_local[i]; } +#ifndef FIX_1330_JBM_MEMORY } +#endif for ( i = 0; i < nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ ) { @@ -428,12 +432,16 @@ void ivas_omasa_separate_object_renderer_close( *-------------------------------------------------------------------------*/ void ivas_omasa_separate_object_render_jbm( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const uint16_t nSamplesRendered, /* i : number of samples rendered */ - float input_f_in[][L_FRAME48k], /* i : separated object signal */ - float *output_f[], /* o : rendered time signal */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const uint16_t nSamplesRendered, /* i : number of samples rendered */ + float input_f_in[][L_FRAME48k], /* i : separated object signal */ + float *output_f[], /* o : rendered time signal */ +#ifdef FIX_1330_JBM_MEMORY + const int16_t subframes_rendered /* i : number of subframes rendered */ +#else const int16_t subframes_rendered, /* i : number of subframes rendered */ const int16_t slots_rendered /* i : number of CLDFB slots rendered */ +#endif ) { VBAP_HANDLE hVBAPdata; @@ -474,13 +482,16 @@ void ivas_omasa_separate_object_render_jbm( num_objects = st_ivas->nchan_ism; } +#ifndef FIX_1330_JBM_MEMORY offsetSamples = slots_rendered * hSpatParamRendCom->slot_size; +#endif for ( j = 0; j < nchan_out_woLFE + num_lfe; j++ ) { output_f_local[j] = output_f[j]; } +#ifndef FIX_1330_JBM_MEMORY if ( st_ivas->hDecoderConfig->Opt_tsm ) { for ( obj = 0; obj < num_objects; obj++ ) @@ -490,11 +501,14 @@ void ivas_omasa_separate_object_render_jbm( } else { +#endif for ( obj = 0; obj < num_objects; obj++ ) { input_f[obj] = input_f_in[obj]; } +#ifndef FIX_1330_JBM_MEMORY } +#endif slots_to_render = nSamplesRendered / hSpatParamRendCom->slot_size; first_sf = subframes_rendered; diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 173d031628..9aeb4f38fe 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -763,7 +763,11 @@ void ivas_jbm_dec_feed_tc_to_renderer( float tmp_buf[MAX_JBM_L_FRAME48k]; float *p_data_f[FOA_CHANNELS + MAX_NUM_OBJECTS]; int16_t n, n_render_timeslots, n_ch_cldfb; +#ifdef FIX_1330_JBM_MEMORY + int16_t ch, offset, len_offset; +#else int16_t ch; +#endif DECODER_TC_BUFFER_HANDLE hTcBuffer; hTcBuffer = st_ivas->hTcBuffer; @@ -781,6 +785,22 @@ void ivas_jbm_dec_feed_tc_to_renderer( n_ch_full_copy = min( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); n_ch_res_copy = hTcBuffer->nchan_transport_jbm - hTcBuffer->nchan_buffer_full; +#ifdef FIX_1330_JBM_MEMORY + /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': + in case of 'length(hTcBuffer->tc[]) < length(p_output_f[])', reset of TC buffers + pointers is needed after ivas_buffer_interleaved_to_deinterleaved() */ + len_offset = NS2SA( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ); + if ( len_offset < L_FRAME48k ) + { + offset = 0; + for ( ch = 0; ch < max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); ch++ ) + { + hTcBuffer->tc[ch] = &hTcBuffer->tc_buffer[offset]; + offset += len_offset; + } + } + +#endif for ( ch = 0; ch < n_ch_full_copy; ch++ ) { mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); @@ -2084,6 +2104,9 @@ static ivas_error ivas_jbm_dec_tc_audio_allocate( if ( Opt_tsm ) { n_samp_full = ( NS2SA( output_Fs, MAX_JBM_L_FRAME_NS ) ); +#ifdef FIX_1330_JBM_MEMORY + n_samp_full = max( n_samp_full, L_FRAME48k ); /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': ensure minimal length */ +#endif n_samp_residual = hTcBuffer->n_samples_granularity - 1; } else @@ -2376,7 +2399,11 @@ static void ivas_jbm_dec_tc_buffer_playout( for ( ch_idx = 0; ch_idx < st_ivas->hTcBuffer->nchan_transport_jbm; ch_idx++ ) { +#ifdef FIX_1330_JBM_MEMORY + output[ch_idx] = st_ivas->hTcBuffer->tc[ch_idx] + st_ivas->hTcBuffer->n_samples_rendered; +#else mvr2r( st_ivas->hTcBuffer->tc[ch_idx] + st_ivas->hTcBuffer->n_samples_rendered, output[ch_idx], *nSamplesRendered ); +#endif } st_ivas->hTcBuffer->subframes_rendered = last_sf; diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index b698395d75..3d7d78d55d 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1474,6 +1474,10 @@ ivas_error ivas_masa_dec_reconfigure( ivas_masa_set_elements( ivas_total_brate, st_ivas->mc_mode, st_ivas->nchan_transport, st_ivas->hQMetaData, &tmp, &tmp, &tmp, st_ivas->ivas_format, st_ivas->ism_mode, ism_total_brate ); + /*-----------------------------------------------------------------* + * JBM TC buffers + *-----------------------------------------------------------------*/ + { int16_t tc_nchan_to_allocate; int16_t tc_nchan_transport; @@ -1544,7 +1548,11 @@ ivas_error ivas_masa_dec_reconfigure( if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->last_ivas_format == MASA_FORMAT ) /* note: switching with OMASA is addressed in ivas_omasa_dec_config() */ { nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); +#ifdef FIX_1330_JBM_MEMORY + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 8fb966c365..b495f594c7 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -1320,6 +1320,7 @@ static ivas_error ivas_mc_dec_reconfig( return error; } } + /* transfer subframe info from central tc buffer to ParamMC or McMASA (DirAC) */ if ( st_ivas->hSpatParamRendCom != NULL ) { @@ -1344,8 +1345,11 @@ static ivas_error ivas_mc_dec_reconfig( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); - +#ifdef FIX_1330_JBM_MEMORY + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index beaf645fa0..d6e0060a57 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -470,7 +470,11 @@ ivas_error ivas_omasa_dec_config( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); +#ifdef FIX_1330_JBM_MEMORY + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -673,19 +677,27 @@ void ivas_omasa_dirac_rend_jbm( ) { int16_t subframes_rendered; +#ifndef FIX_1330_JBM_MEMORY int16_t slots_rendered; +#endif int16_t n; float data_separated_objects[MAX_NUM_OBJECTS][L_FRAME48k]; +#ifndef FIX_1330_JBM_MEMORY if ( !st_ivas->hDecoderConfig->Opt_tsm ) { +#endif *nSamplesRendered = min( nSamplesAsked, st_ivas->hTcBuffer->n_samples_available ); if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) { mvr2r( &output_f[CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[0], *nSamplesRendered ); - if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) +#ifdef FIX_1330_JBM_MEMORY + if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) +#else + if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) +#endif { /* Gain separated object, if edited */ for ( n = 0; n < st_ivas->nchan_ism; n++ ) @@ -704,14 +716,22 @@ void ivas_omasa_dirac_rend_jbm( mvr2r( &output_f[n + CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[n], *nSamplesRendered ); /* Gain discrete objects, if edited */ - if ( st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) +#ifdef FIX_1330_JBM_MEMORY + if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) +#else + if ( st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) +#endif { v_multc( data_separated_objects[n], st_ivas->hMasaIsmData->gain_ism_edited[n], data_separated_objects[n], *nSamplesRendered ); } } /* Gain MASA part, if edited */ - if ( st_ivas->hMasaIsmData->masa_gain_is_edited ) +#ifdef FIX_1330_JBM_MEMORY + if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->masa_gain_is_edited ) +#else + if ( st_ivas->hMasaIsmData->masa_gain_is_edited ) +#endif { for ( int16_t ch = 0; ch < 2; ch++ ) { @@ -719,14 +739,22 @@ void ivas_omasa_dirac_rend_jbm( } } } +#ifndef FIX_1330_JBM_MEMORY } +#endif subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; +#ifndef FIX_1330_JBM_MEMORY slots_rendered = st_ivas->hSpatParamRendCom->slots_rendered; +#endif ivas_dirac_dec_render( st_ivas, nchan_transport, nSamplesAsked, nSamplesRendered, nSamplesAvailable, output_f ); +#ifdef FIX_1330_JBM_MEMORY + ivas_omasa_separate_object_render_jbm( st_ivas, *nSamplesRendered, data_separated_objects, output_f, subframes_rendered ); +#else ivas_omasa_separate_object_render_jbm( st_ivas, *nSamplesRendered, data_separated_objects, output_f, subframes_rendered, slots_rendered ); +#endif return; } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index afa273fdbb..f697fe3632 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -258,7 +258,11 @@ ivas_error ivas_osba_render_sf( float *p_output[] /* o : rendered time signal */ ) { +#ifdef FIX_1330_JBM_MEMORY + int16_t n, tc_offset; +#else int16_t n; +#endif float output_ism[MAX_OUTPUT_CHANNELS][L_FRAME48k]; float *p_output_ism[MAX_OUTPUT_CHANNELS]; ivas_error error; @@ -268,15 +272,19 @@ ivas_error ivas_osba_render_sf( p_output_ism[n] = &output_ism[n][0]; } +#ifndef FIX_1330_JBM_MEMORY if ( !st_ivas->hDecoderConfig->Opt_tsm ) { int16_t tc_offset; +#endif tc_offset = st_ivas->hTcBuffer->n_samples_rendered; for ( n = 0; n < st_ivas->nchan_ism; n++ ) { mvr2r( &p_output[n][tc_offset], &output_ism[n][tc_offset], nSamplesAsked ); } +#ifndef FIX_1330_JBM_MEMORY } +#endif if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) { diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 8ddc7f0406..4e00d948ee 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -591,8 +591,11 @@ ivas_error ivas_sba_dec_reconfigure( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); - +#ifdef FIX_1330_JBM_MEMORY + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 560f9f6661..be4af1b714 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -370,36 +370,97 @@ int16_t ivas_get_nchan_buffers_dec( ivas_error ivas_output_buff_dec( float *p_output_f[], /* i/o: output audio buffers */ const int16_t nchan_out_buff_old, /* i : previous frame number of output channels */ - const int16_t nchan_out_buff /* i : number of output channels */ +#ifdef FIX_1330_JBM_MEMORY + const int16_t nchan_out_buff, /* i : number of output channels */ + const int16_t Opt_tsm, /* i : TSM option flag */ + DECODER_TC_BUFFER_HANDLE hTcBuffer /* i : TSM buffer handle */ +#else + const int16_t nchan_out_buff /* i : number of output channels */ +#endif ) { int16_t ch; - if ( nchan_out_buff > nchan_out_buff_old ) +#ifdef FIX_1330_JBM_MEMORY + if ( !Opt_tsm ) { - for ( ch = nchan_out_buff_old; ch < nchan_out_buff; ch++ ) + /* non-JBM decoding: allocate output audio buffers here; audio buffers from 'hTcBuffer' are set to NULL */ + +#endif + if ( nchan_out_buff > nchan_out_buff_old ) { -#ifdef DEBUGGING - if ( p_output_f[ch] != NULL ) + for ( ch = nchan_out_buff_old; ch < nchan_out_buff; ch++ ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Memory for floating-point output audio buffer is already allocated!\n" ) ); - } +#ifdef DEBUGGING + if ( p_output_f[ch] != NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Memory for floating-point output audio buffer is already allocated!\n" ) ); + } #endif - /* note: these are intra-frame heap memories */ - if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) + /* note: these are intra-frame heap memories */ + if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); + } + } + } + else + { + for ( ch = nchan_out_buff; ch < nchan_out_buff_old; ch++ ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); + free( p_output_f[ch] ); + p_output_f[ch] = NULL; } } +#ifdef FIX_1330_JBM_MEMORY } else { - for ( ch = nchan_out_buff; ch < nchan_out_buff_old; ch++ ) + /* JBM decoding: output audio buffers are shared with audio buffers from 'hTcBuffer' */ + int16_t nchan_tc_jbm; + nchan_tc_jbm = max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); + + if ( nchan_out_buff <= nchan_tc_jbm ) + { + for ( ch = 0; ch < nchan_out_buff; ch++ ) + { + p_output_f[ch] = hTcBuffer->tc[ch]; + } + + for ( ; ch < nchan_out_buff_old; ch++ ) + { + p_output_f[ch] = NULL; + } + } + else { - free( p_output_f[ch] ); - p_output_f[ch] = NULL; + for ( ch = 0; ch < nchan_tc_jbm; ch++ ) + { + p_output_f[ch] = hTcBuffer->tc[ch]; + } + + /* when not enough audio buffers in 'hTcBuffer', allocate remaining output audio buffers here */ + for ( ; ch < nchan_out_buff; ch++ ) + { + /* note: these are intra-frame heap memories */ + if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); + } + + if ( ch < MAX_INTERN_CHANNELS ) + { + hTcBuffer->tc[ch] = p_output_f[ch]; + } + } + + for ( ; ch < nchan_out_buff_old; ch++ ) + { + p_output_f[ch] = NULL; + } } } +#endif return IVAS_ERR_OK; } -- GitLab From 6f654ffeae292175067abfffc4d1d6929944107a Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 14:00:41 +0200 Subject: [PATCH 04/61] introduce buffer *tc_buffer2 --- lib_dec/ivas_init_dec.c | 20 ++++++++++++++++---- lib_dec/ivas_jbm_dec.c | 17 +++++++++++++++++ lib_dec/ivas_stat_dec.h | 4 ++++ lib_rend/ivas_output_init.c | 34 +++++++++++++++++++++++----------- 4 files changed, 60 insertions(+), 15 deletions(-) diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 0424ced917..d273e41128 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2861,16 +2861,26 @@ void ivas_destroy_dec( ivas_limiter_close( &( st_ivas->hLimiter ) ); #ifdef FIX_1330_JBM_MEMORY - /* JBM decoding: floating-point output audio buffers are shared with bufeers from 'hTcBuffer' */ + /* floating-point output audio buffers */ if ( st_ivas->hDecoderConfig->Opt_tsm ) { - int16_t nchan_tc_jbm = max( st_ivas->hTcBuffer->nchan_transport_jbm, st_ivas->hTcBuffer->nchan_buffer_full ); - - for ( i = 0; i < nchan_tc_jbm; i++ ) + /* JBM decoding: floating-point output audio buffers are shared with buffers from 'hTcBuffer' */ + for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { st_ivas->p_output_f[i] = NULL; } } + else + { + for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) + { + if ( st_ivas->p_output_f[i] != NULL ) + { + free( st_ivas->p_output_f[i] ); + st_ivas->p_output_f[i] = NULL; + } + } + } /* Decoder configuration structure */ #endif @@ -2889,6 +2899,7 @@ void ivas_destroy_dec( st_ivas->hJbmMetadata = NULL; } +#ifndef FIX_1330_JBM_MEMORY /* floating-point output audio buffers */ for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { @@ -2899,6 +2910,7 @@ void ivas_destroy_dec( } } +#endif /* main IVAS handle */ free( st_ivas ); diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 9aeb4f38fe..b1d6488b2b 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -2166,6 +2166,10 @@ static ivas_error ivas_jbm_dec_tc_audio_allocate( } } +#ifdef FIX_1330_JBM_MEMORY + hTcBuffer->tc_buffer2 = NULL; + +#endif return IVAS_ERR_OK; } @@ -2203,6 +2207,19 @@ static void ivas_jbm_dec_tc_audio_deallocate( hTcBuffer->tc_buffer_old[ch_idx] = NULL; } } +#ifdef FIX_1330_JBM_MEMORY + + if ( hTcBuffer->tc_buffer2 != NULL ) + { + for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + //hTcBuffer->tc[ch_idx] = NULL; + } + + free( hTcBuffer->tc_buffer2 ); + hTcBuffer->tc_buffer2 = NULL; + } +#endif } return; diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 282d798e4d..2ea2ced388 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -963,6 +963,10 @@ typedef struct decoder_tc_buffer_structure int16_t num_slots; int16_t n_samples_discard; /* number of samples to discard from the beginning of the output */ +#ifdef FIX_1330_JBM_MEMORY + float *tc_buffer2; + +#endif } DECODER_TC_BUFFER, *DECODER_TC_BUFFER_HANDLE; typedef struct jbm_metadata_structure diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index be4af1b714..fb85cacb66 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -417,7 +417,14 @@ ivas_error ivas_output_buff_dec( else { /* JBM decoding: output audio buffers are shared with audio buffers from 'hTcBuffer' */ - int16_t nchan_tc_jbm; + int16_t nchan_tc_jbm, nsamp_to_allocate, n_samp_full, offset; + + if ( hTcBuffer->tc_buffer2 != NULL ) + { + free( hTcBuffer->tc_buffer2 ); + hTcBuffer->tc_buffer2 = NULL; + } + nchan_tc_jbm = max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); if ( nchan_out_buff <= nchan_tc_jbm ) @@ -440,18 +447,23 @@ ivas_error ivas_output_buff_dec( } /* when not enough audio buffers in 'hTcBuffer', allocate remaining output audio buffers here */ - for ( ; ch < nchan_out_buff; ch++ ) + + n_samp_full = ( 48000 / FRAMES_PER_SEC ); + nsamp_to_allocate = ( nchan_out_buff - nchan_tc_jbm ) * n_samp_full; + + /* note: these are intra-frame heap memories */ + if ( ( hTcBuffer->tc_buffer2 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) { - /* note: these are intra-frame heap memories */ - if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); - } + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); + } - if ( ch < MAX_INTERN_CHANNELS ) - { - hTcBuffer->tc[ch] = p_output_f[ch]; - } + set_zero( hTcBuffer->tc_buffer2, nsamp_to_allocate ); + + offset = 0; + for ( ; ch < nchan_out_buff; ch++ ) + { + p_output_f[ch] = &hTcBuffer->tc_buffer2[offset]; + offset += n_samp_full; } for ( ; ch < nchan_out_buff_old; ch++ ) -- GitLab From 8c6ce00b2f77d6df12239d39723ad119a82155a5 Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 14:04:44 +0200 Subject: [PATCH 05/61] clang-format --- lib_dec/ivas_jbm_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index b1d6488b2b..34dd4167b4 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -2213,7 +2213,7 @@ static void ivas_jbm_dec_tc_audio_deallocate( { for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) { - //hTcBuffer->tc[ch_idx] = NULL; + // hTcBuffer->tc[ch_idx] = NULL; } free( hTcBuffer->tc_buffer2 ); -- GitLab From c2616a263dc9b92f597faeecb9ab24fab644b3d0 Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 15:03:43 +0200 Subject: [PATCH 06/61] fixes --- lib_dec/ivas_init_dec.c | 5 ----- lib_dec/ivas_osba_dec.c | 4 ++++ lib_rend/ivas_output_init.c | 5 +++++ 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index d273e41128..3e2dd4a9df 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2380,11 +2380,6 @@ ivas_error ivas_init_decoder( k = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); #ifdef FIX_1330_JBM_MEMORY - for ( n = 0; n < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; n++ ) - { - st_ivas->p_output_f[n] = NULL; - } - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, 0, k, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) { return error; diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index f697fe3632..9711cb6844 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -263,7 +263,11 @@ ivas_error ivas_osba_render_sf( #else int16_t n; #endif +#ifdef FIX_1330_JBM_MEMORY + float output_ism[MAX_OUTPUT_CHANNELS][2 * L_FRAME48k]; // VE: TBV!!! +#else float output_ism[MAX_OUTPUT_CHANNELS][L_FRAME48k]; +#endif float *p_output_ism[MAX_OUTPUT_CHANNELS]; ivas_error error; diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index fb85cacb66..8ed254ac7c 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -419,6 +419,11 @@ ivas_error ivas_output_buff_dec( /* JBM decoding: output audio buffers are shared with audio buffers from 'hTcBuffer' */ int16_t nchan_tc_jbm, nsamp_to_allocate, n_samp_full, offset; + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch++ ) + { + p_output_f[ch] = NULL; + } + if ( hTcBuffer->tc_buffer2 != NULL ) { free( hTcBuffer->tc_buffer2 ); -- GitLab From cab8264e455c4b53d2f9ff23bc6bd3c8eef8d473 Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 15:53:30 +0200 Subject: [PATCH 07/61] fix --- lib_com/ivas_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index d2dde26fb5..9c5aae966e 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -199,7 +199,7 @@ void ivas_buffer_deinterleaved_to_interleaved( { int16_t ch, m; #ifdef FIX_1330_JBM_MEMORY - float buffer[MAX_TRANSPORT_CHANNELS][L_FRAME48k]; + float buffer[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS][L_FRAME48k]; for ( ch = 0; ch < n_channels; ch++ ) { -- GitLab From f520a0fc23eca579269469d82e5799a686bd430d Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 16:59:30 +0200 Subject: [PATCH 08/61] simplifications --- lib_dec/ivas_init_dec.c | 29 ++------ lib_dec/ivas_jbm_dec.c | 5 -- lib_dec/ivas_osba_dec.c | 33 ++++++--- lib_dec/ivas_stat_dec.h | 2 +- lib_rend/ivas_output_init.c | 129 ++++++++++++++++-------------------- 5 files changed, 87 insertions(+), 111 deletions(-) diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 3e2dd4a9df..1e344f88fd 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2855,30 +2855,7 @@ void ivas_destroy_dec( /* Limiter struct */ ivas_limiter_close( &( st_ivas->hLimiter ) ); -#ifdef FIX_1330_JBM_MEMORY - /* floating-point output audio buffers */ - if ( st_ivas->hDecoderConfig->Opt_tsm ) - { - /* JBM decoding: floating-point output audio buffers are shared with buffers from 'hTcBuffer' */ - for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) - { - st_ivas->p_output_f[i] = NULL; - } - } - else - { - for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) - { - if ( st_ivas->p_output_f[i] != NULL ) - { - free( st_ivas->p_output_f[i] ); - st_ivas->p_output_f[i] = NULL; - } - } - } - /* Decoder configuration structure */ -#endif if ( st_ivas->hDecoderConfig != NULL ) { free( st_ivas->hDecoderConfig ); @@ -2894,18 +2871,20 @@ void ivas_destroy_dec( st_ivas->hJbmMetadata = NULL; } -#ifndef FIX_1330_JBM_MEMORY /* floating-point output audio buffers */ for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { +#ifdef FIX_1330_JBM_MEMORY + st_ivas->p_output_f[i] = NULL; +#else if ( st_ivas->p_output_f[i] != NULL ) { free( st_ivas->p_output_f[i] ); st_ivas->p_output_f[i] = NULL; } +#endif } -#endif /* main IVAS handle */ free( st_ivas ); diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 34dd4167b4..2b4241b861 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -2211,11 +2211,6 @@ static void ivas_jbm_dec_tc_audio_deallocate( if ( hTcBuffer->tc_buffer2 != NULL ) { - for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - // hTcBuffer->tc[ch_idx] = NULL; - } - free( hTcBuffer->tc_buffer2 ); hTcBuffer->tc_buffer2 = NULL; } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index 9711cb6844..332ea51b19 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -258,54 +258,71 @@ ivas_error ivas_osba_render_sf( float *p_output[] /* o : rendered time signal */ ) { -#ifdef FIX_1330_JBM_MEMORY - int16_t n, tc_offset; -#else int16_t n; -#endif #ifdef FIX_1330_JBM_MEMORY - float output_ism[MAX_OUTPUT_CHANNELS][2 * L_FRAME48k]; // VE: TBV!!! + float output_sba[MAX_OUTPUT_CHANNELS][L_FRAME48k]; + float *p_output_sba[MAX_OUTPUT_CHANNELS]; #else float output_ism[MAX_OUTPUT_CHANNELS][L_FRAME48k]; -#endif float *p_output_ism[MAX_OUTPUT_CHANNELS]; +#endif ivas_error error; for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) { +#ifdef FIX_1330_JBM_MEMORY + p_output_sba[n] = output_sba[n]; +#else p_output_ism[n] = &output_ism[n][0]; +#endif } #ifndef FIX_1330_JBM_MEMORY if ( !st_ivas->hDecoderConfig->Opt_tsm ) { int16_t tc_offset; -#endif tc_offset = st_ivas->hTcBuffer->n_samples_rendered; for ( n = 0; n < st_ivas->nchan_ism; n++ ) { mvr2r( &p_output[n][tc_offset], &output_ism[n][tc_offset], nSamplesAsked ); } -#ifndef FIX_1330_JBM_MEMORY } #endif +#ifdef FIX_1330_JBM_MEMORY + if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailableNext, p_output_sba ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) +#endif { return error; } if ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) { +#ifdef FIX_1330_JBM_MEMORY + ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output, *nSamplesRendered ); +#else ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output_ism, *nSamplesRendered ); +#endif } for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) { if ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) { +#ifdef FIX_1330_JBM_MEMORY + v_add( p_output[n], p_output_sba[n], p_output[n], *nSamplesRendered ); +#else v_add( p_output[n], p_output_ism[n], p_output[n], *nSamplesRendered ); +#endif } +#ifdef FIX_1330_JBM_MEMORY + else + { + mvr2r( p_output_sba[n], p_output[n], *nSamplesRendered ); + } +#endif v_multc( p_output[n], 0.5f, p_output[n], *nSamplesRendered ); } diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index 2ea2ced388..8c08e8dbaa 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -964,7 +964,7 @@ typedef struct decoder_tc_buffer_structure int16_t n_samples_discard; /* number of samples to discard from the beginning of the output */ #ifdef FIX_1330_JBM_MEMORY - float *tc_buffer2; + float *tc_buffer2; /* non-scaled buffer of output audio - needed only when '*tc_buffer* is not long enough */ #endif } DECODER_TC_BUFFER, *DECODER_TC_BUFFER_HANDLE; diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 8ed254ac7c..36ef1ee6df 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -379,102 +379,87 @@ ivas_error ivas_output_buff_dec( #endif ) { - int16_t ch; - #ifdef FIX_1330_JBM_MEMORY - if ( !Opt_tsm ) + int16_t ch, nchan_tc_jbm, nsamp_to_allocate, n_samp_full, offset; + + for ( ch = 0; ch < nchan_out_buff_old; ch++ ) { - /* non-JBM decoding: allocate output audio buffers here; audio buffers from 'hTcBuffer' are set to NULL */ + p_output_f[ch] = NULL; + } -#endif - if ( nchan_out_buff > nchan_out_buff_old ) - { - for ( ch = nchan_out_buff_old; ch < nchan_out_buff; ch++ ) - { -#ifdef DEBUGGING - if ( p_output_f[ch] != NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Memory for floating-point output audio buffer is already allocated!\n" ) ); - } -#endif - /* note: these are intra-frame heap memories */ - if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); - } - } - } - else + if ( hTcBuffer->tc_buffer2 != NULL ) + { + free( hTcBuffer->tc_buffer2 ); + hTcBuffer->tc_buffer2 = NULL; + } + + nchan_tc_jbm = 0; + if ( Opt_tsm ) + { + /* JBM decoding: output audio buffers are shared with audio buffers from 'hTcBuffer->tc[]' */ + nchan_tc_jbm = max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); + } + + if ( nchan_out_buff <= nchan_tc_jbm && !Opt_tsm ) + { + for ( ch = 0; ch < nchan_out_buff; ch++ ) { - for ( ch = nchan_out_buff; ch < nchan_out_buff_old; ch++ ) - { - free( p_output_f[ch] ); - p_output_f[ch] = NULL; - } + p_output_f[ch] = hTcBuffer->tc[ch]; } -#ifdef FIX_1330_JBM_MEMORY } else { - /* JBM decoding: output audio buffers are shared with audio buffers from 'hTcBuffer' */ - int16_t nchan_tc_jbm, nsamp_to_allocate, n_samp_full, offset; - - for ( ch = 0; ch < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch++ ) + for ( ch = 0; ch < nchan_tc_jbm; ch++ ) { - p_output_f[ch] = NULL; + p_output_f[ch] = hTcBuffer->tc[ch]; } - if ( hTcBuffer->tc_buffer2 != NULL ) + /* non-JBM decoding: allocate output audio buffers + JBM decoding: when not enough audio buffers 'hTcBuffer->tc[]', allocate additional buffers */ + n_samp_full = ( 48000 / FRAMES_PER_SEC ); + nsamp_to_allocate = ( nchan_out_buff - nchan_tc_jbm ) * n_samp_full; + + /* note: these are intra-frame heap memories */ + if ( ( hTcBuffer->tc_buffer2 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) { - free( hTcBuffer->tc_buffer2 ); - hTcBuffer->tc_buffer2 = NULL; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); } - nchan_tc_jbm = max( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); + set_zero( hTcBuffer->tc_buffer2, nsamp_to_allocate ); - if ( nchan_out_buff <= nchan_tc_jbm ) + offset = 0; + for ( ; ch < nchan_out_buff; ch++ ) { - for ( ch = 0; ch < nchan_out_buff; ch++ ) - { - p_output_f[ch] = hTcBuffer->tc[ch]; - } - - for ( ; ch < nchan_out_buff_old; ch++ ) - { - p_output_f[ch] = NULL; - } + p_output_f[ch] = &hTcBuffer->tc_buffer2[offset]; + offset += n_samp_full; } - else + } +#else + int16_t ch; + + if ( nchan_out_buff > nchan_out_buff_old ) + { + for ( ch = nchan_out_buff_old; ch < nchan_out_buff; ch++ ) { - for ( ch = 0; ch < nchan_tc_jbm; ch++ ) +#ifdef DEBUGGING + if ( p_output_f[ch] != NULL ) { - p_output_f[ch] = hTcBuffer->tc[ch]; + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Memory for floating-point output audio buffer is already allocated!\n" ) ); } - - /* when not enough audio buffers in 'hTcBuffer', allocate remaining output audio buffers here */ - - n_samp_full = ( 48000 / FRAMES_PER_SEC ); - nsamp_to_allocate = ( nchan_out_buff - nchan_tc_jbm ) * n_samp_full; - +#endif /* note: these are intra-frame heap memories */ - if ( ( hTcBuffer->tc_buffer2 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) + if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); } - - set_zero( hTcBuffer->tc_buffer2, nsamp_to_allocate ); - - offset = 0; - for ( ; ch < nchan_out_buff; ch++ ) - { - p_output_f[ch] = &hTcBuffer->tc_buffer2[offset]; - offset += n_samp_full; - } - - for ( ; ch < nchan_out_buff_old; ch++ ) - { - p_output_f[ch] = NULL; - } + } + } + else + { + for ( ch = nchan_out_buff; ch < nchan_out_buff_old; ch++ ) + { + free( p_output_f[ch] ); + p_output_f[ch] = NULL; } } #endif -- GitLab From cc809c9f981e2ccf259b6293a0569bfe85459f6b Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 17:02:10 +0200 Subject: [PATCH 09/61] clang-format --- lib_rend/ivas_output_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 36ef1ee6df..c90b9e7990 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -414,8 +414,8 @@ ivas_error ivas_output_buff_dec( p_output_f[ch] = hTcBuffer->tc[ch]; } - /* non-JBM decoding: allocate output audio buffers - JBM decoding: when not enough audio buffers 'hTcBuffer->tc[]', allocate additional buffers */ + /* non-JBM decoding: allocate output audio buffers */ + /* JBM decoding: when not enough audio buffers 'hTcBuffer->tc[]', allocate additional buffers */ n_samp_full = ( 48000 / FRAMES_PER_SEC ); nsamp_to_allocate = ( nchan_out_buff - nchan_tc_jbm ) * n_samp_full; -- GitLab From d971738a71cde1c142323156de1357002d99d06b Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 17:32:14 +0200 Subject: [PATCH 10/61] fix crash + simplification --- lib_com/ivas_prot.h | 2 +- lib_dec/ivas_init_dec.c | 8 ++++++-- lib_dec/ivas_ism_dec.c | 8 +++++++- lib_dec/ivas_masa_dec.c | 8 +++++++- lib_dec/ivas_mct_dec.c | 8 +++++++- lib_dec/ivas_omasa_dec.c | 9 +++++++-- lib_dec/ivas_sba_dec.c | 9 +++++++-- lib_rend/ivas_output_init.c | 8 ++++---- 8 files changed, 46 insertions(+), 14 deletions(-) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index c4ef05e123..01bbfe7754 100755 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -308,12 +308,12 @@ ivas_error ivas_init_decoder( ivas_error ivas_output_buff_dec( float *p_output_f[], /* i/o: output audio buffers */ - const int16_t nchan_out_buff_old, /* i : previous frame number of output channels*/ #ifdef FIX_1330_JBM_MEMORY const int16_t nchan_out_buff, /* i : number of output channels */ const int16_t Opt_tsm, /* i : TSM option flag */ DECODER_TC_BUFFER_HANDLE hTcBuffer /* i : TSM buffer handle */ #else + const int16_t nchan_out_buff_old, /* i : previous frame number of output channels*/ const int16_t nchan_out_buff /* i : number of output channels */ #endif ); diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 1e344f88fd..e3e0e42d03 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1252,6 +1252,9 @@ ivas_error ivas_init_decoder( int16_t sce_id, cpe_id; int16_t numCldfbAnalyses, numCldfbSyntheses; int16_t granularity, n_channels_transport_jbm; +#ifdef FIX_1330_JBM_MEMORY + int16_t nchan_out_buff; +#endif int32_t output_Fs, ivas_total_brate; int32_t delay_ns; AUDIO_CONFIG output_config; @@ -2378,13 +2381,14 @@ ivas_error ivas_init_decoder( * Allocate floating-point output audio buffers *-----------------------------------------------------------------*/ - k = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); #ifdef FIX_1330_JBM_MEMORY - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, 0, k, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) { return error; } #else + k = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); for ( n = 0; n < k; n++ ) { /* note: these are intra-frame heap memories */ diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 64f8d15dab..6e46c4b89d 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -60,7 +60,11 @@ static ivas_error ivas_ism_bitrate_switching_dec( int16_t tc_nchan_tc_new; int16_t tc_nchan_allocate_new; int16_t tc_granularity_new; +#ifdef FIX_1330_JBM_MEMORY + int16_t nchan_out_buff; +#else int16_t nchan_out_buff, nchan_out_buff_old; +#endif nCPE_old = st_ivas->nCPE; nSCE_old = st_ivas->nSCE; @@ -70,7 +74,9 @@ static ivas_error ivas_ism_bitrate_switching_dec( st_ivas->ism_mode = last_ism_mode; ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); st_ivas->ism_mode = ism_mode; +#ifndef FIX_1330_JBM_MEMORY nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); +#endif if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nchan_ism, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 0 ) ) != IVAS_ERR_OK ) { @@ -323,7 +329,7 @@ static ivas_error ivas_ism_bitrate_switching_dec( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) { return error; } diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 3d7d78d55d..6886d550a8 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1320,7 +1320,11 @@ ivas_error ivas_masa_dec_reconfigure( Decoder_State **sts; int32_t ivas_total_brate, last_ivas_total_brate; int16_t numCldfbAnalyses_old, numCldfbSyntheses_old; +#ifdef FIX_1330_JBM_MEMORY + int16_t nchan_out_buff; +#else int16_t nchan_out_buff_old, nchan_out_buff; +#endif ivas_error error; int16_t pos_idx; int32_t ism_total_brate; @@ -1328,8 +1332,10 @@ ivas_error ivas_masa_dec_reconfigure( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; +#ifndef FIX_1330_JBM_MEMORY nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); +#endif /* Copy state to TC buffer if granularity matches and we are not in OMASA EXT rendering mode */ if ( st_ivas->hSpatParamRendCom != NULL && st_ivas->hSpatParamRendCom->slot_size == st_ivas->hTcBuffer->n_samples_granularity && st_ivas->hDecoderConfig->output_config != IVAS_AUDIO_CONFIG_EXTERNAL ) { @@ -1549,7 +1555,7 @@ ivas_error ivas_masa_dec_reconfigure( { nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); #ifdef FIX_1330_JBM_MEMORY - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) #else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) #endif diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index b495f594c7..f410a0bb0e 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -732,11 +732,17 @@ static ivas_error ivas_mc_dec_reconfig( int16_t tc_nchan_tc_new; int16_t tc_nchan_allocate_new; int16_t tc_granularity_new; +#ifdef FIX_1330_JBM_MEMORY + int16_t nchan_out_buff; +#else int16_t nchan_out_buff_old, nchan_out_buff; +#endif ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; nchan_transport_old = st_ivas->nchan_transport; +#ifndef FIX_1330_JBM_MEMORY nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); +#endif last_mc_mode = ivas_mc_mode_select( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ), st_ivas->hDecoderConfig->last_ivas_total_brate ); /* NB: this assumes that LS config remains the same between frames */ /* temporally set the current mc_mode back to the previous one to make sure the following call to @@ -1346,7 +1352,7 @@ static ivas_error ivas_mc_dec_reconfig( nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); #ifdef FIX_1330_JBM_MEMORY - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) #else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) #endif diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index d6e0060a57..628d6b4d24 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -200,7 +200,11 @@ ivas_error ivas_omasa_dec_config( int32_t ivas_total_brate, ism_total_brate, cpe_brate; ISM_MODE ism_mode_old; IVAS_FORMAT ivas_format_orig; +#ifdef FIX_1330_JBM_MEMORY + int16_t nchan_out_buff; +#else int16_t nchan_out_buff, nchan_out_buff_old; +#endif ivas_error error; RENDERER_TYPE old_renderer_type; @@ -215,8 +219,9 @@ ivas_error ivas_omasa_dec_config( ivas_format_orig = st_ivas->ivas_format; st_ivas->ivas_format = st_ivas->last_ivas_format; ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); +#ifndef FIX_1330_JBM_MEMORY nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); - +#endif st_ivas->ivas_format = ivas_format_orig; nSCE_old = st_ivas->nSCE; @@ -471,7 +476,7 @@ ivas_error ivas_omasa_dec_config( nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); #ifdef FIX_1330_JBM_MEMORY - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) #else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) #endif diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 4e00d948ee..53a0faf148 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -111,7 +111,11 @@ ivas_error ivas_sba_dec_reconfigure( int32_t ivas_total_brate; int32_t last_ivas_total_brate; int16_t num_channels, num_md_sub_frames; +#ifdef FIX_1330_JBM_MEMORY + int16_t nchan_out_buff; +#else int16_t nchan_out_buff, nchan_out_buff_old; +#endif int16_t sba_analysis_order_old_flush; DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; @@ -130,8 +134,9 @@ ivas_error ivas_sba_dec_reconfigure( * Save old SBA high-level parameters *-----------------------------------------------------------------*/ +#ifndef FIX_1330_JBM_MEMORY nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, sba_analysis_order_old_flush, last_ivas_total_brate ); - +#endif ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); nchan_hp20_old = getNumChanSynthesis( st_ivas ); @@ -592,7 +597,7 @@ ivas_error ivas_sba_dec_reconfigure( nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); #ifdef FIX_1330_JBM_MEMORY - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) #else if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) #endif diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index c90b9e7990..3ceb2eb352 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -368,21 +368,21 @@ int16_t ivas_get_nchan_buffers_dec( *-------------------------------------------------------------------*/ ivas_error ivas_output_buff_dec( - float *p_output_f[], /* i/o: output audio buffers */ - const int16_t nchan_out_buff_old, /* i : previous frame number of output channels */ + float *p_output_f[], /* i/o: output audio buffers */ #ifdef FIX_1330_JBM_MEMORY const int16_t nchan_out_buff, /* i : number of output channels */ const int16_t Opt_tsm, /* i : TSM option flag */ DECODER_TC_BUFFER_HANDLE hTcBuffer /* i : TSM buffer handle */ #else - const int16_t nchan_out_buff /* i : number of output channels */ + const int16_t nchan_out_buff_old, /* i : previous frame number of output channels */ + const int16_t nchan_out_buff /* i : number of output channels */ #endif ) { #ifdef FIX_1330_JBM_MEMORY int16_t ch, nchan_tc_jbm, nsamp_to_allocate, n_samp_full, offset; - for ( ch = 0; ch < nchan_out_buff_old; ch++ ) + for ( ch = 0; ch < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch++ ) { p_output_f[ch] = NULL; } -- GitLab From 683053faa4eed29c063f354211f80a0bd073b716 Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 18:07:53 +0200 Subject: [PATCH 11/61] remove unused variable --- lib_dec/ivas_sba_dec.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 53a0faf148..abeb19243d 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -115,8 +115,8 @@ ivas_error ivas_sba_dec_reconfigure( int16_t nchan_out_buff; #else int16_t nchan_out_buff, nchan_out_buff_old; -#endif int16_t sba_analysis_order_old_flush; +#endif DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; ISM_MODE ism_mode_old; @@ -127,7 +127,9 @@ ivas_error ivas_sba_dec_reconfigure( hDecoderConfig = st_ivas->hDecoderConfig; ivas_total_brate = hDecoderConfig->ivas_total_brate; last_ivas_total_brate = st_ivas->last_active_ivas_total_brate; +#ifndef FIX_1330_JBM_MEMORY sba_analysis_order_old_flush = st_ivas->sba_analysis_order; +#endif /*-----------------------------------------------------------------* * Set SBA high-level parameters -- GitLab From 4da816930f33329f3538398b23c5569202e44446 Mon Sep 17 00:00:00 2001 From: vaclav Date: Fri, 25 Jul 2025 20:25:35 +0200 Subject: [PATCH 12/61] update --- lib_dec/ivas_init_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index e3e0e42d03..85c5b0070a 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -2404,7 +2404,7 @@ ivas_error ivas_init_decoder( } #endif - return error; + return IVAS_ERR_OK; } -- GitLab From 28b252d4190b1848f847b6142ce55903995ea420 Mon Sep 17 00:00:00 2001 From: vaclav Date: Sat, 26 Jul 2025 14:57:40 +0200 Subject: [PATCH 13/61] fix --- lib_rend/ivas_output_init.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 3ceb2eb352..460bf182a3 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -419,13 +419,16 @@ ivas_error ivas_output_buff_dec( n_samp_full = ( 48000 / FRAMES_PER_SEC ); nsamp_to_allocate = ( nchan_out_buff - nchan_tc_jbm ) * n_samp_full; - /* note: these are intra-frame heap memories */ - if ( ( hTcBuffer->tc_buffer2 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) + if ( nsamp_to_allocate > 0 ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); - } + /* note: these are intra-frame heap memories */ + if ( ( hTcBuffer->tc_buffer2 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); + } - set_zero( hTcBuffer->tc_buffer2, nsamp_to_allocate ); + set_zero( hTcBuffer->tc_buffer2, nsamp_to_allocate ); + } offset = 0; for ( ; ch < nchan_out_buff; ch++ ) -- GitLab From f9e867d30086be890949e7f5b8caea8cac57b242 Mon Sep 17 00:00:00 2001 From: Tommy Vaillancourt Date: Wed, 30 Jul 2025 11:44:12 -0400 Subject: [PATCH 14/61] Adapting the solution depening of max position --- lib_com/swb_tbe_com.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib_com/swb_tbe_com.c b/lib_com/swb_tbe_com.c index 096fc02250..159fc21a17 100644 --- a/lib_com/swb_tbe_com.c +++ b/lib_com/swb_tbe_com.c @@ -1365,7 +1365,9 @@ void non_linearity( int16_t en_abs = 0; float v_fac = 0, ths; int16_t nframes; - +#ifdef NONBE_1328_FIX_NON_LINEARITY + float sc_factor; +#endif if ( L_frame == L_FRAME16k ) { nframes = 5; @@ -1411,7 +1413,10 @@ void non_linearity( } #ifdef NONBE_1328_FIX_NON_LINEARITY - if ( *prev_scale <= 0.0 || *prev_scale > 256.0f * scale ) + sc_factor = (float) ( 1 << ( 13 - norm_s( j + 1 ) ) ); /* Adapt the scaling factor allowed depending of max position */ + sc_factor = max( sc_factor, 2.0f ); + + if ( *prev_scale <= 0.0 || *prev_scale > sc_factor * scale ) #else if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) #endif @@ -1471,8 +1476,14 @@ void non_linearity( scale = 0.67f; } +#ifdef NONBE_1328_FIX_NON_LINEARITY + sc_factor = (float) ( 1 << ( 12 - norm_s( j - length / 2 + 1 ) ) ); /* allowed intra frame jump is smaller */ + sc_factor = max( sc_factor, 2.0f ); + if ( *prev_scale <= 0.0 || *prev_scale > sc_factor * scale ) +#else if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) +#endif { scale_step = 1.0; *prev_scale = scale; -- GitLab From 3dffc062fdb879f295ab63affd9d36f93c2219dd Mon Sep 17 00:00:00 2001 From: Tommy Vaillancourt Date: Wed, 30 Jul 2025 12:26:56 -0400 Subject: [PATCH 15/61] fix possible undefined behaviour --- lib_com/swb_tbe_com.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_com/swb_tbe_com.c b/lib_com/swb_tbe_com.c index 159fc21a17..111fc5ec7e 100644 --- a/lib_com/swb_tbe_com.c +++ b/lib_com/swb_tbe_com.c @@ -1413,7 +1413,7 @@ void non_linearity( } #ifdef NONBE_1328_FIX_NON_LINEARITY - sc_factor = (float) ( 1 << ( 13 - norm_s( j + 1 ) ) ); /* Adapt the scaling factor allowed depending of max position */ + sc_factor = (float) ( 1 << max( 13 - norm_s( j + 1 ), 0 ) ); /* Adapt the scaling factor allowed depending of max position */ sc_factor = max( sc_factor, 2.0f ); if ( *prev_scale <= 0.0 || *prev_scale > sc_factor * scale ) @@ -1477,7 +1477,7 @@ void non_linearity( } #ifdef NONBE_1328_FIX_NON_LINEARITY - sc_factor = (float) ( 1 << ( 12 - norm_s( j - length / 2 + 1 ) ) ); /* allowed intra frame jump is smaller */ + sc_factor = (float) ( 1 << max( 12 - norm_s( j - length / 2 + 1 ), 0 ) ); /* allowed intra frame jump is smaller */ sc_factor = max( sc_factor, 2.0f ); if ( *prev_scale <= 0.0 || *prev_scale > sc_factor * scale ) -- GitLab From 211eb37b75a1662272fe3ff7f8a4257723bc7268 Mon Sep 17 00:00:00 2001 From: Tommy Vaillancourt Date: Tue, 19 Aug 2025 15:05:52 -0400 Subject: [PATCH 16/61] adding a condition to differentiate EVS and IVAS --- lib_com/swb_tbe_com.c | 22 ++++++++++++++++------ lib_dec/acelp_core_dec.c | 6 +++++- lib_dec/dec_acelp_tcx_main.c | 7 ++++++- lib_enc/acelp_core_enc.c | 6 +++++- lib_enc/enc_acelp_tcx_main.c | 6 +++++- 5 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib_com/swb_tbe_com.c b/lib_com/swb_tbe_com.c index 111fc5ec7e..e8f83d3473 100644 --- a/lib_com/swb_tbe_com.c +++ b/lib_com/swb_tbe_com.c @@ -1353,6 +1353,10 @@ void non_linearity( const int16_t coder_type, /* i : Coder Type */ const float *voice_factors, /* i : Voice Factors */ const int16_t L_frame /* i : ACELP frame length */ +#ifdef NONBE_1328_FIX_NON_LINEARITY + , + const int16_t element_mode /* i : element_mode to differentiate EVS and IVAS */ +#endif ) { int16_t i, j; @@ -1413,9 +1417,12 @@ void non_linearity( } #ifdef NONBE_1328_FIX_NON_LINEARITY - sc_factor = (float) ( 1 << max( 13 - norm_s( j + 1 ), 0 ) ); /* Adapt the scaling factor allowed depending of max position */ - sc_factor = max( sc_factor, 2.0f ); - + sc_factor = 1024.0f; + if ( element_mode > EVS_MONO ) + { + sc_factor = (float) ( 1 << max( 13 - norm_s( j + 1 ), 0 ) ); /* Adapt the scaling factor allowed depending of max position */ + sc_factor = max( sc_factor, 2.0f ); + } if ( *prev_scale <= 0.0 || *prev_scale > sc_factor * scale ) #else if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) @@ -1477,9 +1484,12 @@ void non_linearity( } #ifdef NONBE_1328_FIX_NON_LINEARITY - sc_factor = (float) ( 1 << max( 12 - norm_s( j - length / 2 + 1 ), 0 ) ); /* allowed intra frame jump is smaller */ - sc_factor = max( sc_factor, 2.0f ); - + sc_factor = 1024.0f; + if ( element_mode > EVS_MONO ) + { + sc_factor = (float) ( 1 << max( 12 - norm_s( j - length / 2 + 1 ), 0 ) ); /* allowed intra frame jump is smaller */ + sc_factor = max( sc_factor, 2.0f ); + } if ( *prev_scale <= 0.0 || *prev_scale > sc_factor * scale ) #else if ( *prev_scale <= 0.0 || *prev_scale > 1024.0f * scale ) diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c index 8e3a5cff68..4cfa06115b 100644 --- a/lib_dec/acelp_core_dec.c +++ b/lib_dec/acelp_core_dec.c @@ -1414,7 +1414,11 @@ ivas_error acelp_core_dec( if ( !st->ppp_mode_dec && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { - non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); + non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame +#ifdef NONBE_1328_FIX_NON_LINEARITY + , st->element_mode +#endif + ); } if ( st->core_brate == FRAME_NO_DATA || st->core_brate == SID_2k40 ) diff --git a/lib_dec/dec_acelp_tcx_main.c b/lib_dec/dec_acelp_tcx_main.c index 4689bdb795..6baf128c00 100644 --- a/lib_dec/dec_acelp_tcx_main.c +++ b/lib_dec/dec_acelp_tcx_main.c @@ -425,7 +425,12 @@ void dec_acelp_tcx_frame( if ( st->core == ACELP_CORE && st->igf && st->con_tcx == 0 ) { - non_linearity( ptr_bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); + non_linearity( ptr_bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame +#ifdef NONBE_1328_FIX_NON_LINEARITY + , + st->element_mode +#endif + ); /* update the old BWE exe memory */ mvr2r( &old_bwe_exc[L_FRAME32k], st->hBWE_TD->old_bwe_exc, PIT16k_MAX * 2 ); diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index 535a52430e..7814bea8f3 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -695,7 +695,11 @@ ivas_error acelp_core_enc( if ( !st->Opt_SC_VBR && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { /* Apply a non linearity to the SHB excitation */ - non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); + non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame +#ifdef NONBE_1328_FIX_NON_LINEARITY + , st->element_mode +#endif + ); } if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) diff --git a/lib_enc/enc_acelp_tcx_main.c b/lib_enc/enc_acelp_tcx_main.c index 6ede9b9bf1..fdff974ab8 100644 --- a/lib_enc/enc_acelp_tcx_main.c +++ b/lib_enc/enc_acelp_tcx_main.c @@ -99,7 +99,11 @@ void enc_acelp_tcx_main( /* Apply non linearity to the SHB excitation */ if ( st->core == ACELP_CORE && st->igf ) { - non_linearity( ptr_bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame ); + non_linearity( ptr_bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame +#ifdef NONBE_1328_FIX_NON_LINEARITY + , st->element_mode +#endif + ); /* update the old_BWE_exc memory */ mvr2r( &old_bwe_exc[L_FRAME32k], st->hBWE_TD->old_bwe_exc, PIT16k_MAX * 2 ); -- GitLab From 08ceba5a26616066a241b935346897df30925dc1 Mon Sep 17 00:00:00 2001 From: Tommy Vaillancourt Date: Tue, 19 Aug 2025 15:06:17 -0400 Subject: [PATCH 17/61] adding a condition to differentiate EVS and IVAS --- lib_com/prot.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib_com/prot.h b/lib_com/prot.h index c1dd64527d..d6c80cd733 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -2653,6 +2653,10 @@ void non_linearity( const int16_t coder_type, /* i : Coder Type */ const float *voice_factors, /* i : Voice Factors */ const int16_t L_frame /* i : ACELP frame length */ +#ifdef NONBE_1328_FIX_NON_LINEARITY + , + const int16_t element_mode /* i : element_mode to differentiate EVS and IVAS */ +#endif ); void interp_code_5over2( -- GitLab From ec9968e65358f70f12a9616f48b267b2f46f38f4 Mon Sep 17 00:00:00 2001 From: Tommy Vaillancourt Date: Tue, 19 Aug 2025 15:09:38 -0400 Subject: [PATCH 18/61] fix clang --- lib_com/prot.h | 4 ++-- lib_com/swb_tbe_com.c | 2 +- lib_dec/acelp_core_dec.c | 5 +++-- lib_dec/dec_acelp_tcx_main.c | 2 +- lib_enc/acelp_core_enc.c | 3 ++- lib_enc/enc_acelp_tcx_main.c | 3 ++- 6 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lib_com/prot.h b/lib_com/prot.h index d6c80cd733..efb77f0a3f 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -2655,8 +2655,8 @@ void non_linearity( const int16_t L_frame /* i : ACELP frame length */ #ifdef NONBE_1328_FIX_NON_LINEARITY , - const int16_t element_mode /* i : element_mode to differentiate EVS and IVAS */ -#endif + const int16_t element_mode /* i : element_mode to differentiate EVS and IVAS */ +#endif ); void interp_code_5over2( diff --git a/lib_com/swb_tbe_com.c b/lib_com/swb_tbe_com.c index e8f83d3473..ed06e57636 100644 --- a/lib_com/swb_tbe_com.c +++ b/lib_com/swb_tbe_com.c @@ -1355,7 +1355,7 @@ void non_linearity( const int16_t L_frame /* i : ACELP frame length */ #ifdef NONBE_1328_FIX_NON_LINEARITY , - const int16_t element_mode /* i : element_mode to differentiate EVS and IVAS */ + const int16_t element_mode /* i : element_mode to differentiate EVS and IVAS */ #endif ) { diff --git a/lib_dec/acelp_core_dec.c b/lib_dec/acelp_core_dec.c index 4cfa06115b..d488d4479e 100644 --- a/lib_dec/acelp_core_dec.c +++ b/lib_dec/acelp_core_dec.c @@ -1414,9 +1414,10 @@ ivas_error acelp_core_dec( if ( !st->ppp_mode_dec && ( st->idchan == 0 || st->element_mode != IVAS_CPE_TD || ( st->idchan == 1 && st->element_mode == IVAS_CPE_TD && st->tdm_LRTD_flag ) ) ) { - non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame + non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame #ifdef NONBE_1328_FIX_NON_LINEARITY - , st->element_mode + , + st->element_mode #endif ); } diff --git a/lib_dec/dec_acelp_tcx_main.c b/lib_dec/dec_acelp_tcx_main.c index 6baf128c00..a591157e44 100644 --- a/lib_dec/dec_acelp_tcx_main.c +++ b/lib_dec/dec_acelp_tcx_main.c @@ -430,7 +430,7 @@ void dec_acelp_tcx_frame( , st->element_mode #endif - ); + ); /* update the old BWE exe memory */ mvr2r( &old_bwe_exc[L_FRAME32k], st->hBWE_TD->old_bwe_exc, PIT16k_MAX * 2 ); diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index 7814bea8f3..33bef3e67a 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -697,7 +697,8 @@ ivas_error acelp_core_enc( /* Apply a non linearity to the SHB excitation */ non_linearity( bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame #ifdef NONBE_1328_FIX_NON_LINEARITY - , st->element_mode + , + st->element_mode #endif ); } diff --git a/lib_enc/enc_acelp_tcx_main.c b/lib_enc/enc_acelp_tcx_main.c index fdff974ab8..8851d9be5e 100644 --- a/lib_enc/enc_acelp_tcx_main.c +++ b/lib_enc/enc_acelp_tcx_main.c @@ -101,7 +101,8 @@ void enc_acelp_tcx_main( { non_linearity( ptr_bwe_exc, bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended, L_FRAME32k, &st->hBWE_TD->bwe_non_lin_prev_scale, st->coder_type, voice_factors, st->L_frame #ifdef NONBE_1328_FIX_NON_LINEARITY - , st->element_mode + , + st->element_mode #endif ); -- GitLab From 737e30acf8d7d5702c9a5a44c9b199e9415c4dc8 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Thu, 21 Aug 2025 09:37:13 +0200 Subject: [PATCH 19/61] fix overflow in hq_lr_enc --- lib_com/options.h | 1 + lib_enc/hq_lr_enc.c | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/lib_com/options.h b/lib_com/options.h index 0000a66f49..e6081dee4f 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -164,6 +164,7 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ #define FIX_1348_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_dec(), brings floating-point code inline with FX */ +#define FIX_1369_HQ_LR_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_enc(), brings floating-point code inline with FX */ /* #################### End BE switches ################################## */ diff --git a/lib_enc/hq_lr_enc.c b/lib_enc/hq_lr_enc.c index 65b5dd4ef5..ca71fbc307 100644 --- a/lib_enc/hq_lr_enc.c +++ b/lib_enc/hq_lr_enc.c @@ -336,7 +336,15 @@ void hq_lr_enc( frac1 = L_Extract_lc( L_tmp, &exp ); /* Extract exponent of L_tmp */ L_tmp = Pow2( 30, frac1 ); exp = sub( exp, 30 ); +#ifdef FIX_1369_HQ_LR_OVERFLOW +#ifdef BASOP_NOGLOB + Ep_fx[i] = L_shl_o( L_tmp, s_max( sub( exp, 6 ), -31 ), &Overflow ); /* Q -6 */ +#else + Ep_fx[i] = L_shl( L_tmp, s_max( sub( exp, 6 ), -31 ) ); /* Q -6 */ +#endif +#else Ep_fx[i] = L_shl( L_tmp, sub( exp, 6 ) ); /* Q -6 */ +#endif Ep[i] = (float) ( Ep_fx[i] / pow( 2.0, -6 ) ); } -- GitLab From 46912cc8f9db0e70425a2b831495386a8f51c8cf Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Thu, 21 Aug 2025 09:39:10 +0200 Subject: [PATCH 20/61] formatting --- lib_enc/hq_lr_enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_enc/hq_lr_enc.c b/lib_enc/hq_lr_enc.c index ca71fbc307..be0a2254c5 100644 --- a/lib_enc/hq_lr_enc.c +++ b/lib_enc/hq_lr_enc.c @@ -343,7 +343,7 @@ void hq_lr_enc( Ep_fx[i] = L_shl( L_tmp, s_max( sub( exp, 6 ), -31 ) ); /* Q -6 */ #endif #else - Ep_fx[i] = L_shl( L_tmp, sub( exp, 6 ) ); /* Q -6 */ + Ep_fx[i] = L_shl( L_tmp, sub( exp, 6 ) ); /* Q -6 */ #endif Ep[i] = (float) ( Ep_fx[i] / pow( 2.0, -6 ) ); } -- GitLab From ef37ae487c73b49067d807562919d60d8fb586db Mon Sep 17 00:00:00 2001 From: Lauros Pajunen Date: Thu, 21 Aug 2025 12:12:38 +0300 Subject: [PATCH 21/61] Add sanity check for Euler/Quaternion angles for external orientations --- lib_com/ivas_error.h | 7 +++++++ lib_com/options.h | 1 + lib_util/rotation_file_reader.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index a2f893ed78..c6d18125e2 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -134,6 +134,9 @@ typedef enum IVAS_ERR_BITSTREAM_READER_INVALID_FORMAT, IVAS_ERR_NO_FILE_OPEN, IVAS_ERR_SAMPLING_RATE_UNKNOWN, +#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK + IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT, +#endif /*----------------------------------------* * renderer (lib_rend only) * @@ -271,6 +274,10 @@ static inline const char *ivas_error_to_string( ivas_error error_code ) return "Invalid input format"; case IVAS_ERR_INVALID_INDEX: return "Invalid index"; +#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK + case IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT: + return "Euler angles were detected in the input but only Quaternions are supported"; +#endif default: break; } diff --git a/lib_com/options.h b/lib_com/options.h index 0000a66f49..440b556325 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -164,6 +164,7 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ #define FIX_1348_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_dec(), brings floating-point code inline with FX */ +#define FIX_1370_EXTERNAL_ORIENTATION_CHECK /* Nokia: add sanity check for Euler angles for external orientations */ /* #################### End BE switches ################################## */ diff --git a/lib_util/rotation_file_reader.c b/lib_util/rotation_file_reader.c index 024b083737..bd35e5ac4a 100644 --- a/lib_util/rotation_file_reader.c +++ b/lib_util/rotation_file_reader.c @@ -183,6 +183,14 @@ ivas_error ExternalOrientationFileReading( *enableExternalOrientation = (int8_t) extOrientationFlag; *enableRotationInterpolation = (int8_t) rotInterpolationFlag; *numFramesToTargetOrientation = (int16_t) nFramesToTarget; +#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK + + /* Only Quaternion orientations are supported, raise an error if Euler angles are detected in the input */ + if ( pQuaternion->w == -3.0f ) + { + return IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT; + } +#endif return IVAS_ERR_OK; } -- GitLab From 25323eae6f4e091721e89147f8e859fddd9b40e0 Mon Sep 17 00:00:00 2001 From: vaclav Date: Thu, 21 Aug 2025 12:16:59 +0200 Subject: [PATCH 22/61] add comment --- lib_com/ivas_tools.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index 9c5aae966e..b63a923a1b 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -199,7 +199,7 @@ void ivas_buffer_deinterleaved_to_interleaved( { int16_t ch, m; #ifdef FIX_1330_JBM_MEMORY - float buffer[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS][L_FRAME48k]; + float buffer[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS][L_FRAME48k]; /* temp buffer needed when "*audio[]" and "*audio_out[]" are the same */ for ( ch = 0; ch < n_channels; ch++ ) { -- GitLab From 1d82582d17cfcdad38b4ab29db89a5c473de8672 Mon Sep 17 00:00:00 2001 From: vaclav Date: Thu, 21 Aug 2025 16:44:57 +0200 Subject: [PATCH 23/61] fix OSBA RENDERER_ROOM_IR output --- lib_dec/ivas_osba_dec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index 75afa5bd5f..a3ff4aa5df 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -316,6 +316,12 @@ ivas_error ivas_osba_render_sf( v_add( p_output[n], p_output_ism[n], p_output[n], *nSamplesRendered ); #endif } +#ifdef FIX_1330_JBM_MEMORY + else + { + mvr2r( p_output_sba[n], p_output[n], *nSamplesRendered ); + } +#endif } return IVAS_ERR_OK; -- GitLab From fe4355d9de5d3928652e96460d27c2faaff75a8c Mon Sep 17 00:00:00 2001 From: vaclav Date: Thu, 21 Aug 2025 18:05:42 +0200 Subject: [PATCH 24/61] issue 1372: Fix OSBA object-editing in BINAURAL_ROOM_IR; under FIX_1372_OSBA_OBJECT_EDITING --- lib_com/options.h | 1 + lib_dec/ivas_sba_dec.c | 6 ++++++ lib_dec/ivas_spar_decoder.c | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/lib_com/options.h b/lib_com/options.h index e6081dee4f..9c0c1dc928 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -165,6 +165,7 @@ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ #define FIX_1348_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_dec(), brings floating-point code inline with FX */ #define FIX_1369_HQ_LR_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_enc(), brings floating-point code inline with FX */ +#define FIX_1372_OSBA_OBJECT_EDITING /* VA: issue 1372: Fix OSBA object-editing in BINAURAL_ROOM_IR */ /* #################### End BE switches ################################## */ diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 8ddc7f0406..5407b058a3 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -712,6 +712,12 @@ ivas_error ivas_sba_dec_render( { nchan_out = max( nchan_internal, st_ivas->hDecoderConfig->nchan_out - st_ivas->nchan_ism ); } +#ifdef FIX_1372_OSBA_OBJECT_EDITING + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + nchan_out = BINAURAL_CHANNELS; + } +#endif } nchan_out = min( nchan_out, ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ) ); diff --git a/lib_dec/ivas_spar_decoder.c b/lib_dec/ivas_spar_decoder.c index 41319e9fe2..2a575c6177 100644 --- a/lib_dec/ivas_spar_decoder.c +++ b/lib_dec/ivas_spar_decoder.c @@ -1406,7 +1406,11 @@ void ivas_spar_dec_upmixer_sf( p_tc[i] = st_ivas->hTcBuffer->tc[i + nchan_ism] + slot_idx_start * slot_size; } +#ifdef FIX_1372_OSBA_OBJECT_EDITING + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) +#else if ( st_ivas->ivas_format == SBA_ISM_FORMAT && st_ivas->ism_mode == ISM_SBA_MODE_DISC && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) +#endif { for ( i = 0; i < nchan_ism; i++ ) { -- GitLab From 47cfc0a17b596efdccfeb64499505a3820c737f8 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Fri, 22 Aug 2025 10:50:15 +0300 Subject: [PATCH 25/61] Fix issue 1371 by not touching earlyPartEneCorrection when FASTCONV path is used. --- lib_com/options.h | 1 + lib_dec/ivas_binRenderer_internal.c | 8 +++++++- lib_rend/ivas_reverb.c | 14 ++++++++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/lib_com/options.h b/lib_com/options.h index e6081dee4f..b1f68c2f4d 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -165,6 +165,7 @@ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ #define FIX_1348_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_dec(), brings floating-point code inline with FX */ #define FIX_1369_HQ_LR_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_enc(), brings floating-point code inline with FX */ +#define FIX_1371_EARLY_PART_INIT_FASTCONV /* Nokia: fix uninitialized variable in FASTCONV path of binaural reverb init */ /* #################### End BE switches ################################## */ diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 4b2c4c7d07..7cd919233e 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -1007,7 +1007,13 @@ ivas_error ivas_binRenderer_open( st_ivas->hDecoderConfig->output_Fs, st_ivas->hHrtfFastConv->fastconvReverberationTimes, st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections, - hBinRenderer->earlyPartEneCorrection ) ) != IVAS_ERR_OK ) +#ifdef FIX_1371_EARLY_PART_INIT_FASTCONV + NULL +#else + hBinRenderer->earlyPartEneCorrection +#endif + ) ) != IVAS_ERR_OK ) + { return error; } diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 2811a3c4d0..097057cffb 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1924,13 +1924,27 @@ ivas_error ivas_binaural_reverb_init( energyModifier = ( adjustedRevTime - revTimes[bin] ) / adjustedRevTime; /* Adjust early and late energies, by moving late energy to early energy */ +#ifdef FIX_1371_EARLY_PART_INIT_FASTCONV + if ( earlyEne != NULL ) + { + adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; + } +#else adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; +#endif adjustedLateEne = revEne[bin] * ( 1.0f - energyModifier ); /* Store adjusted room effect parameters to be used in reverb processing */ revTimes[bin] = adjustedRevTime; revEne[bin] = adjustedLateEne; +#ifdef FIX_1371_EARLY_PART_INIT_FASTCONV + if ( earlyEne != NULL ) + { + earlyEne[bin] = adjustedEarlyEne; + } +#else earlyEne[bin] = adjustedEarlyEne; +#endif } } -- GitLab From c53bfa5597ae0921af37a36f9b57d19a3d791852 Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Fri, 22 Aug 2025 11:31:11 +0300 Subject: [PATCH 26/61] Satisfy Windows warning --- lib_rend/ivas_reverb.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 097057cffb..3119f5fdf9 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1928,6 +1928,7 @@ ivas_error ivas_binaural_reverb_init( if ( earlyEne != NULL ) { adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; + earlyEne[bin] = adjustedEarlyEne; /* Store already here */ } #else adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; @@ -1937,12 +1938,7 @@ ivas_error ivas_binaural_reverb_init( /* Store adjusted room effect parameters to be used in reverb processing */ revTimes[bin] = adjustedRevTime; revEne[bin] = adjustedLateEne; -#ifdef FIX_1371_EARLY_PART_INIT_FASTCONV - if ( earlyEne != NULL ) - { - earlyEne[bin] = adjustedEarlyEne; - } -#else +#ifndef FIX_1371_EARLY_PART_INIT_FASTCONV earlyEne[bin] = adjustedEarlyEne; #endif } -- GitLab From 08124d95343d2c49980360f7c9d36b90a8ae5106 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 22 Aug 2025 10:49:19 +0200 Subject: [PATCH 27/61] IVAS_rend: Do not allow empty strings as valid ISM metadata file paths --- apps/renderer.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index 8ef8a988bd..06ee8087aa 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -564,12 +564,19 @@ static void setupWithSingleFormatInput( positionProvider->numObjects = args.inConfig.numAudioObjects; for ( int16_t i = 0; i < positionProvider->numObjects; ++i ) { - /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string is empty or contains "NULL" */ + /* Check if path to metadata file was given */ + if ( isEmptyString( args.inMetadataFilePaths[i] ) ) + { + fprintf( stderr, "No metadata file was given for ISM input %d\n", i ); + exit( -1 ); + } + + /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string contains "NULL" */ char charBuf[FILENAME_MAX]; strncpy( charBuf, args.inMetadataFilePaths[i], min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1 ); charBuf[min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1] = '\0'; to_upper( charBuf ); - if ( isEmptyString( args.inMetadataFilePaths[i] ) || strncmp( charBuf, "NULL", 4 ) == 0 ) + if ( strncmp( charBuf, "NULL", 4 ) == 0 ) { continue; } @@ -2595,7 +2602,7 @@ static CmdlnArgs defaultArgs( args.outConfig.outSetupCustom.num_lfe = 0; args.inConfig.ambisonicsBuses->audioConfig = IVAS_AUDIO_CONFIG_INVALID; - for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS + RENDERER_MAX_MASA_INPUTS; ++i ) { clearString( args.inMetadataFilePaths[i] ); } -- GitLab From 0e880a070258979d80691fa90527ae61cbdcdc3c Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 22 Aug 2025 13:35:42 +0200 Subject: [PATCH 28/61] Wrap changes in preprocessor switch --- apps/renderer.c | 12 ++++++++++++ lib_com/options.h | 1 + 2 files changed, 13 insertions(+) diff --git a/apps/renderer.c b/apps/renderer.c index 06ee8087aa..deda26e8ae 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -564,6 +564,7 @@ static void setupWithSingleFormatInput( positionProvider->numObjects = args.inConfig.numAudioObjects; for ( int16_t i = 0; i < positionProvider->numObjects; ++i ) { +#ifdef FIX_1376_MISSING_ISM_METADATA /* Check if path to metadata file was given */ if ( isEmptyString( args.inMetadataFilePaths[i] ) ) { @@ -572,11 +573,18 @@ static void setupWithSingleFormatInput( } /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string contains "NULL" */ +#else + /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string is empty or contains "NULL" */ +#endif char charBuf[FILENAME_MAX]; strncpy( charBuf, args.inMetadataFilePaths[i], min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1 ); charBuf[min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1] = '\0'; to_upper( charBuf ); +#ifdef FIX_1376_MISSING_ISM_METADATA if ( strncmp( charBuf, "NULL", 4 ) == 0 ) +#else + if ( isEmptyString( args.inMetadataFilePaths[i] ) || strncmp( charBuf, "NULL", 4 ) == 0 ) +#endif { continue; } @@ -2602,7 +2610,11 @@ static CmdlnArgs defaultArgs( args.outConfig.outSetupCustom.num_lfe = 0; args.inConfig.ambisonicsBuses->audioConfig = IVAS_AUDIO_CONFIG_INVALID; +#ifdef FIX_1376_MISSING_ISM_METADATA for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS + RENDERER_MAX_MASA_INPUTS; ++i ) +#else + for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) +#endif { clearString( args.inMetadataFilePaths[i] ); } diff --git a/lib_com/options.h b/lib_com/options.h index e6081dee4f..32c2722e32 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -165,6 +165,7 @@ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ #define FIX_1348_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_dec(), brings floating-point code inline with FX */ #define FIX_1369_HQ_LR_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_enc(), brings floating-point code inline with FX */ +#define FIX_1376_MISSING_ISM_METADATA /* FhG: IVAS_rend: throw error if there exists an ISM input without a corresponding metadata file path */ /* #################### End BE switches ################################## */ -- GitLab From b712e08bf08167611441e67c7c4d4beabea8fd63 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Fri, 22 Aug 2025 14:07:15 +0200 Subject: [PATCH 29/61] Fix renderer tests that relied on default ISM metadata when no -im was given --- tests/renderer/utils.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 29ee307fad..657b1aa616 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -273,6 +273,13 @@ def run_renderer( if in_meta_files is None and in_fmt in format_to_metadata_files: in_meta_files = format_to_metadata_files[in_fmt] + # If metadata not given with ISM input, use default NULL + if in_meta_files is None and isinstance(in_fmt, str) and "ism" in in_fmt.lower(): + match = re.search(r"ism(\d)", in_fmt.lower()) + assert match is not None + num_obj = int(match[1]) + in_meta_files = ["NULL"] * num_obj + if out_file is None: out_file_stem = f"{in_name}_to_{out_name}{trj_name}{non_diegetic_pan}{refrot_name}{refvec_name}{refveclev_name}{config_name}{framing_name}{hrtf_file_name}{name_extension}{aeid_name}_{sr}.wav" out_file = str(output_path_base.joinpath(out_file_stem)) -- GitLab From 40adfdf9fd2358c6daa5f80c1b1dc65b22657715 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 26 Aug 2025 07:56:32 +0200 Subject: [PATCH 30/61] Add scripts/merge_logs.py --- scripts/merge_logs.py | 60 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 scripts/merge_logs.py diff --git a/scripts/merge_logs.py b/scripts/merge_logs.py new file mode 100644 index 0000000000..7e332e4f52 --- /dev/null +++ b/scripts/merge_logs.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python3 + +import argparse +from pathlib import Path +import pandas as pd + +def main(logs_dir, output_filename, measure): + + input_path = Path(logs_dir) + logs = [f for f in input_path.iterdir() if f.is_dir()] + + # Build dict of scores + logdict = {} + for log in logs: + date = log.name + logdict[date] = {} + for logfile in log.glob('*.csv'): + tmp = logfile.name.split('-') + job = '-'.join(tmp[3:-4]) + #sha = tmp[-1].split('.')[0] + #logdict[date]["sha"] = sha # Maybe we want to store the SHA too somehow. + data = pd.read_csv(logfile, usecols=["testcase", measure]) + logdict[date][job] = {} + + for testcase, value in zip(data["testcase"], data[measure]): + logdict[date][job][testcase] = value + + # Restructure dict + csv_rows = [] + for date, jobs in logdict.items(): + for job, testcases in jobs.items(): + for testcase, value in testcases.items(): + csv_rows.append((job, testcase, date, value)) + + result = pd.DataFrame(csv_rows, columns=["job","testcase","date","value"]) + result = result.pivot(index=['job', 'testcase'], columns='date', values="value").reset_index() + result.to_csv(output_filename, sep=';', index=False) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="logs dir") + parser.add_argument( + "logs_dir", + type=str, + help="Logs dir, e.g. logs", + ) + parser.add_argument( + "output_filename", + type=str, + help="Filename of the combined csv file. e.g mld.csv", + ) + parser.add_argument( + "--measure", + type=str, + help="Measure for summary, one of MLD MIN_SSNR MAX_ABS_DIFF MIN_ODG, (default: MLD)", + default="MLD", + ) + + args = parser.parse_args() + + main(args.logs_dir, args.output_filename, args.measure) \ No newline at end of file -- GitLab From e1f4bca8470f0c991a5ebc664101b1194fe486ad Mon Sep 17 00:00:00 2001 From: Tapani Pihlajakuja Date: Tue, 26 Aug 2025 11:19:19 +0300 Subject: [PATCH 31/61] Minor change in check placement to align better with BASOP code. --- lib_util/rotation_file_reader.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib_util/rotation_file_reader.c b/lib_util/rotation_file_reader.c index bd35e5ac4a..6c62290b00 100644 --- a/lib_util/rotation_file_reader.c +++ b/lib_util/rotation_file_reader.c @@ -174,6 +174,14 @@ ivas_error ExternalOrientationFileReading( } ( externalOrientationReader->frameCounter )++; +#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK + + /* Only Quaternion orientations are supported, raise an error if Euler angles are detected in the input */ + if ( w == -3.0f ) + { + return IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT; + } +#endif pQuaternion->w = w; pQuaternion->x = x; @@ -183,14 +191,6 @@ ivas_error ExternalOrientationFileReading( *enableExternalOrientation = (int8_t) extOrientationFlag; *enableRotationInterpolation = (int8_t) rotInterpolationFlag; *numFramesToTargetOrientation = (int16_t) nFramesToTarget; -#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK - - /* Only Quaternion orientations are supported, raise an error if Euler angles are detected in the input */ - if ( pQuaternion->w == -3.0f ) - { - return IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT; - } -#endif return IVAS_ERR_OK; } -- GitLab From 84db99db4af25d8f9c3a856287746d67e80f627f Mon Sep 17 00:00:00 2001 From: vaclav Date: Tue, 26 Aug 2025 14:09:08 +0200 Subject: [PATCH 32/61] acceptance of switches --- apps/renderer.c | 17 +---- lib_com/options.h | 6 +- lib_dec/hq_lr_dec.c | 6 +- lib_dec/ivas_svd_dec.c | 162 +---------------------------------------- lib_enc/hq_lr_enc.c | 6 +- 5 files changed, 7 insertions(+), 190 deletions(-) diff --git a/apps/renderer.c b/apps/renderer.c index deda26e8ae..26c4b349d2 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -564,7 +564,6 @@ static void setupWithSingleFormatInput( positionProvider->numObjects = args.inConfig.numAudioObjects; for ( int16_t i = 0; i < positionProvider->numObjects; ++i ) { -#ifdef FIX_1376_MISSING_ISM_METADATA /* Check if path to metadata file was given */ if ( isEmptyString( args.inMetadataFilePaths[i] ) ) { @@ -573,18 +572,11 @@ static void setupWithSingleFormatInput( } /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string contains "NULL" */ -#else - /* It is allowed on CLI to have no metadata for an ISM input - skip opening if string is empty or contains "NULL" */ -#endif char charBuf[FILENAME_MAX]; strncpy( charBuf, args.inMetadataFilePaths[i], min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1 ); charBuf[min( FILENAME_MAX, RENDERER_MAX_CLI_ARG_LENGTH ) - 1] = '\0'; to_upper( charBuf ); -#ifdef FIX_1376_MISSING_ISM_METADATA if ( strncmp( charBuf, "NULL", 4 ) == 0 ) -#else - if ( isEmptyString( args.inMetadataFilePaths[i] ) || strncmp( charBuf, "NULL", 4 ) == 0 ) -#endif { continue; } @@ -2592,6 +2584,7 @@ static CmdlnArgs defaultArgs( const char *executableName ) { CmdlnArgs args; + int16_t i; strncpy( args.executableName, executableName, RENDERER_MAX_CLI_ARG_LENGTH ); clearString( args.inputFilePath ); @@ -2610,11 +2603,7 @@ static CmdlnArgs defaultArgs( args.outConfig.outSetupCustom.num_lfe = 0; args.inConfig.ambisonicsBuses->audioConfig = IVAS_AUDIO_CONFIG_INVALID; -#ifdef FIX_1376_MISSING_ISM_METADATA - for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS + RENDERER_MAX_MASA_INPUTS; ++i ) -#else - for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) -#endif + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS + RENDERER_MAX_MASA_INPUTS; ++i ) { clearString( args.inMetadataFilePaths[i] ); } @@ -2651,7 +2640,7 @@ static CmdlnArgs defaultArgs( args.render_framesize = IVAS_RENDER_FRAMESIZE_20MS; args.syncMdDelay = 0; - for ( int32_t i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) + for ( i = 0; i < RENDERER_MAX_ISM_INPUTS; ++i ) { args.directivityPatternId[i] = 65535; } diff --git a/lib_com/options.h b/lib_com/options.h index 42f17f9081..48b031d604 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -163,9 +163,6 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ -#define FIX_1348_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_dec(), brings floating-point code inline with FX */ -#define FIX_1369_HQ_LR_OVERFLOW /* FhG: fix BASOP overflow in hq_lr_enc(), brings floating-point code inline with FX */ -#define FIX_1376_MISSING_ISM_METADATA /* FhG: IVAS_rend: throw error if there exists an ISM input without a corresponding metadata file path */ #define FIX_1330_JBM_MEMORY /* VA: issue 1330: memory savings in the JBM decoder */ #define FIX_1370_EXTERNAL_ORIENTATION_CHECK /* Nokia: add sanity check for Euler angles for external orientations */ #define FIX_1371_EARLY_PART_INIT_FASTCONV /* Nokia: fix uninitialized variable in FASTCONV path of binaural reverb init */ @@ -179,9 +176,8 @@ #define NONBE_1244_FIX_SWB_BWE_MEMORY /* VA: issue 1244: fix to SWB BWE memory in case of switching from FB coding - pending a review by Huawei */ #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 NONBE_SVD_OPTIMIZATION - #define NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0 */ + /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/hq_lr_dec.c b/lib_dec/hq_lr_dec.c index b2febc4956..e50bd127d7 100644 --- a/lib_dec/hq_lr_dec.c +++ b/lib_dec/hq_lr_dec.c @@ -262,14 +262,10 @@ void hq_lr_dec( frac1 = L_Extract_lc( L_tmp, &exp ); /* Extract exponent of L_tmp */ L_tmp = Pow2( 30, frac1 ); exp = sub( exp, 30 ); -#ifdef FIX_1348_OVERFLOW #ifdef BASOP_NOGLOB Ep_fx[i] = L_shl_o( L_tmp, s_max( sub( exp, 6 ), -31 ), &Overflow ); /* Q -6 */ #else - Ep_fx[i] = L_shl( L_tmp, s_max( sub( exp, 6 ), -31 ) ); /* Q -6 */ -#endif -#else - Ep_fx[i] = L_shl( L_tmp, sub( exp, 6 ) ); /* Q -6 */ + Ep_fx[i] = L_shl( L_tmp, s_max( sub( exp, 6 ), -31 ) ); /* Q -6 */ #endif Ep[i] = (float) ( Ep_fx[i] / pow( 2.0, -6 ) ); } diff --git a/lib_dec/ivas_svd_dec.c b/lib_dec/ivas_svd_dec.c index 8957c8e060..12a98e87e9 100644 --- a/lib_dec/ivas_svd_dec.c +++ b/lib_dec/ivas_svd_dec.c @@ -60,17 +60,9 @@ static float GivensRotation( const float x, const float z ); -#ifdef NONBE_SVD_OPTIMIZATION static void biDiagonalReductionLeft( float singularVectors[][MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const int16_t currChannel, float *g ); -#else -static void biDiagonalReductionLeft( float singularVectors[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const int16_t currChannel, float *sig_x, float *g ); -#endif -#ifdef NONBE_SVD_OPTIMIZATION static void biDiagonalReductionRight( float singularVectors[][MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const int16_t currChannel, float *g ); -#else -static void biDiagonalReductionRight( float singularVectors[][MAX_OUTPUT_CHANNELS], float secDiag[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC, const int16_t currChannel, float *sig_x, float *g ); -#endif static void singularVectorsAccumulationLeft( float singularVectors_Left[][MAX_OUTPUT_CHANNELS], float singularValues[MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, const int16_t nChannelsC ); @@ -497,27 +489,16 @@ static void HouseholderReduction( float *eps_x ) { int16_t nCh; -#ifdef NONBE_SVD_OPTIMIZATION float g_left = 0.0f; float g_right = 0.0f; -#else - float sig_x = 0.0f; - float g = 0.0f; -#endif - /* Bidiagonal Reduction for every channel */ for ( nCh = 0; nCh < nChannelsC; nCh++ ) /* nChannelsC */ { -#ifdef NONBE_SVD_OPTIMIZATION secDiag[nCh] = g_right; /* from the previous channel */ biDiagonalReductionLeft( singularVectors_Left, nChannelsL, nChannelsC, nCh, &g_left ); singularValues[nCh] = g_left; biDiagonalReductionRight( singularVectors_Left, nChannelsL, nChannelsC, nCh, &g_right ); -#else - biDiagonalReductionLeft( singularVectors_Left, singularValues, secDiag, nChannelsL, nChannelsC, nCh, &sig_x, &g ); - biDiagonalReductionRight( singularVectors_Left, secDiag, nChannelsL, nChannelsC, nCh, &sig_x, &g ); -#endif *eps_x = max( *eps_x, ( fabsf( singularValues[nCh] ) + fabsf( secDiag[nCh] ) ) ); } @@ -535,7 +516,7 @@ static void HouseholderReduction( * * *-------------------------------------------------------------------------*/ -#ifdef NONBE_SVD_OPTIMIZATION + static void biDiagonalReductionLeft( float singularVectors[][MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, @@ -553,7 +534,6 @@ static void biDiagonalReductionLeft( { norm_x = 0.0f; - for ( jCh = currChannel; jCh < nChannelsL; jCh++ ) /* nChannelsL */ { norm_x += ( singularVectors[jCh][currChannel] * singularVectors[jCh][currChannel] ); @@ -586,78 +566,7 @@ static void biDiagonalReductionLeft( return; } -#else -static void biDiagonalReductionLeft( - float singularVectors[][MAX_OUTPUT_CHANNELS], - float singularValues[MAX_OUTPUT_CHANNELS], - float secDiag[MAX_OUTPUT_CHANNELS], - const int16_t nChannelsL, - const int16_t nChannelsC, - const int16_t currChannel, - float *sig_x, - float *g ) -{ - int16_t iCh, jCh, idx; - float norm_x, f, r; - - secDiag[currChannel] = ( *sig_x ) * ( *g ); - - /* Setting values to 0 */ - ( *sig_x ) = 0.0f; - ( *g ) = 0.0f; - - if ( currChannel < nChannelsL ) /* i <= m */ - { - idx = currChannel; - - for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */ - { - ( *sig_x ) += fabsf( singularVectors[jCh][currChannel] ); - } - if ( ( *sig_x ) ) /*(fabsf(*sig_x) > EPSILON * fabsf(*sig_x)) { */ - { - norm_x = 0.0f; - - for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */ - { - singularVectors[jCh][currChannel] = ( singularVectors[jCh][currChannel] / maxWithSign( ( *sig_x ) ) ); - norm_x += ( singularVectors[jCh][currChannel] * singularVectors[jCh][currChannel] ); - } - ( *g ) = -( singularVectors[currChannel][idx] >= 0 ? 1 : ( -1 ) ) * sqrtf( norm_x ); - r = ( *g ) * singularVectors[currChannel][idx] - norm_x; - singularVectors[currChannel][idx] = ( singularVectors[currChannel][idx] - ( *g ) ); - - for ( iCh = currChannel + 1; iCh < nChannelsC; iCh++ ) /* nChannelsC */ - { - norm_x = 0.0f; - for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */ - { - norm_x += ( singularVectors[jCh][currChannel] * singularVectors[jCh][iCh] ); - } - - f = norm_x / maxWithSign( r ); - - - for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */ - { - singularVectors[jCh][iCh] += ( f * singularVectors[jCh][currChannel] ); - } - } - - - for ( jCh = idx; jCh < nChannelsL; jCh++ ) /* nChannelsL */ - { - singularVectors[jCh][currChannel] = ( singularVectors[jCh][currChannel] * ( *sig_x ) ); - } - } - - singularValues[currChannel] = ( ( *sig_x ) * ( *g ) ); - } - - return; -} -#endif /*------------------------------------------------------------------------- * biDiagonalReductionRight() @@ -665,7 +574,6 @@ static void biDiagonalReductionLeft( * *-------------------------------------------------------------------------*/ -#ifdef NONBE_SVD_OPTIMIZATION static void biDiagonalReductionRight( float singularVectors[][MAX_OUTPUT_CHANNELS], const int16_t nChannelsL, @@ -714,75 +622,7 @@ static void biDiagonalReductionRight( return; } -#else -static void biDiagonalReductionRight( - float singularVectors[][MAX_OUTPUT_CHANNELS], - float secDiag[MAX_OUTPUT_CHANNELS], - const int16_t nChannelsL, - const int16_t nChannelsC, - const int16_t currChannel, - float *sig_x, - float *g ) -{ - int16_t iCh, jCh, idx; - - float norm_x, r; - /* Setting values to 0 */ - ( *sig_x ) = 0.0f; - ( *g ) = 0.0f; - - if ( currChannel < nChannelsL && currChannel != ( nChannelsC - 1 ) ) /* i <=m && i !=n */ - { - idx = currChannel + 1; - - for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */ - { - ( *sig_x ) += fabsf( singularVectors[currChannel][jCh] ); - } - - if ( ( *sig_x ) ) /*(fabsf(*sig_x) > EPSILON * fabsf(*sig_x)) { */ - { - norm_x = 0.0f; - - for ( jCh = idx; jCh < nChannelsC; jCh++ ) /*nChannelsC */ - { - singularVectors[currChannel][jCh] = ( singularVectors[currChannel][jCh] / maxWithSign( ( *sig_x ) ) ); - norm_x += ( singularVectors[currChannel][jCh] * singularVectors[currChannel][jCh] ); - } - ( *g ) = -( singularVectors[currChannel][idx] >= 0 ? 1 : ( -1 ) ) * sqrtf( norm_x ); - r = ( *g ) * singularVectors[currChannel][idx] - norm_x; - singularVectors[currChannel][idx] = ( singularVectors[currChannel][idx] - ( *g ) ); - - for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */ - { - secDiag[jCh] = singularVectors[currChannel][jCh] / maxWithSign( r ); - } - - for ( iCh = currChannel + 1; iCh < nChannelsL; iCh++ ) /* nChannelsL */ - { - norm_x = 0.0f; - for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */ - { - norm_x += ( singularVectors[iCh][jCh] * singularVectors[currChannel][jCh] ); - } - - for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */ - { - singularVectors[iCh][jCh] += ( norm_x * secDiag[jCh] ); - } - } - - for ( jCh = idx; jCh < nChannelsC; jCh++ ) /* nChannelsC */ - { - singularVectors[currChannel][jCh] = ( singularVectors[currChannel][jCh] * ( *sig_x ) ); - } - } - } - - return; -} -#endif /*------------------------------------------------------------------------- * singularVectorsAccumulationLeft() diff --git a/lib_enc/hq_lr_enc.c b/lib_enc/hq_lr_enc.c index be0a2254c5..13637fdbd2 100644 --- a/lib_enc/hq_lr_enc.c +++ b/lib_enc/hq_lr_enc.c @@ -336,14 +336,10 @@ void hq_lr_enc( frac1 = L_Extract_lc( L_tmp, &exp ); /* Extract exponent of L_tmp */ L_tmp = Pow2( 30, frac1 ); exp = sub( exp, 30 ); -#ifdef FIX_1369_HQ_LR_OVERFLOW #ifdef BASOP_NOGLOB Ep_fx[i] = L_shl_o( L_tmp, s_max( sub( exp, 6 ), -31 ), &Overflow ); /* Q -6 */ #else - Ep_fx[i] = L_shl( L_tmp, s_max( sub( exp, 6 ), -31 ) ); /* Q -6 */ -#endif -#else - Ep_fx[i] = L_shl( L_tmp, sub( exp, 6 ) ); /* Q -6 */ + Ep_fx[i] = L_shl( L_tmp, s_max( sub( exp, 6 ), -31 ) ); /* Q -6 */ #endif Ep[i] = (float) ( Ep_fx[i] / pow( 2.0, -6 ) ); } -- GitLab From 610756a20429b2e9660b9c9219a0b6364e0f0cf1 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Tue, 26 Aug 2025 11:05:47 +0200 Subject: [PATCH 33/61] Manually revert commit that caused assert to be triggered in JBM during rate switching --- lib_com/options.h | 1 + lib_dec/ivas_ism_dec.c | 21 +++++++++++++++++++++ lib_dec/ivas_masa_dec.c | 19 +++++++++++++++++++ lib_dec/ivas_mct_dec.c | 21 +++++++++++++++++++++ lib_dec/ivas_sba_dec.c | 22 ++++++++++++++++++++++ lib_dec/lib_dec.c | 2 ++ 6 files changed, 86 insertions(+) diff --git a/lib_com/options.h b/lib_com/options.h index 42f17f9081..90f3950615 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -182,6 +182,7 @@ #define NONBE_SVD_OPTIMIZATION #define NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0 */ +#define NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING /* FhG: Fix assert being hit in JBM code during rate switching */ /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 6e46c4b89d..000b5f6ca5 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -128,6 +128,25 @@ static ivas_error ivas_ism_bitrate_switching_dec( mvs2s( st_ivas->hSpatParamRendCom->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } +#ifdef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING + /* JBM: when granularity goes down (e.g. Discrete ISM with TD Obj Renderer -> ParamISM with binaural fastconv + render what still fits in the new granularity */ + tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, RENDERER_DISABLE, st_ivas->hDecoderConfig->output_Fs ); + + if ( tc_granularity_new < st_ivas->hTcBuffer->n_samples_granularity ) + { + /* flush already done in IVAS_DEC_ReadFormat() */ + } + /* JBM: when granularity goes up set samples to discard at the beginning of the frame */ + else if ( tc_granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_set_discard_samples( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + +#endif if ( st_ivas->ism_mode != last_ism_mode ) { /* EFAP handle */ @@ -295,7 +314,9 @@ static ivas_error ivas_ism_bitrate_switching_dec( tc_nchan_tc_new = ivas_jbm_dec_get_num_tc_channels( st_ivas ); tc_nchan_allocate_new = tc_nchan_tc_new; tc_nchan_full_new = tc_nchan_tc_new; +#ifndef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, RENDERER_DISABLE, st_ivas->hDecoderConfig->output_Fs ); +#endif if ( st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type != RENDERER_MONO_DOWNMIX && st_ivas->renderer_type != RENDERER_DISABLE && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC && st_ivas->renderer_type != RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 6886d550a8..5f4634c383 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1509,6 +1509,25 @@ ivas_error ivas_masa_dec_reconfigure( tc_nchan_to_allocate = 2 * BINAURAL_CHANNELS; } } +#ifdef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING + if ( st_ivas->ivas_format == MASA_ISM_FORMAT && st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC && st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + if ( n_samples_granularity > st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_set_discard_samples( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC && st_ivas->ism_mode != ISM_MASA_MODE_DISC ) + { + if ( n_samples_granularity < st_ivas->hTcBuffer->n_samples_granularity ) + { + /* flush already done in IVAS_DEC_ReadFormat() */ + } + } +#endif } else if ( st_ivas->nchan_transport == 1 && ( st_ivas->renderer_type == RENDERER_DIRAC && st_ivas->hDirACRend->synthesisConf == DIRAC_SYNTHESIS_GAIN_SHD ) ) { diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 84bf52456d..d7639e8ce5 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -795,6 +795,25 @@ static ivas_error ivas_mc_dec_reconfig( } } +#ifdef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING + /* JBM: when granularity goes down (e.g. MCT with CREND -> ParamMC with binaural fastconv + render what still fits in the new granularity */ + tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, RENDERER_DISABLE, st_ivas->hDecoderConfig->output_Fs ); + + if ( tc_granularity_new < st_ivas->hTcBuffer->n_samples_granularity ) + { + /* flush already done in IVAS_DEC_ReadFormat() */ + } + /* JBM: when granularity goes up set samples to discard at the beginning of the frame */ + else if ( tc_granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_set_discard_samples( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + } + +#endif if ( st_ivas->mc_mode == MC_MODE_MCT ) { st_ivas->nchan_transport = ivas_mc_ls_setup_get_num_channels( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ) ); @@ -1303,7 +1322,9 @@ static ivas_error ivas_mc_dec_reconfig( tc_nchan_tc_new = ivas_jbm_dec_get_num_tc_channels( st_ivas ); tc_nchan_allocate_new = tc_nchan_tc_new; tc_nchan_full_new = tc_nchan_tc_new; +#ifndef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, RENDERER_DISABLE, st_ivas->hDecoderConfig->output_Fs ); +#endif if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index abeb19243d..a11fb37d54 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -173,6 +173,27 @@ ivas_error ivas_sba_dec_reconfigure( /* determine new granularity */ granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, ivas_renderer_secondary_select( st_ivas ), st_ivas->hDecoderConfig->output_Fs ); +#ifdef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING + /* flush renderer on granularity change form 5ms to 1.25ms, again only possible for binaural rendering */ + if ( granularity_new < st_ivas->hTcBuffer->n_samples_granularity ) + { + /* flush already done in IVAS_DEC_ReadFormat() */ + } + else if ( granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) + { + if ( ( error = ivas_jbm_dec_set_discard_samples( st_ivas ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* make sure the changed number of slots in the last subframe is not lost in the following steps */ + if ( st_ivas->hSpatParamRendCom != NULL ) + { + st_ivas->hSpatParamRendCom->subframe_nbslots[st_ivas->hSpatParamRendCom->nb_subframes - 1] = st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; + } + st_ivas->hSpar->subframe_nbslots[st_ivas->hSpar->nb_subframes - 1] = st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; + } +#else if ( granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) { /* make sure the changed number of slots in the last subframe is not lost in the following steps */ @@ -182,6 +203,7 @@ ivas_error ivas_sba_dec_reconfigure( } st_ivas->hSpar->subframe_nbslots[st_ivas->hSpar->nb_subframes - 1] = st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; } +#endif } /* save old */ diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 0e04971fc3..41feeafec2 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -1080,6 +1080,7 @@ ivas_error IVAS_DEC_ReadFormat( return error; } } +#ifndef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING /* when granularity goes up, discard samples at the beginning of the frame */ else if ( tc_granularity_new > st_ivas->hTcBuffer->n_samples_granularity ) { @@ -1088,6 +1089,7 @@ ivas_error IVAS_DEC_ReadFormat( return error; } } +#endif } } -- GitLab From 3d52d0a9fae5e760532cee1e6b6180660d1c3ea5 Mon Sep 17 00:00:00 2001 From: Kacper Sagnowski Date: Tue, 26 Aug 2025 15:26:00 +0200 Subject: [PATCH 34/61] Fix formatting --- lib_dec/ivas_mct_dec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index d7639e8ce5..2ea644dbd2 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -796,8 +796,8 @@ static ivas_error ivas_mc_dec_reconfig( } #ifdef NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING - /* JBM: when granularity goes down (e.g. MCT with CREND -> ParamMC with binaural fastconv - render what still fits in the new granularity */ + /* JBM: when granularity goes down (e.g. MCT with CREND -> ParamMC with binaural fastconv + render what still fits in the new granularity */ tc_granularity_new = ivas_jbm_dec_get_render_granularity( st_ivas->renderer_type, RENDERER_DISABLE, st_ivas->hDecoderConfig->output_Fs ); if ( tc_granularity_new < st_ivas->hTcBuffer->n_samples_granularity ) -- GitLab From 329d9f555d996fb9d0c4aab94df13fa0f03f7d59 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 1 Sep 2025 16:25:13 +0200 Subject: [PATCH 35/61] Add output of scripts to reproduce critical cases --- scripts/find_regressions_from_logs.py | 237 ++++++++++++++++++++++++++ scripts/merge_logs.py | 60 ------- 2 files changed, 237 insertions(+), 60 deletions(-) create mode 100644 scripts/find_regressions_from_logs.py delete mode 100644 scripts/merge_logs.py diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py new file mode 100644 index 0000000000..522d144436 --- /dev/null +++ b/scripts/find_regressions_from_logs.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python3 + +import argparse +from pathlib import Path +import pandas as pd + +REPRODUCE_REGRESSION_SCRIPT_TMPL = """ +#!/bin/bash -x + +SCRIPTS_DIR=/usr/local/scripts +LTV_DIR=/usr/local/ltv + +MIN_DATE={min_date} +MIN_SHA={min_sha} +LEVEL_SCALING={level_scaling} +TESTCASE="{testcase}" + +REF_ENC1={REF_ENC1} +REF_DEC1={REF_DEC1} +DUT_ENC1={DUT_ENC1} +DUT_DEC1={DUT_DEC1} + +REF_ENC2={REF_ENC2} +REF_DEC2={REF_DEC2} +DUT_ENC2={DUT_ENC2} +DUT_DEC2={DUT_DEC2} + +# Obtain executables from past reference +git checkout 'ivas-float-update@{$MIN_DATE 22:00:00}' +make clean +make -j +mv IVAS_cod IVAS_cod_ref_1 +mv IVAS_dec IVAS_dec_ref_1 +mv IVAS_rend IVAS_rend_ref_1 + +git checkout $MIN_SHA +make clean +make -j +mv IVAS_cod IVAS_cod_1 +mv IVAS_dec IVAS_dec_1 +mv IVAS_rend IVAS_rend_1 + +# Obtain latest executables +git checkout ivas-float-update +git pull +make clean +make -j +mv IVAS_cod IVAS_cod_ref_2 +mv IVAS_dec IVAS_dec_ref_2 +mv IVAS_rend IVAS_rend_ref_2 + +git checkout main +git pull +make clean +make -j +mv IVAS_cod IVAS_cod_2 +mv IVAS_dec IVAS_dec_2 +mv IVAS_rend IVAS_rend_2 + +# Get fresh copy of scripts, tests and ci +cp -r $SCRIPTS_DIR/{scripts,tests,ci,pytest.ini} . +python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm # Should not be needed since only supported testcases should be input + +# Get LTVs +cp $LTV_DIR/* scripts/testv + +# Apply level scaling +tests/scale_pcm.py ./scripts/testv/ "$LEVEL_SCALING" + +# Run tests +cp IVAS_rend_ref_1 IVAS_rend_ref +cp IVAS_rend_1 IVAS_rend +python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg + +# Store results from first run +mkdir tests1 +cp -r tests/ref tests/dut tests1 +cp -r tests/renderer/ref tests/renderer/cut tests1 + +cp IVAS_rend_ref_2 IVAS_rend_ref +cp IVAS_rend_2 IVAS_rend +python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg + +""" + + +def main(logs_dir, output_filename, measure): + + input_path = Path(logs_dir) + logs = [f for f in input_path.iterdir() if f.is_dir()] + + # Build dict of scores + formatdict = {} + sha = {} + logdict = {} + for log in logs: + date = log.name + logdict[date] = {} + formatdict[date] = {} + for logfile in log.glob("*.csv"): + tmp = logfile.name.split("-") + job = "-".join(tmp[3:-4]) + sha[date] = tmp[-1].split(".")[0] + data = pd.read_csv(logfile, usecols=["testcase", measure, "format"]) + logdict[date][job] = {} + formatdict[date][job] = {} + + for testcase, value, format in zip( + data["testcase"], data[measure], data["format"] + ): + formatdict[date][job][testcase] = format + logdict[date][job][testcase] = value + + # Restructure dict + csv_rows = [] + formats = [] + for date, jobs in logdict.items(): + for job, testcases in jobs.items(): + for testcase, value in testcases.items(): + csv_rows.append((job, testcase, date, value)) + formats.append((job, testcase, date, formatdict[date][job][testcase])) + + result = pd.DataFrame(csv_rows, columns=["job", "testcase", "date", "value"]) + result = result.pivot( + index=["job", "testcase"], columns="date", values="value" + ).reset_index() + + f = pd.DataFrame(formats, columns=["job", "testcase", "date", "format"]) + f = f.pivot( + index=["job", "testcase"], columns="date", values="format" + ).reset_index() + + values = result.iloc[:, 2:] + last_date = values.columns[-1] + + result.insert(2, "format", f[last_date]) + result.insert(3, "min_date", values.idxmin(axis=1)) + result.insert(4, "min_sha", result["min_date"].map(sha)) + result.insert(5, "curr_value", values[last_date]) + result.insert(6, "min_value", values.min(axis=1)) + result.insert(7, "diff", result["curr_value"] - result["min_value"]) + result.insert(8, "ratio", result["curr_value"] / result["min_value"]) + result.loc[result["min_value"] == 0, "ratio"] = ( + 1 # Set ratio to 1 for denominator 0 + ) + + result["min_sha"] = "'" + result["min_sha"] + + result.to_csv(output_filename, sep=";", index=False) + + critical = result.iloc[:, 0:9] + formats = list(set(critical["format"])) + critical3 = pd.DataFrame() + + for format in formats: + top3 = ( + critical[critical["format"] == format] + .sort_values(by="ratio", ascending=False) + .head(3) + ) + critical3 = pd.concat([critical3, top3], ignore_index=True) + + critical3.to_csv("critical3.csv", sep=";", index=False) + + row_counter = 1 + for row in critical3.row(): + + # Find level + level_scaling = 1.0 + if "lev+10" in row["job"]: + level_scaling = 3.162 + if "lev-10" in row["job"]: + level_scaling = 0.3162 + + # Find executables setup + REF_ENC1 = "IVAS_cod_ref_1" + REF_DEC1 = "IVAS_dec_ref_1" + DUT_ENC1 = "IVAS_ref_1" + DUT_DEC1 = "IVAS_dec_1" + REF_ENC2 = "IVAS_cod_ref_2" + REF_DEC2 = "IVAS_dec_ref_2" + DUT_ENC2 = "IVAS_ref_2" + DUT_DEC2 = "IVAS_dec_2" + + if "dec" in row["job"]: + DUT_ENC1 = "IVAS_cod_ref_1" + DUT_ENC2 = "IVAS_cod_ref_2" + if "enc" in row["job"]: + DUT_DEC1 = "IVAS_dec_ref_1" + DUT_DEC2 = "IVAS_dec_ref_2" + + script_content = REPRODUCE_REGRESSION_SCRIPT_TMPL.format( + min_date=row["min_date"], + min_sha=row["min_sha"][1:], + LEVEL_SCALING={level_scaling}, + TESTCASE=row["testcase"][1:], + REF_ENC1 = REF_ENC1, + REF_DEC1 = REF_DEC1, + DUT_ENC1 = DUT_ENC1, + DUT_DEC1 = DUT_DEC1, + REF_ENC2 = REF_ENC2, + REF_DEC2 = REF_DEC2, + DUT_ENC2 = DUT_ENC2, + DUT_DEC2 = DUT_DEC2, + ) + + script_filename = f"regression_{row_counter:02d}.bash" + with open(script_filename, "w") as f: + f.write(script_content) + + row_counter = row_counter + 1 + + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="logs dir") + parser.add_argument( + "logs_dir", + type=str, + help="Logs dir, e.g. logs", + ) + parser.add_argument( + "output_filename", + type=str, + help="Filename of the combined csv file. e.g mld.csv", + ) + parser.add_argument( + "--measure", + type=str, + help="Measure for summary, one of MLD MIN_SSNR MAX_ABS_DIFF MIN_ODG, (default: MLD)", + default="MLD", + ) + + args = parser.parse_args() + + main(args.logs_dir, args.output_filename, args.measure) diff --git a/scripts/merge_logs.py b/scripts/merge_logs.py deleted file mode 100644 index 7e332e4f52..0000000000 --- a/scripts/merge_logs.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -from pathlib import Path -import pandas as pd - -def main(logs_dir, output_filename, measure): - - input_path = Path(logs_dir) - logs = [f for f in input_path.iterdir() if f.is_dir()] - - # Build dict of scores - logdict = {} - for log in logs: - date = log.name - logdict[date] = {} - for logfile in log.glob('*.csv'): - tmp = logfile.name.split('-') - job = '-'.join(tmp[3:-4]) - #sha = tmp[-1].split('.')[0] - #logdict[date]["sha"] = sha # Maybe we want to store the SHA too somehow. - data = pd.read_csv(logfile, usecols=["testcase", measure]) - logdict[date][job] = {} - - for testcase, value in zip(data["testcase"], data[measure]): - logdict[date][job][testcase] = value - - # Restructure dict - csv_rows = [] - for date, jobs in logdict.items(): - for job, testcases in jobs.items(): - for testcase, value in testcases.items(): - csv_rows.append((job, testcase, date, value)) - - result = pd.DataFrame(csv_rows, columns=["job","testcase","date","value"]) - result = result.pivot(index=['job', 'testcase'], columns='date', values="value").reset_index() - result.to_csv(output_filename, sep=';', index=False) - -if __name__ == "__main__": - parser = argparse.ArgumentParser(description="logs dir") - parser.add_argument( - "logs_dir", - type=str, - help="Logs dir, e.g. logs", - ) - parser.add_argument( - "output_filename", - type=str, - help="Filename of the combined csv file. e.g mld.csv", - ) - parser.add_argument( - "--measure", - type=str, - help="Measure for summary, one of MLD MIN_SSNR MAX_ABS_DIFF MIN_ODG, (default: MLD)", - default="MLD", - ) - - args = parser.parse_args() - - main(args.logs_dir, args.output_filename, args.measure) \ No newline at end of file -- GitLab From bdd825dc29b3561a46c170cb133898fd4de3772f Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 1 Sep 2025 16:44:16 +0200 Subject: [PATCH 36/61] Fix to regression script generation --- scripts/find_regressions_from_logs.py | 33 ++++++++++++--------------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 522d144436..55ff526687 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -26,7 +26,7 @@ DUT_ENC2={DUT_ENC2} DUT_DEC2={DUT_DEC2} # Obtain executables from past reference -git checkout 'ivas-float-update@{$MIN_DATE 22:00:00}' +git checkout 'ivas-float-update@{{$MIN_DATE 22:00:00}}' make clean make -j mv IVAS_cod IVAS_cod_ref_1 @@ -58,7 +58,7 @@ mv IVAS_dec IVAS_dec_2 mv IVAS_rend IVAS_rend_2 # Get fresh copy of scripts, tests and ci -cp -r $SCRIPTS_DIR/{scripts,tests,ci,pytest.ini} . +cp -r $SCRIPTS_DIR/{{scripts,tests,ci,pytest.ini}} . python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm # Should not be needed since only supported testcases should be input # Get LTVs @@ -164,8 +164,7 @@ def main(logs_dir, output_filename, measure): critical3.to_csv("critical3.csv", sep=";", index=False) - row_counter = 1 - for row in critical3.row(): + for row_counter, row in critical3.iterrows(): # Find level level_scaling = 1.0 @@ -173,7 +172,7 @@ def main(logs_dir, output_filename, measure): level_scaling = 3.162 if "lev-10" in row["job"]: level_scaling = 0.3162 - + # Find executables setup REF_ENC1 = "IVAS_cod_ref_1" REF_DEC1 = "IVAS_dec_ref_1" @@ -190,28 +189,26 @@ def main(logs_dir, output_filename, measure): if "enc" in row["job"]: DUT_DEC1 = "IVAS_dec_ref_1" DUT_DEC2 = "IVAS_dec_ref_2" - + script_content = REPRODUCE_REGRESSION_SCRIPT_TMPL.format( min_date=row["min_date"], min_sha=row["min_sha"][1:], - LEVEL_SCALING={level_scaling}, - TESTCASE=row["testcase"][1:], - REF_ENC1 = REF_ENC1, - REF_DEC1 = REF_DEC1, - DUT_ENC1 = DUT_ENC1, - DUT_DEC1 = DUT_DEC1, - REF_ENC2 = REF_ENC2, - REF_DEC2 = REF_DEC2, - DUT_ENC2 = DUT_ENC2, - DUT_DEC2 = DUT_DEC2, + level_scaling=level_scaling, + testcase=row["testcase"][1:], + REF_ENC1=REF_ENC1, + REF_DEC1=REF_DEC1, + DUT_ENC1=DUT_ENC1, + DUT_DEC1=DUT_DEC1, + REF_ENC2=REF_ENC2, + REF_DEC2=REF_DEC2, + DUT_ENC2=DUT_ENC2, + DUT_DEC2=DUT_DEC2, ) script_filename = f"regression_{row_counter:02d}.bash" with open(script_filename, "w") as f: f.write(script_content) - row_counter = row_counter + 1 - if __name__ == "__main__": parser = argparse.ArgumentParser(description="logs dir") -- GitLab From a93771a9f6f7d2af25b001c93fb190214a1f5a2e Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 1 Sep 2025 16:53:09 +0200 Subject: [PATCH 37/61] Correct testcase printout and row numbering in find_regressions_from_logs.py --- scripts/find_regressions_from_logs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 55ff526687..4479998bdc 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -194,7 +194,7 @@ def main(logs_dir, output_filename, measure): min_date=row["min_date"], min_sha=row["min_sha"][1:], level_scaling=level_scaling, - testcase=row["testcase"][1:], + testcase=row["testcase"], REF_ENC1=REF_ENC1, REF_DEC1=REF_DEC1, DUT_ENC1=DUT_ENC1, @@ -205,7 +205,7 @@ def main(logs_dir, output_filename, measure): DUT_DEC2=DUT_DEC2, ) - script_filename = f"regression_{row_counter:02d}.bash" + script_filename = f"regression_{row_counter+2:03d}.bash" with open(script_filename, "w") as f: f.write(script_content) -- GitLab From 88b91a23c57085489e6d3f1c407e75ee561fa82d Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 1 Sep 2025 18:27:00 +0200 Subject: [PATCH 38/61] Fix for renderer tests, and checkout by date --- scripts/find_regressions_from_logs.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 4479998bdc..4fba13730e 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -26,7 +26,7 @@ DUT_ENC2={DUT_ENC2} DUT_DEC2={DUT_DEC2} # Obtain executables from past reference -git checkout 'ivas-float-update@{{$MIN_DATE 22:00:00}}' +git checkout `git rev-list -1 --before="$MIN_DATE 22:00:00" ivas-float-update` make clean make -j mv IVAS_cod IVAS_cod_ref_1 @@ -70,8 +70,8 @@ tests/scale_pcm.py ./scripts/testv/ "$LEVEL_SCALING" # Run tests cp IVAS_rend_ref_1 IVAS_rend_ref cp IVAS_rend_1 IVAS_rend -python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg +python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg # Store results from first run mkdir tests1 @@ -80,8 +80,8 @@ cp -r tests/renderer/ref tests/renderer/cut tests1 cp IVAS_rend_ref_2 IVAS_rend_ref cp IVAS_rend_2 IVAS_rend -python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg +python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg """ -- GitLab From f4acb5fd143fbdd7faaa8bd252eb8d721a41581f Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 1 Sep 2025 19:08:52 +0200 Subject: [PATCH 39/61] Fix for encoder executables in scripts/find_regressions_from_logs.py --- scripts/find_regressions_from_logs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 4fba13730e..d40a5cbef0 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -176,11 +176,11 @@ def main(logs_dir, output_filename, measure): # Find executables setup REF_ENC1 = "IVAS_cod_ref_1" REF_DEC1 = "IVAS_dec_ref_1" - DUT_ENC1 = "IVAS_ref_1" + DUT_ENC1 = "IVAS_cod_1" DUT_DEC1 = "IVAS_dec_1" REF_ENC2 = "IVAS_cod_ref_2" REF_DEC2 = "IVAS_dec_ref_2" - DUT_ENC2 = "IVAS_ref_2" + DUT_ENC2 = "IVAS_cod_2" DUT_DEC2 = "IVAS_dec_2" if "dec" in row["job"]: -- GitLab From 9eea37e7f5075724766e70e1e336f3f6ba2871e5 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 2 Sep 2025 08:30:14 +0200 Subject: [PATCH 40/61] Add cleanup of tests folder --- scripts/find_regressions_from_logs.py | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index d40a5cbef0..9c25412c01 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -59,6 +59,7 @@ mv IVAS_rend IVAS_rend_2 # Get fresh copy of scripts, tests and ci cp -r $SCRIPTS_DIR/{{scripts,tests,ci,pytest.ini}} . +rm -rf tests/ref tests/dut tests/renderer/ref tests/renderer/cut python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm # Should not be needed since only supported testcases should be input # Get LTVs -- GitLab From 3cdfceefe41bc4e4b0cf0c9a9fdfcff93ceeffd2 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 2 Sep 2025 08:51:44 +0200 Subject: [PATCH 41/61] Fixes in find_regression script --- scripts/find_regressions_from_logs.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 9c25412c01..ba473c859e 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -72,17 +72,20 @@ tests/scale_pcm.py ./scripts/testv/ "$LEVEL_SCALING" cp IVAS_rend_ref_1 IVAS_rend_ref cp IVAS_rend_1 IVAS_rend python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg --junit-xml=report1.xml +python3 scripts/parse_xml_report.py report1.xml report1.csv # Store results from first run -mkdir tests1 +mkdir -p tests1/renderer cp -r tests/ref tests/dut tests1 -cp -r tests/renderer/ref tests/renderer/cut tests1 +cp -r tests/renderer/ref tests1/renderer +cp -r tests/renderer/cut tests1/renderer cp IVAS_rend_ref_2 IVAS_rend_ref cp IVAS_rend_2 IVAS_rend python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg --junit-xml=report2.xml +python3 scripts/parse_xml_report.py report2.xml report2.csv """ -- GitLab From 87858638d0c36ce89ccd6c0afd79e23dc1aa2071 Mon Sep 17 00:00:00 2001 From: vaclav Date: Tue, 2 Sep 2025 10:09:36 +0200 Subject: [PATCH 42/61] revert debugging --- lib_dec/ivas_sba_dec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index 3e0357b528..37107ae2df 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -744,7 +744,7 @@ ivas_error ivas_sba_dec_render( { nchan_out = max( nchan_internal, st_ivas->hDecoderConfig->nchan_out - st_ivas->nchan_ism ); } -#ifdef FIX_1372_OSBA_OBJECT_EDITINGaa +#ifdef FIX_1372_OSBA_OBJECT_EDITING else if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { nchan_out = BINAURAL_CHANNELS; -- GitLab From 24907da6def58496830852c97b50109037fdb502 Mon Sep 17 00:00:00 2001 From: vaclav Date: Tue, 2 Sep 2025 10:37:09 +0200 Subject: [PATCH 43/61] change one self-test condition --- scripts/config/self_test.prm | 4 ++-- scripts/config/self_test_ltv.prm | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/config/self_test.prm b/scripts/config/self_test.prm index 0bd9fbb2d8..28254ed77c 100644 --- a/scripts/config/self_test.prm +++ b/scripts/config/self_test.prm @@ -2018,9 +2018,9 @@ networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit ../IVAS_cod -ism_masa 2 2 testv/stvISM1.csv testv/stvISM2.csv testv/stv2MASA2TC48c.met ../scripts/switchPaths/sw_13k2_512k_2fr_start_48k_omasatechs_2ism.bin 48 testv/stvOMASA_2ISM_2MASA2TC48c.wav bit ../IVAS_dec -obj_edit ../scripts/object_edit/combined_edit.txt BINAURAL 48 bit testv/stvOMASA_2ISM_2MASA2TC48c.wav_BINAURAL_sw_48-48_OE.tst -// OSBA 3OA 4ISM at 256 kbps, 48kHz in, 48kHz out, BINAURAL out, object editing, DISC +// OSBA 3OA 4ISM at 256 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM_IR out, object editing, DISC ../IVAS_cod -ism_sba 4 3 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv testv/stvISM4.csv 256000 48 testv/stvOSBA_4ISM_3OA48c.wav bit -../IVAS_dec -obj_edit ../scripts/object_edit/combined_edit.txt BINAURAL 48 bit testv/stvOSBA_4ISM_3OA48c.wav_BINAURAL_256000_48-48_OE.tst +../IVAS_dec -obj_edit ../scripts/object_edit/combined_edit.txt BINAURAL_ROOM_IR 48 bit testv/stvOSBA_4ISM_3OA48c.wav_BINAURAL_ROOM_IR_256000_48-48_OE.tst // OSBA 2OA 3ISM at 128 kbps, 48kHz in, 48kHz out, FOA out, object editing, JBM Prof 5, DISC ../IVAS_cod -ism_sba 3 2 testv/stvISM1.csv testv/stvISM2.csv testv/stvISM3.csv 128000 48 testv/stvOSBA_3ISM_2OA48c.wav bit diff --git a/scripts/config/self_test_ltv.prm b/scripts/config/self_test_ltv.prm index 64890d7157..5db028d50a 100644 --- a/scripts/config/self_test_ltv.prm +++ b/scripts/config/self_test_ltv.prm @@ -2014,9 +2014,9 @@ networkSimulator_g192 ../scripts/dly_error_profiles/dly_error_profile_5.dat bit ../IVAS_cod -ism_masa 2 2 testv/ltv48_OMASA_2ISM_2TC_ISM1.csv testv/ltv48_OMASA_2ISM_2TC_ISM2.csv testv/ltv48_OMASA_2ISM_2TC.met ../scripts/switchPaths/sw_13k2_512k_2fr_start_48k_omasatechs_2ism.bin 48 testv/ltv48_OMASA_2ISM_2TC.wav bit ../IVAS_dec -obj_edit ../scripts/object_edit/combined_edit.txt BINAURAL 48 bit testv/ltv48_OMASA_2ISM_2TC.wav_BINAURAL_sw_48-48_OE.tst -// OSBA 3OA 4ISM at 256 kbps, 48kHz in, 48kHz out, BINAURAL out, object editing, DISC +// OSBA 3OA 4ISM at 256 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM_IR out, object editing, DISC ../IVAS_cod -ism_sba 4 3 testv/ltv48_OSBA_4ISM_HOA3_ISM1.csv testv/ltv48_OSBA_4ISM_HOA3_ISM2.csv testv/ltv48_OSBA_4ISM_HOA3_ISM3.csv testv/ltv48_OSBA_4ISM_HOA3_ISM4.csv 256000 48 testv/ltv48_OSBA_4ISM_HOA3.wav bit -../IVAS_dec -obj_edit ../scripts/object_edit/combined_edit.txt BINAURAL 48 bit testv/ltv48_OSBA_4ISM_HOA3.wav_BINAURAL_256000_48-48_OE.tst +../IVAS_dec -obj_edit ../scripts/object_edit/combined_edit.txt BINAURAL_ROOM_IR 48 bit testv/ltv48_OSBA_4ISM_HOA3.wav_BINAURAL_ROOM_IR_256000_48-48_OE.tst // OSBA 2OA 3ISM at 128 kbps, 48kHz in, 48kHz out, FOA out, object editing, JBM Prof 5, DISC ../IVAS_cod -ism_sba 3 2 testv/ltv48_OSBA_3ISM_HOA2_ISM1.csv testv/ltv48_OSBA_3ISM_HOA2_ISM2.csv testv/ltv48_OSBA_3ISM_HOA2_ISM3.csv 128000 48 testv/ltv48_OSBA_3ISM_HOA2.wav bit -- GitLab From f8822c0db283b086564b161ff70301ae0100c838 Mon Sep 17 00:00:00 2001 From: vaclav Date: Tue, 2 Sep 2025 10:54:27 +0200 Subject: [PATCH 44/61] accept FIX_1371_EARLY_PART_INIT_FASTCONV, FIX_1370_EXTERNAL_ORIENTATION_CHECK, and FIX_1330_JBM_MEMORY --- lib_com/ivas_error.h | 4 -- lib_com/ivas_prot.h | 10 ---- lib_com/ivas_tools.c | 6 -- lib_com/options.h | 4 +- lib_dec/ivas_binRenderer_internal.c | 8 +-- lib_dec/ivas_init_dec.c | 27 --------- lib_dec/ivas_ism_dec.c | 20 ------- lib_dec/ivas_ism_renderer.c | 47 ++------------- lib_dec/ivas_jbm_dec.c | 16 ------ lib_dec/ivas_masa_dec.c | 12 ---- lib_dec/ivas_mct_dec.c | 11 ---- lib_dec/ivas_omasa_dec.c | 88 ++++++++--------------------- lib_dec/ivas_osba_dec.c | 35 ------------ lib_dec/ivas_sba_dec.c | 15 ----- lib_dec/ivas_stat_dec.h | 2 - lib_rend/ivas_output_init.c | 37 +----------- lib_rend/ivas_reverb.c | 8 +-- lib_util/rotation_file_reader.c | 2 - 18 files changed, 34 insertions(+), 318 deletions(-) diff --git a/lib_com/ivas_error.h b/lib_com/ivas_error.h index c6d18125e2..563b10e391 100644 --- a/lib_com/ivas_error.h +++ b/lib_com/ivas_error.h @@ -134,9 +134,7 @@ typedef enum IVAS_ERR_BITSTREAM_READER_INVALID_FORMAT, IVAS_ERR_NO_FILE_OPEN, IVAS_ERR_SAMPLING_RATE_UNKNOWN, -#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT, -#endif /*----------------------------------------* * renderer (lib_rend only) * @@ -274,10 +272,8 @@ static inline const char *ivas_error_to_string( ivas_error error_code ) return "Invalid input format"; case IVAS_ERR_INVALID_INDEX: return "Invalid index"; -#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK case IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT: return "Euler angles were detected in the input but only Quaternions are supported"; -#endif default: break; } diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 01bbfe7754..895cb3ac07 100755 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -308,14 +308,9 @@ ivas_error ivas_init_decoder( ivas_error ivas_output_buff_dec( float *p_output_f[], /* i/o: output audio buffers */ -#ifdef FIX_1330_JBM_MEMORY const int16_t nchan_out_buff, /* i : number of output channels */ const int16_t Opt_tsm, /* i : TSM option flag */ DECODER_TC_BUFFER_HANDLE hTcBuffer /* i : TSM buffer handle */ -#else - const int16_t nchan_out_buff_old, /* i : previous frame number of output channels*/ - const int16_t nchan_out_buff /* i : number of output channels */ -#endif ); ivas_error stereo_dmx_evs_init_encoder( @@ -5829,12 +5824,7 @@ void ivas_omasa_separate_object_render_jbm( const uint16_t nSamplesRendered, /* i : number of samples rendered */ float input_f[][L_FRAME48k], /* i : separated object signal */ float *output_f[], /* o : rendered time signal */ -#ifdef FIX_1330_JBM_MEMORY const int16_t subframes_rendered /* i : number of subframes rendered */ -#else - const int16_t subframes_rendered, /* i : number of subframes rendered */ - const int16_t slots_rendered /* i : number of CLDFB slots rendered */ -#endif ); void ivas_omasa_encode_masa_to_total( diff --git a/lib_com/ivas_tools.c b/lib_com/ivas_tools.c index b63a923a1b..e7ada0a343 100644 --- a/lib_com/ivas_tools.c +++ b/lib_com/ivas_tools.c @@ -198,24 +198,18 @@ void ivas_buffer_deinterleaved_to_interleaved( ) { int16_t ch, m; -#ifdef FIX_1330_JBM_MEMORY float buffer[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS][L_FRAME48k]; /* temp buffer needed when "*audio[]" and "*audio_out[]" are the same */ for ( ch = 0; ch < n_channels; ch++ ) { mvr2r( audio[ch], buffer[ch], frame_length ); } -#endif for ( ch = 0; ch < n_channels; ch++ ) { for ( m = 0; m < frame_length; m++ ) { -#ifdef FIX_1330_JBM_MEMORY audio_out[m * n_channels + ch] = buffer[ch][m]; -#else - audio_out[m * n_channels + ch] = audio[ch][m]; -#endif } } diff --git a/lib_com/options.h b/lib_com/options.h index 121cdad56d..62cb9b3b78 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -163,9 +163,6 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ -#define FIX_1330_JBM_MEMORY /* VA: issue 1330: memory savings in the JBM decoder */ -#define FIX_1370_EXTERNAL_ORIENTATION_CHECK /* Nokia: add sanity check for Euler angles for external orientations */ -#define FIX_1371_EARLY_PART_INIT_FASTCONV /* Nokia: fix uninitialized variable in FASTCONV path of binaural reverb init */ /* #################### End BE switches ################################## */ @@ -178,6 +175,7 @@ #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 NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0 */ #define NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING /* FhG: Fix assert being hit in JBM code during rate switching */ + /* ##################### End NON-BE switches ########################### */ /* ################## End DEVELOPMENT switches ######################### */ diff --git a/lib_dec/ivas_binRenderer_internal.c b/lib_dec/ivas_binRenderer_internal.c index 7cd919233e..8cda55017c 100644 --- a/lib_dec/ivas_binRenderer_internal.c +++ b/lib_dec/ivas_binRenderer_internal.c @@ -999,6 +999,7 @@ ivas_error ivas_binRenderer_open( if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM || ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV && st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ) { pRoomAcoustics = ( st_ivas->hOutSetup.output_config == IVAS_AUDIO_CONFIG_BINAURAL_ROOM_REVERB ) ? &( st_ivas->hRenderConfig->roomAcoustics ) : NULL; + if ( ( error = ivas_binaural_reverb_init( &( hBinRenderer->hReverb ), st_ivas->hHrtfStatistics, hBinRenderer->conv_band, @@ -1007,12 +1008,7 @@ ivas_error ivas_binRenderer_open( st_ivas->hDecoderConfig->output_Fs, st_ivas->hHrtfFastConv->fastconvReverberationTimes, st_ivas->hHrtfFastConv->fastconvReverberationEneCorrections, -#ifdef FIX_1371_EARLY_PART_INIT_FASTCONV - NULL -#else - hBinRenderer->earlyPartEneCorrection -#endif - ) ) != IVAS_ERR_OK ) + NULL ) ) != IVAS_ERR_OK ) { return error; diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c index 5989880c14..2c2f814ab8 100644 --- a/lib_dec/ivas_init_dec.c +++ b/lib_dec/ivas_init_dec.c @@ -1252,9 +1252,7 @@ ivas_error ivas_init_decoder( int16_t sce_id, cpe_id; int16_t numCldfbAnalyses, numCldfbSyntheses; int16_t granularity, n_channels_transport_jbm; -#ifdef FIX_1330_JBM_MEMORY int16_t nchan_out_buff; -#endif int32_t output_Fs, ivas_total_brate; int32_t delay_ns; AUDIO_CONFIG output_config; @@ -2389,28 +2387,11 @@ ivas_error ivas_init_decoder( * Allocate floating-point output audio buffers *-----------------------------------------------------------------*/ -#ifdef FIX_1330_JBM_MEMORY nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) { return error; } -#else - k = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, ivas_total_brate ); - for ( n = 0; n < k; n++ ) - { - /* note: these are intra-frame heap memories */ - if ( ( st_ivas->p_output_f[n] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); - } - } - - for ( ; n < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; n++ ) - { - st_ivas->p_output_f[n] = NULL; - } -#endif return IVAS_ERR_OK; } @@ -2886,15 +2867,7 @@ void ivas_destroy_dec( /* floating-point output audio buffers */ for ( i = 0; i < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; i++ ) { -#ifdef FIX_1330_JBM_MEMORY st_ivas->p_output_f[i] = NULL; -#else - if ( st_ivas->p_output_f[i] != NULL ) - { - free( st_ivas->p_output_f[i] ); - st_ivas->p_output_f[i] = NULL; - } -#endif } /* main IVAS handle */ diff --git a/lib_dec/ivas_ism_dec.c b/lib_dec/ivas_ism_dec.c index 000b5f6ca5..d89076863a 100644 --- a/lib_dec/ivas_ism_dec.c +++ b/lib_dec/ivas_ism_dec.c @@ -60,11 +60,7 @@ static ivas_error ivas_ism_bitrate_switching_dec( int16_t tc_nchan_tc_new; int16_t tc_nchan_allocate_new; int16_t tc_granularity_new; -#ifdef FIX_1330_JBM_MEMORY int16_t nchan_out_buff; -#else - int16_t nchan_out_buff, nchan_out_buff_old; -#endif nCPE_old = st_ivas->nCPE; nSCE_old = st_ivas->nSCE; @@ -74,9 +70,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( st_ivas->ism_mode = last_ism_mode; ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); st_ivas->ism_mode = ism_mode; -#ifndef FIX_1330_JBM_MEMORY - nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); -#endif if ( ( error = ivas_ism_config( st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->nchan_transport, st_ivas->nchan_ism, NULL, 0, NULL, NULL, element_brate_tmp, NULL, NULL, 0 ) ) != IVAS_ERR_OK ) { @@ -291,17 +284,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( return error; } -#ifndef FIX_1330_JBM_MEMORY - /*-----------------------------------------------------------------* - * floating-point output audio buffers - *-----------------------------------------------------------------*/ - - nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) - { - return error; - } -#endif /*-----------------------------------------------------------------* * JBM TC buffers *-----------------------------------------------------------------*/ @@ -343,7 +325,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( mvs2s( st_ivas->hTcBuffer->subframe_nbslots, st_ivas->hSpatParamRendCom->subframe_nbslots, MAX_JBM_SUBFRAMES_5MS ); } -#ifdef FIX_1330_JBM_MEMORY /*-----------------------------------------------------------------* * floating-point output audio buffers @@ -354,7 +335,6 @@ static ivas_error ivas_ism_bitrate_switching_dec( { return error; } -#endif return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_ism_renderer.c b/lib_dec/ivas_ism_renderer.c index 55a77e0ba8..11d797253a 100644 --- a/lib_dec/ivas_ism_renderer.c +++ b/lib_dec/ivas_ism_renderer.c @@ -193,25 +193,11 @@ void ivas_ism_render_sf( ism_md_subframe_update_jbm = st_ivas->hTcBuffer->nb_subframes - 2; } -#ifndef FIX_1330_JBM_MEMORY - if ( st_ivas->hDecoderConfig->Opt_tsm ) + for ( i = 0; i < num_objects; i++ ) { - for ( i = 0; i < num_objects; i++ ) - { - p_tc[i] = &st_ivas->hTcBuffer->tc[i][tc_offset]; - } + mvr2r( &output_f[i][tc_offset], tc_local[i], n_samples_to_render ); + p_tc[i] = tc_local[i]; } - else - { -#endif - for ( i = 0; i < num_objects; i++ ) - { - mvr2r( &output_f[i][tc_offset], tc_local[i], n_samples_to_render ); - p_tc[i] = tc_local[i]; - } -#ifndef FIX_1330_JBM_MEMORY - } -#endif for ( i = 0; i < nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; i++ ) { @@ -436,12 +422,7 @@ void ivas_omasa_separate_object_render_jbm( const uint16_t nSamplesRendered, /* i : number of samples rendered */ float input_f_in[][L_FRAME48k], /* i : separated object signal */ float *output_f[], /* o : rendered time signal */ -#ifdef FIX_1330_JBM_MEMORY const int16_t subframes_rendered /* i : number of subframes rendered */ -#else - const int16_t subframes_rendered, /* i : number of subframes rendered */ - const int16_t slots_rendered /* i : number of CLDFB slots rendered */ -#endif ) { VBAP_HANDLE hVBAPdata; @@ -482,33 +463,15 @@ void ivas_omasa_separate_object_render_jbm( num_objects = st_ivas->nchan_ism; } -#ifndef FIX_1330_JBM_MEMORY - offsetSamples = slots_rendered * hSpatParamRendCom->slot_size; - -#endif for ( j = 0; j < nchan_out_woLFE + num_lfe; j++ ) { output_f_local[j] = output_f[j]; } -#ifndef FIX_1330_JBM_MEMORY - if ( st_ivas->hDecoderConfig->Opt_tsm ) - { - for ( obj = 0; obj < num_objects; obj++ ) - { - input_f[obj] = &st_ivas->hTcBuffer->tc[obj + 2][offsetSamples]; - } - } - else + for ( obj = 0; obj < num_objects; obj++ ) { -#endif - for ( obj = 0; obj < num_objects; obj++ ) - { - input_f[obj] = input_f_in[obj]; - } -#ifndef FIX_1330_JBM_MEMORY + input_f[obj] = input_f_in[obj]; } -#endif slots_to_render = nSamplesRendered / hSpatParamRendCom->slot_size; first_sf = subframes_rendered; diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 711d6a6e38..e30f5aebeb 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -763,11 +763,7 @@ void ivas_jbm_dec_feed_tc_to_renderer( float tmp_buf[MAX_JBM_L_FRAME48k]; float *p_data_f[FOA_CHANNELS + MAX_NUM_OBJECTS]; int16_t n, n_render_timeslots, n_ch_cldfb; -#ifdef FIX_1330_JBM_MEMORY int16_t ch, offset, len_offset; -#else - int16_t ch; -#endif DECODER_TC_BUFFER_HANDLE hTcBuffer; hTcBuffer = st_ivas->hTcBuffer; @@ -785,7 +781,6 @@ void ivas_jbm_dec_feed_tc_to_renderer( n_ch_full_copy = min( hTcBuffer->nchan_transport_jbm, hTcBuffer->nchan_buffer_full ); n_ch_res_copy = hTcBuffer->nchan_transport_jbm - hTcBuffer->nchan_buffer_full; -#ifdef FIX_1330_JBM_MEMORY /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': in case of 'length(hTcBuffer->tc[]) < length(p_output_f[])', reset of TC buffers pointers is needed after ivas_buffer_interleaved_to_deinterleaved() */ @@ -800,7 +795,6 @@ void ivas_jbm_dec_feed_tc_to_renderer( } } -#endif for ( ch = 0; ch < n_ch_full_copy; ch++ ) { mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); @@ -2106,9 +2100,7 @@ static ivas_error ivas_jbm_dec_tc_audio_allocate( if ( Opt_tsm ) { n_samp_full = ( NS2SA( output_Fs, MAX_JBM_L_FRAME_NS ) ); -#ifdef FIX_1330_JBM_MEMORY n_samp_full = max( n_samp_full, L_FRAME48k ); /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': ensure minimal length */ -#endif n_samp_residual = hTcBuffer->n_samples_granularity - 1; } else @@ -2168,10 +2160,8 @@ static ivas_error ivas_jbm_dec_tc_audio_allocate( } } -#ifdef FIX_1330_JBM_MEMORY hTcBuffer->tc_buffer2 = NULL; -#endif return IVAS_ERR_OK; } @@ -2209,14 +2199,12 @@ static void ivas_jbm_dec_tc_audio_deallocate( hTcBuffer->tc_buffer_old[ch_idx] = NULL; } } -#ifdef FIX_1330_JBM_MEMORY if ( hTcBuffer->tc_buffer2 != NULL ) { free( hTcBuffer->tc_buffer2 ); hTcBuffer->tc_buffer2 = NULL; } -#endif } return; @@ -2413,11 +2401,7 @@ static void ivas_jbm_dec_tc_buffer_playout( for ( ch_idx = 0; ch_idx < st_ivas->hTcBuffer->nchan_transport_jbm; ch_idx++ ) { -#ifdef FIX_1330_JBM_MEMORY output[ch_idx] = st_ivas->hTcBuffer->tc[ch_idx] + st_ivas->hTcBuffer->n_samples_rendered; -#else - mvr2r( st_ivas->hTcBuffer->tc[ch_idx] + st_ivas->hTcBuffer->n_samples_rendered, output[ch_idx], *nSamplesRendered ); -#endif } st_ivas->hTcBuffer->subframes_rendered = last_sf; diff --git a/lib_dec/ivas_masa_dec.c b/lib_dec/ivas_masa_dec.c index 5f4634c383..f44f872abd 100644 --- a/lib_dec/ivas_masa_dec.c +++ b/lib_dec/ivas_masa_dec.c @@ -1320,11 +1320,7 @@ ivas_error ivas_masa_dec_reconfigure( Decoder_State **sts; int32_t ivas_total_brate, last_ivas_total_brate; int16_t numCldfbAnalyses_old, numCldfbSyntheses_old; -#ifdef FIX_1330_JBM_MEMORY int16_t nchan_out_buff; -#else - int16_t nchan_out_buff_old, nchan_out_buff; -#endif ivas_error error; int16_t pos_idx; int32_t ism_total_brate; @@ -1332,10 +1328,6 @@ ivas_error ivas_masa_dec_reconfigure( ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; -#ifndef FIX_1330_JBM_MEMORY - nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); - -#endif /* Copy state to TC buffer if granularity matches and we are not in OMASA EXT rendering mode */ if ( st_ivas->hSpatParamRendCom != NULL && st_ivas->hSpatParamRendCom->slot_size == st_ivas->hTcBuffer->n_samples_granularity && st_ivas->hDecoderConfig->output_config != IVAS_AUDIO_CONFIG_EXTERNAL ) { @@ -1573,11 +1565,7 @@ ivas_error ivas_masa_dec_reconfigure( if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->last_ivas_format == MASA_FORMAT ) /* note: switching with OMASA is addressed in ivas_omasa_dec_config() */ { nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); -#ifdef FIX_1330_JBM_MEMORY if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 2ea644dbd2..eaa094b68b 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -732,17 +732,10 @@ static ivas_error ivas_mc_dec_reconfig( int16_t tc_nchan_tc_new; int16_t tc_nchan_allocate_new; int16_t tc_granularity_new; -#ifdef FIX_1330_JBM_MEMORY int16_t nchan_out_buff; -#else - int16_t nchan_out_buff_old, nchan_out_buff; -#endif ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; nchan_transport_old = st_ivas->nchan_transport; -#ifndef FIX_1330_JBM_MEMORY - nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); -#endif last_mc_mode = ivas_mc_mode_select( ivas_mc_map_output_config_to_mc_ls_setup( st_ivas->transport_config ), st_ivas->hDecoderConfig->last_ivas_total_brate ); /* NB: this assumes that LS config remains the same between frames */ /* temporally set the current mc_mode back to the previous one to make sure the following call to @@ -1393,11 +1386,7 @@ static ivas_error ivas_mc_dec_reconfig( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); -#ifdef FIX_1330_JBM_MEMORY if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_dec/ivas_omasa_dec.c b/lib_dec/ivas_omasa_dec.c index 628d6b4d24..279dfe6931 100644 --- a/lib_dec/ivas_omasa_dec.c +++ b/lib_dec/ivas_omasa_dec.c @@ -200,11 +200,7 @@ ivas_error ivas_omasa_dec_config( int32_t ivas_total_brate, ism_total_brate, cpe_brate; ISM_MODE ism_mode_old; IVAS_FORMAT ivas_format_orig; -#ifdef FIX_1330_JBM_MEMORY int16_t nchan_out_buff; -#else - int16_t nchan_out_buff, nchan_out_buff_old; -#endif ivas_error error; RENDERER_TYPE old_renderer_type; @@ -219,9 +215,6 @@ ivas_error ivas_omasa_dec_config( ivas_format_orig = st_ivas->ivas_format; st_ivas->ivas_format = st_ivas->last_ivas_format; ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); -#ifndef FIX_1330_JBM_MEMORY - nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); -#endif st_ivas->ivas_format = ivas_format_orig; nSCE_old = st_ivas->nSCE; @@ -475,11 +468,7 @@ ivas_error ivas_omasa_dec_config( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, -1, -1 ); -#ifdef FIX_1330_JBM_MEMORY if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, st_ivas->hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) -#endif { return error; } @@ -682,84 +671,55 @@ void ivas_omasa_dirac_rend_jbm( ) { int16_t subframes_rendered; -#ifndef FIX_1330_JBM_MEMORY - int16_t slots_rendered; -#endif int16_t n; float data_separated_objects[MAX_NUM_OBJECTS][L_FRAME48k]; -#ifndef FIX_1330_JBM_MEMORY - if ( !st_ivas->hDecoderConfig->Opt_tsm ) + *nSamplesRendered = min( nSamplesAsked, st_ivas->hTcBuffer->n_samples_available ); + + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) { -#endif - *nSamplesRendered = min( nSamplesAsked, st_ivas->hTcBuffer->n_samples_available ); + mvr2r( &output_f[CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[0], *nSamplesRendered ); - if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) { - mvr2r( &output_f[CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[0], *nSamplesRendered ); - -#ifdef FIX_1330_JBM_MEMORY - if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) -#else - if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) -#endif + /* Gain separated object, if edited */ + for ( n = 0; n < st_ivas->nchan_ism; n++ ) { - /* Gain separated object, if edited */ - for ( n = 0; n < st_ivas->nchan_ism; n++ ) + if ( st_ivas->hMasaIsmData->ism_gain_is_edited[n] && st_ivas->hMasaIsmData->idx_separated_ism == n ) { - if ( st_ivas->hMasaIsmData->ism_gain_is_edited[n] && st_ivas->hMasaIsmData->idx_separated_ism == n ) - { - v_multc( data_separated_objects[0], st_ivas->hMasaIsmData->gain_ism_edited[n], data_separated_objects[0], *nSamplesRendered ); - } + v_multc( data_separated_objects[0], st_ivas->hMasaIsmData->gain_ism_edited[n], data_separated_objects[0], *nSamplesRendered ); } } } - else + } + else + { + for ( n = 0; n < st_ivas->nchan_ism; n++ ) { - for ( n = 0; n < st_ivas->nchan_ism; n++ ) - { - mvr2r( &output_f[n + CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[n], *nSamplesRendered ); + mvr2r( &output_f[n + CPE_CHANNELS][st_ivas->hTcBuffer->n_samples_rendered], data_separated_objects[n], *nSamplesRendered ); - /* Gain discrete objects, if edited */ -#ifdef FIX_1330_JBM_MEMORY - if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) -#else - if ( st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) -#endif - { - v_multc( data_separated_objects[n], st_ivas->hMasaIsmData->gain_ism_edited[n], data_separated_objects[n], *nSamplesRendered ); - } + /* Gain discrete objects, if edited */ + if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->ism_gain_is_edited[n] ) + { + v_multc( data_separated_objects[n], st_ivas->hMasaIsmData->gain_ism_edited[n], data_separated_objects[n], *nSamplesRendered ); } + } - /* Gain MASA part, if edited */ -#ifdef FIX_1330_JBM_MEMORY - if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->masa_gain_is_edited ) -#else - if ( st_ivas->hMasaIsmData->masa_gain_is_edited ) -#endif + /* Gain MASA part, if edited */ + if ( !st_ivas->hDecoderConfig->Opt_tsm && st_ivas->hMasaIsmData->masa_gain_is_edited ) + { + for ( int16_t ch = 0; ch < 2; ch++ ) { - for ( int16_t ch = 0; ch < 2; ch++ ) - { - v_multc( output_f[ch], st_ivas->hMasaIsmData->gain_masa_edited, output_f[ch], *nSamplesRendered ); - } + v_multc( output_f[ch], st_ivas->hMasaIsmData->gain_masa_edited, output_f[ch], *nSamplesRendered ); } } -#ifndef FIX_1330_JBM_MEMORY } -#endif subframes_rendered = st_ivas->hSpatParamRendCom->subframes_rendered; -#ifndef FIX_1330_JBM_MEMORY - slots_rendered = st_ivas->hSpatParamRendCom->slots_rendered; -#endif ivas_dirac_dec_render( st_ivas, nchan_transport, nSamplesAsked, nSamplesRendered, nSamplesAvailable, output_f ); -#ifdef FIX_1330_JBM_MEMORY ivas_omasa_separate_object_render_jbm( st_ivas, *nSamplesRendered, data_separated_objects, output_f, subframes_rendered ); -#else - ivas_omasa_separate_object_render_jbm( st_ivas, *nSamplesRendered, data_separated_objects, output_f, subframes_rendered, slots_rendered ); -#endif return; } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index a3ff4aa5df..8f790bde91 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -258,70 +258,35 @@ ivas_error ivas_osba_render_sf( ) { int16_t n; -#ifdef FIX_1330_JBM_MEMORY float output_sba[MAX_OUTPUT_CHANNELS][L_FRAME48k]; float *p_output_sba[MAX_OUTPUT_CHANNELS]; -#else - float output_ism[MAX_OUTPUT_CHANNELS][L_FRAME48k]; - float *p_output_ism[MAX_OUTPUT_CHANNELS]; -#endif ivas_error error; for ( n = 0; n < MAX_OUTPUT_CHANNELS; n++ ) { -#ifdef FIX_1330_JBM_MEMORY p_output_sba[n] = output_sba[n]; -#else - p_output_ism[n] = &output_ism[n][0]; -#endif - } - -#ifndef FIX_1330_JBM_MEMORY - if ( !st_ivas->hDecoderConfig->Opt_tsm ) - { - int16_t tc_offset; - tc_offset = st_ivas->hTcBuffer->n_samples_rendered; - for ( n = 0; n < st_ivas->nchan_ism; n++ ) - { - mvr2r( &p_output[n][tc_offset], &output_ism[n][tc_offset], nSamplesAsked ); - } } -#endif -#ifdef FIX_1330_JBM_MEMORY if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailableNext, p_output_sba ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAsked, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) -#endif { return error; } if ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) { -#ifdef FIX_1330_JBM_MEMORY ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output, *nSamplesRendered ); -#else - ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output_ism, *nSamplesRendered ); -#endif } for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) { if ( st_ivas->renderer_type != RENDERER_BINAURAL_FASTCONV_ROOM ) { -#ifdef FIX_1330_JBM_MEMORY v_add( p_output[n], p_output_sba[n], p_output[n], *nSamplesRendered ); -#else - v_add( p_output[n], p_output_ism[n], p_output[n], *nSamplesRendered ); -#endif } -#ifdef FIX_1330_JBM_MEMORY else { mvr2r( p_output_sba[n], p_output[n], *nSamplesRendered ); } -#endif } return IVAS_ERR_OK; diff --git a/lib_dec/ivas_sba_dec.c b/lib_dec/ivas_sba_dec.c index a11fb37d54..4f4fb83f22 100644 --- a/lib_dec/ivas_sba_dec.c +++ b/lib_dec/ivas_sba_dec.c @@ -111,12 +111,7 @@ ivas_error ivas_sba_dec_reconfigure( int32_t ivas_total_brate; int32_t last_ivas_total_brate; int16_t num_channels, num_md_sub_frames; -#ifdef FIX_1330_JBM_MEMORY int16_t nchan_out_buff; -#else - int16_t nchan_out_buff, nchan_out_buff_old; - int16_t sba_analysis_order_old_flush; -#endif DECODER_CONFIG_HANDLE hDecoderConfig; ivas_error error; ISM_MODE ism_mode_old; @@ -127,18 +122,12 @@ ivas_error ivas_sba_dec_reconfigure( hDecoderConfig = st_ivas->hDecoderConfig; ivas_total_brate = hDecoderConfig->ivas_total_brate; last_ivas_total_brate = st_ivas->last_active_ivas_total_brate; -#ifndef FIX_1330_JBM_MEMORY - sba_analysis_order_old_flush = st_ivas->sba_analysis_order; -#endif /*-----------------------------------------------------------------* * Set SBA high-level parameters * Save old SBA high-level parameters *-----------------------------------------------------------------*/ -#ifndef FIX_1330_JBM_MEMORY - nchan_out_buff_old = ivas_get_nchan_buffers_dec( st_ivas, sba_analysis_order_old_flush, last_ivas_total_brate ); -#endif ivas_init_dec_get_num_cldfb_instances( st_ivas, &numCldfbAnalyses_old, &numCldfbSyntheses_old ); nchan_hp20_old = getNumChanSynthesis( st_ivas ); @@ -620,11 +609,7 @@ ivas_error ivas_sba_dec_reconfigure( *-----------------------------------------------------------------*/ nchan_out_buff = ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); -#ifdef FIX_1330_JBM_MEMORY if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff, hDecoderConfig->Opt_tsm, st_ivas->hTcBuffer ) ) != IVAS_ERR_OK ) -#else - if ( ( error = ivas_output_buff_dec( st_ivas->p_output_f, nchan_out_buff_old, nchan_out_buff ) ) != IVAS_ERR_OK ) -#endif { return error; } diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index b93bb8bf56..0f0ad4cedb 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -964,10 +964,8 @@ typedef struct decoder_tc_buffer_structure int16_t num_slots; int16_t n_samples_discard; /* number of samples to discard from the beginning of the output */ -#ifdef FIX_1330_JBM_MEMORY float *tc_buffer2; /* non-scaled buffer of output audio - needed only when '*tc_buffer* is not long enough */ -#endif } DECODER_TC_BUFFER, *DECODER_TC_BUFFER_HANDLE; typedef struct jbm_metadata_structure diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 460bf182a3..01e1d77231 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -368,18 +368,12 @@ int16_t ivas_get_nchan_buffers_dec( *-------------------------------------------------------------------*/ ivas_error ivas_output_buff_dec( - float *p_output_f[], /* i/o: output audio buffers */ -#ifdef FIX_1330_JBM_MEMORY + float *p_output_f[], /* i/o: output audio buffers */ const int16_t nchan_out_buff, /* i : number of output channels */ const int16_t Opt_tsm, /* i : TSM option flag */ DECODER_TC_BUFFER_HANDLE hTcBuffer /* i : TSM buffer handle */ -#else - const int16_t nchan_out_buff_old, /* i : previous frame number of output channels */ - const int16_t nchan_out_buff /* i : number of output channels */ -#endif ) { -#ifdef FIX_1330_JBM_MEMORY int16_t ch, nchan_tc_jbm, nsamp_to_allocate, n_samp_full, offset; for ( ch = 0; ch < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch++ ) @@ -437,35 +431,6 @@ ivas_error ivas_output_buff_dec( offset += n_samp_full; } } -#else - int16_t ch; - - if ( nchan_out_buff > nchan_out_buff_old ) - { - for ( ch = nchan_out_buff_old; ch < nchan_out_buff; ch++ ) - { -#ifdef DEBUGGING - if ( p_output_f[ch] != NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Memory for floating-point output audio buffer is already allocated!\n" ) ); - } -#endif - /* note: these are intra-frame heap memories */ - if ( ( p_output_f[ch] = (float *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for floating-point output audio buffer!\n" ) ); - } - } - } - else - { - for ( ch = nchan_out_buff; ch < nchan_out_buff_old; ch++ ) - { - free( p_output_f[ch] ); - p_output_f[ch] = NULL; - } - } -#endif return IVAS_ERR_OK; } diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 3119f5fdf9..c12fa8488b 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1924,23 +1924,17 @@ ivas_error ivas_binaural_reverb_init( energyModifier = ( adjustedRevTime - revTimes[bin] ) / adjustedRevTime; /* Adjust early and late energies, by moving late energy to early energy */ -#ifdef FIX_1371_EARLY_PART_INIT_FASTCONV if ( earlyEne != NULL ) { adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; earlyEne[bin] = adjustedEarlyEne; /* Store already here */ } -#else - adjustedEarlyEne = earlyEne[bin] + revEne[bin] * energyModifier; -#endif + adjustedLateEne = revEne[bin] * ( 1.0f - energyModifier ); /* Store adjusted room effect parameters to be used in reverb processing */ revTimes[bin] = adjustedRevTime; revEne[bin] = adjustedLateEne; -#ifndef FIX_1371_EARLY_PART_INIT_FASTCONV - earlyEne[bin] = adjustedEarlyEne; -#endif } } diff --git a/lib_util/rotation_file_reader.c b/lib_util/rotation_file_reader.c index 6c62290b00..cbf36e42ba 100644 --- a/lib_util/rotation_file_reader.c +++ b/lib_util/rotation_file_reader.c @@ -174,14 +174,12 @@ ivas_error ExternalOrientationFileReading( } ( externalOrientationReader->frameCounter )++; -#ifdef FIX_1370_EXTERNAL_ORIENTATION_CHECK /* Only Quaternion orientations are supported, raise an error if Euler angles are detected in the input */ if ( w == -3.0f ) { return IVAS_ERR_EXTERNAL_ORIENTATION_INVALID_FORMAT; } -#endif pQuaternion->w = w; pQuaternion->x = x; -- GitLab From 7bfb74f4be99fa778355af6102fa1d300d31e820 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 2 Sep 2025 11:38:55 +0200 Subject: [PATCH 45/61] Add SHAs in versions.txt and html report --- scripts/find_regressions_from_logs.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index ba473c859e..01826f23b1 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -25,8 +25,11 @@ REF_DEC2={REF_DEC2} DUT_ENC2={DUT_ENC2} DUT_DEC2={DUT_DEC2} +INV_LEVEL_SCALING=$(awk "BEGIN {{print 1.0 / $LEVEL_SCALING}}") + # Obtain executables from past reference git checkout `git rev-list -1 --before="$MIN_DATE 22:00:00" ivas-float-update` +echo "ivas_float_update, min version: `git rev-parse HEAD`" > versions.txt make clean make -j mv IVAS_cod IVAS_cod_ref_1 @@ -34,6 +37,7 @@ mv IVAS_dec IVAS_dec_ref_1 mv IVAS_rend IVAS_rend_ref_1 git checkout $MIN_SHA +echo "main, min version: `git rev-parse HEAD`" >> versions.txt make clean make -j mv IVAS_cod IVAS_cod_1 @@ -43,6 +47,7 @@ mv IVAS_rend IVAS_rend_1 # Obtain latest executables git checkout ivas-float-update git pull +echo "ivas-float-update, current version: `git rev-parse HEAD`" >> versions.txt make clean make -j mv IVAS_cod IVAS_cod_ref_2 @@ -51,6 +56,7 @@ mv IVAS_rend IVAS_rend_ref_2 git checkout main git pull +echo "main, current version: `git rev-parse HEAD`" >> versions.txt make clean make -j mv IVAS_cod IVAS_cod_2 @@ -60,7 +66,7 @@ mv IVAS_rend IVAS_rend_2 # Get fresh copy of scripts, tests and ci cp -r $SCRIPTS_DIR/{{scripts,tests,ci,pytest.ini}} . rm -rf tests/ref tests/dut tests/renderer/ref tests/renderer/cut -python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm # Should not be needed since only supported testcases should be input +python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm # Get LTVs cp $LTV_DIR/* scripts/testv @@ -72,7 +78,7 @@ tests/scale_pcm.py ./scripts/testv/ "$LEVEL_SCALING" cp IVAS_rend_ref_1 IVAS_rend_ref cp IVAS_rend_1 IVAS_rend python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg --junit-xml=report1.xml +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg --scalefac $INV_LEVEL_SCALING --junit-xml=report1.xml --html=report1.html --self-contained-html python3 scripts/parse_xml_report.py report1.xml report1.csv # Store results from first run @@ -84,7 +90,7 @@ cp -r tests/renderer/cut tests1/renderer cp IVAS_rend_ref_2 IVAS_rend_ref cp IVAS_rend_2 IVAS_rend python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg --junit-xml=report2.xml +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg --scalefac $INV_LEVEL_SCALING --junit-xml=report2.xml --html=report2.html --self-contained-html python3 scripts/parse_xml_report.py report2.xml report2.csv """ @@ -155,7 +161,7 @@ def main(logs_dir, output_filename, measure): result.to_csv(output_filename, sep=";", index=False) critical = result.iloc[:, 0:9] - formats = list(set(critical["format"])) + formats = list(set(critical["format"])).sort() critical3 = pd.DataFrame() for format in formats: -- GitLab From 4080c5b0fce2c0fc8bf44f5bd246256b1fcf1479 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 2 Sep 2025 11:48:54 +0200 Subject: [PATCH 46/61] Fix sorting --- scripts/find_regressions_from_logs.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 01826f23b1..068fe77871 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -161,7 +161,8 @@ def main(logs_dir, output_filename, measure): result.to_csv(output_filename, sep=";", index=False) critical = result.iloc[:, 0:9] - formats = list(set(critical["format"])).sort() + formats = list(set(critical["format"])) + formats.sort() critical3 = pd.DataFrame() for format in formats: -- GitLab From 2acc2d7ce8e339af774d33ef0fd18ce4e2776ed9 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 3 Sep 2025 07:14:40 +0200 Subject: [PATCH 47/61] Add missing lc3plus files from main --- lib_lc3plus/lc3plus.c | 438 +++++++++++++++++++++++ lib_lc3plus/lc3plus.h | 520 +++++++++++++++++++++++++++ lib_lc3plus/setup_com_lc3plus.c | 31 ++ lib_lc3plus/setup_dec_lc3plus.c | 512 +++++++++++++++++++++++++++ lib_lc3plus/setup_dec_lc3plus.h | 114 ++++++ lib_lc3plus/setup_enc_lc3plus.c | 610 ++++++++++++++++++++++++++++++++ lib_lc3plus/setup_enc_lc3plus.h | 121 +++++++ lib_rend/ivas_td_ring_buffer.c | 288 +++++++++++++++ 8 files changed, 2634 insertions(+) create mode 100644 lib_lc3plus/lc3plus.c create mode 100644 lib_lc3plus/lc3plus.h create mode 100644 lib_lc3plus/setup_com_lc3plus.c create mode 100644 lib_lc3plus/setup_dec_lc3plus.c create mode 100644 lib_lc3plus/setup_dec_lc3plus.h create mode 100644 lib_lc3plus/setup_enc_lc3plus.c create mode 100644 lib_lc3plus/setup_enc_lc3plus.h create mode 100644 lib_rend/ivas_td_ring_buffer.c diff --git a/lib_lc3plus/lc3plus.c b/lib_lc3plus/lc3plus.c new file mode 100644 index 0000000000..d208cfb151 --- /dev/null +++ b/lib_lc3plus/lc3plus.c @@ -0,0 +1,438 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "options.h" +#include "wmc_auto.h" +#include "lc3plus.h" +#include "defines.h" +#include "functions.h" +#include + +#include "setup_dec_lc3plus.h" +#include "setup_enc_lc3plus.h" + +#define RETURN_IF(cond, error) \ + if (cond) \ + return (error) + +/* ensure api header constants are up to date */ +STATIC_ASSERT(LC3PLUS_MAX_SAMPLES >= MAX_LEN); +STATIC_ASSERT(LC3PLUS_MAX_CHANNELS >= MAX_CHANNELS); +STATIC_ASSERT(LC3PLUS_MAX_BYTES >= BYTESBUFSIZE); + +/* misc functions ************************************************************/ + +int lc3plus_version(void) +{ + return LC3PLUS_VERSION; +} + +int lc3plus_channels_supported(int channels) +{ + return channels >= 1 && channels <= MAX_CHANNELS; +} + +int lc3plus_samplerate_supported(int samplerate) +{ + switch (samplerate) + { + case 8000: return 1; + case 16000: return 1; + case 24000: return 1; + case 32000: return 1; + case 44100: return 1; + case 48000: return 1; + case 96000: return 1; + default: break; + } + return 0; +} + +static int lc3plus_plc_mode_supported(LC3PLUS_PlcMode plc_mode) +{ + switch ((int)plc_mode) + { + case LC3PLUS_PLC_ADVANCED: /* fallthru */ + return 1; + default: break; + } + return 0; +} + +static int lc3plus_frame_size_supported(float frame_ms) +{ + switch ((int)(ceil(frame_ms * 10))) + { + case 25: /* fallthru */ + case 50: /* fallthru */ + case 75: /* fallthru */ + case 100: return 1; + default: break; + } + return 0; +} + +static int null_in_list(void **list, int n) +{ + while (--n >= 0) + RETURN_IF(list[n] == NULL, 1); + return 0; +} + +/* return pointer to aligned base + base_size, *base_size += size + 4 bytes align */ +void *balloc(void *base, size_t *base_size, size_t size) +{ + uintptr_t ptr = ((uintptr_t)base + *base_size + 3) & (uintptr_t)(~3); + assert((uintptr_t)base % 4 == 0); /* base must be 4-byte aligned */ + *base_size = (*base_size + size + 3) & (uintptr_t)(~3); + return (void *)ptr; +} + +int32_t lc3_enc_supported_lfe(void) +{ + return 1; +} + +/* encoder functions *********************************************************/ +LC3PLUS_Error lc3plus_enc_init(LC3PLUS_Enc *encoder, int samplerate, int channels, int hrmode, int32_t lfe_channel_array[]) +{ + int ch = 0; + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF((uintptr_t)encoder % 4 != 0, LC3PLUS_ALIGN_ERROR); + RETURN_IF(!lc3plus_samplerate_supported(samplerate), LC3PLUS_SAMPLERATE_ERROR); + RETURN_IF(!lc3plus_channels_supported(channels), LC3PLUS_CHANNELS_ERROR); + RETURN_IF(samplerate==96000 && hrmode == 0, LC3PLUS_HRMODE_ERROR); + + if (lfe_channel_array != NULL) + { + for (ch = 0; ch < channels; ch++) + { + RETURN_IF(!lc3_enc_supported_lfe() && lfe_channel_array[ch], LC3PLUS_LFE_MODE_NOT_SUPPORTED); + } + } + + return FillEncSetup(encoder, samplerate, channels, hrmode, lfe_channel_array); /* real bitrate check happens here */ +} + +int lc3plus_enc_get_size(int samplerate, int channels) +{ + RETURN_IF(!lc3plus_samplerate_supported(samplerate), 0); + RETURN_IF(!lc3plus_channels_supported(channels), 0); + return alloc_encoder(NULL, channels); +} + +/* Dummy function for API alignment */ +int lc3plus_enc_get_scratch_size(const LC3PLUS_Enc *encoder) +{ + UNUSED(encoder); + return 0; +} + +int lc3plus_enc_get_input_samples(const LC3PLUS_Enc *encoder) +{ + RETURN_IF(encoder == NULL, 0); + return encoder->frame_length; +} + +int lc3plus_enc_get_num_bytes(const LC3PLUS_Enc *encoder) +{ + RETURN_IF(encoder == NULL, 0); + + return encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in); +} + +int lc3plus_enc_get_real_bitrate(const LC3PLUS_Enc *encoder) +{ + int ch = 0, totalBytes = 0; + int bitrate; + RETURN_IF(encoder == NULL, 0); + RETURN_IF(!encoder->lc3_br_set, LC3PLUS_BITRATE_UNSET_ERROR); + + for (ch = 0; ch < encoder->channels; ch++) + { + totalBytes += encoder->channel_setup[ch]->targetBytes; + } + + bitrate = (totalBytes * 80000.0 + encoder->frame_dms - 1) / encoder->frame_dms; + + if (encoder->fs_in == 44100) + { + int rem = bitrate % 480; + bitrate = ((bitrate - rem) / 480) * 441 + (rem * 441) / 480; + } + + return bitrate; +} + + +LC3PLUS_Error lc3plus_enc_set_bitrate(LC3PLUS_Enc *encoder, int bitrate) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(bitrate <= 0, LC3PLUS_BITRATE_ERROR); +#ifndef STRIP_HR_MODE_API + RETURN_IF(encoder->fs_idx == 5 && encoder->hrmode == 0, LC3PLUS_HRMODE_ERROR); +#endif + return update_enc_bitrate(encoder, bitrate); +} + +int lc3plus_enc_get_delay(const LC3PLUS_Enc *encoder) +{ + RETURN_IF(encoder == NULL, 0); + return encoder->frame_length - 2 * encoder->la_zeroes; +} + +LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_dms) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(!lc3plus_frame_size_supported(frame_dms / 10.0), LC3PLUS_FRAMEMS_ERROR); + RETURN_IF(encoder->lc3_br_set, LC3PLUS_BITRATE_SET_ERROR); + encoder->frame_dms = frame_dms; + encoder->frame_ms = frame_dms / 10.0; + set_enc_frame_params(encoder); + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_enc_set_bandwidth(LC3PLUS_Enc *encoder, int bandwidth) +{ + LC3_INT effective_fs; + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); +#ifdef ENABLE_HR_MODE_FL_FLAG + RETURN_IF(encoder->hrmode == 1, LC3PLUS_HRMODE_BW_ERROR); +#endif + effective_fs = encoder->fs_in; + if (encoder->bandwidth != bandwidth) { + if (encoder->fs_in > 40000) { + effective_fs = 40000; + } + if ((bandwidth * 2) > effective_fs) { + return LC3PLUS_BW_WARNING; + } + else { + encoder->bandwidth = bandwidth; + encoder->bandwidth_preset = bandwidth; + encoder->bw_ctrl_active = 1; + update_enc_bitrate(encoder, encoder->bitrate); + } + } + return LC3PLUS_OK; +} + + +LC3PLUS_Error lc3plus_enc16(LC3PLUS_Enc* encoder, int16_t** input_samples, void* output_bytes, int* num_bytes +, void *scratch +) +{ + UNUSED(scratch); + return lc3plus_enc_fl(encoder, (void**)input_samples, 16, output_bytes, num_bytes); +} + +LC3PLUS_Error lc3plus_enc24(LC3PLUS_Enc* encoder, int32_t** input_samples, void* output_bytes, int* num_bytes +, void *scratch +) +{ + UNUSED(scratch); + return lc3plus_enc_fl(encoder, (void**)input_samples, 24, output_bytes, num_bytes); +} + + +LC3PLUS_Error lc3plus_enc_fl(LC3PLUS_Enc* encoder, void** input_samples, int bitdepth, void* output_bytes, int* num_bytes) +{ + RETURN_IF(!encoder || !input_samples || !output_bytes || !num_bytes, LC3PLUS_NULL_ERROR); + RETURN_IF(null_in_list(input_samples, encoder->channels), LC3PLUS_NULL_ERROR); + RETURN_IF(bitdepth != 16 && bitdepth != 24, LC3PLUS_ERROR); + *num_bytes = Enc_LC3PLUS_fl(encoder, input_samples, output_bytes, bitdepth + , *num_bytes == -1 + ); + assert(*num_bytes == lc3plus_enc_get_num_bytes(encoder)); + return LC3PLUS_OK; +} + +/* decoder functions *********************************************************/ + +LC3PLUS_Error lc3plus_dec_init(LC3PLUS_Dec* decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode, int hrmode) +{ + RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(!lc3plus_samplerate_supported(samplerate), LC3PLUS_SAMPLERATE_ERROR); + RETURN_IF(!lc3plus_channels_supported(channels), LC3PLUS_CHANNELS_ERROR); + RETURN_IF(!lc3plus_plc_mode_supported(plc_mode), LC3PLUS_PLCMODE_ERROR); + RETURN_IF(samplerate==96000 && hrmode == 0, LC3PLUS_HRMODE_ERROR); + return FillDecSetup(decoder, samplerate, channels, plc_mode, hrmode); +} + +int lc3plus_dec_get_size(int samplerate, int channels) +{ + RETURN_IF(!lc3plus_samplerate_supported(samplerate), 0); + RETURN_IF(!lc3plus_channels_supported(channels), 0); + return alloc_decoder(NULL, samplerate, channels); +} + +/* Dummy function for API alignment */ +int lc3plus_dec_get_scratch_size(const LC3PLUS_Dec *decoder) +{ + UNUSED(decoder); + return 0; +} + +LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_dms) +{ + RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF(!lc3plus_frame_size_supported(frame_dms / 10.0), LC3PLUS_FRAMEMS_ERROR); + RETURN_IF(decoder->plcMeth == 2 && frame_dms != 100, LC3PLUS_FRAMEMS_ERROR); + + decoder->frame_dms = frame_dms; + decoder->frame_ms = frame_dms / 10.0; + set_dec_frame_params(decoder); + return LC3PLUS_OK; +} + +int lc3plus_dec_get_output_samples(const LC3PLUS_Dec* decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->frame_length; +} + +int lc3plus_dec_get_delay(const LC3PLUS_Dec* decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->frame_length - 2 * decoder->la_zeroes; +} + +LC3PLUS_Error lc3plus_dec_fl(LC3PLUS_Dec* decoder, void* input_bytes, int num_bytes, void** output_samples, int bps, int bfi_ext) +{ + if (bfi_ext == 1) + { + RETURN_IF(!decoder || !output_samples, LC3PLUS_NULL_ERROR); + } else { + RETURN_IF(!decoder || !input_bytes || !output_samples, LC3PLUS_NULL_ERROR); + } + + RETURN_IF(null_in_list((void**)output_samples, decoder->channels), LC3PLUS_NULL_ERROR); + return Dec_LC3PLUS_fl(decoder, input_bytes, num_bytes, output_samples, bps, bfi_ext); +} + +LC3PLUS_Error lc3plus_dec16(LC3PLUS_Dec* decoder, void* input_bytes, int num_bytes, int16_t** output_samples, + void* scratch, + int bfi_ext) +{ + UNUSED(scratch); + return lc3plus_dec_fl(decoder, input_bytes, num_bytes, (void**)output_samples, 16, bfi_ext); +} + +LC3PLUS_Error lc3plus_dec24(LC3PLUS_Dec* decoder, void* input_bytes, int num_bytes, int32_t** output_samples, + void* scratch, + int bfi_ext) +{ + UNUSED(scratch); + return lc3plus_dec_fl(decoder, input_bytes, num_bytes, (void**)output_samples, 24, bfi_ext); +} + +/* memory functions *********************************************************/ + +LC3PLUS_Error lc3plus_enc_free_memory(LC3PLUS_Enc* encoder) +{ + RETURN_IF(!encoder, LC3PLUS_NULL_ERROR); + + lc3plus_free_encoder_structs(encoder); + + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_dec_free_memory(LC3PLUS_Dec* decoder) +{ + RETURN_IF(!decoder, LC3PLUS_NULL_ERROR); + + lc3plus_free_decoder_structs(decoder); + + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_free_encoder_structs(LC3PLUS_Enc* encoder) +{ + int ch = 0; + RETURN_IF(!encoder, LC3PLUS_NULL_ERROR); + + for (ch = 0; ch < encoder->channels; ch++) { + mdct_free(&encoder->channel_setup[ch]->mdctStruct); + dct2_free(&encoder->channel_setup[ch]->dct2StructSNS); + } + + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_free_decoder_structs(LC3PLUS_Dec* decoder) +{ + int ch = 0; + RETURN_IF(!decoder, LC3PLUS_NULL_ERROR); + + for (ch = 0; ch < decoder->channels; ch++) { + dct4_free(&decoder->channel_setup[ch]->dct4structImdct); + real_fft_free(&decoder->channel_setup[ch]->PlcAdvSetup->PlcPhEcuSetup.PhEcu_Fft); + real_fft_free(&decoder->channel_setup[ch]->PlcAdvSetup->PlcPhEcuSetup.PhEcu_Ifft); + } + + return LC3PLUS_OK; +} + + +LC3PLUS_EpModeRequest lc3plus_dec_get_ep_mode_request(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, LC3PLUS_EPMR_ZERO); + return (LC3PLUS_EpModeRequest)decoder->epmr; +} + +int lc3plus_dec_get_error_report(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->error_report == 2047 ? -1 : decoder->error_report & 0x07FF; +} + +LC3PLUS_Error lc3plus_enc_set_ep_mode(LC3PLUS_Enc *encoder, LC3PLUS_EpMode epmode) +{ + LC3PLUS_EpMode oldEpmode; + LC3PLUS_Error error; + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF((unsigned)epmode > LC3PLUS_EP_HIGH, LC3PLUS_EPMODE_ERROR); + oldEpmode = encoder->epmode; + encoder->epmode = epmode; + error = encoder->lc3_br_set ? update_enc_bitrate(encoder, encoder->bitrate) : LC3PLUS_OK; + if (error != LC3PLUS_OK) + { + encoder->epmode = oldEpmode; // preserve old epmode in case of failure + } + return error; +} + +LC3PLUS_Error lc3plus_enc_set_ep_mode_request(LC3PLUS_Enc *encoder, LC3PLUS_EpModeRequest epmr) +{ + RETURN_IF(encoder == NULL, LC3PLUS_NULL_ERROR); + RETURN_IF((unsigned)epmr > LC3PLUS_EPMR_HIGH, LC3PLUS_EPMODE_ERROR); + encoder->epmr = epmr; + return LC3PLUS_OK; +} + +LC3PLUS_Error lc3plus_dec_set_ep_enabled(LC3PLUS_Dec *decoder, int32_t ep_enabled) +{ + RETURN_IF(decoder == NULL, LC3PLUS_NULL_ERROR); + decoder->ep_enabled = ep_enabled != 0; + decoder->epmr = LC3PLUS_EPMR_ZERO; + return LC3PLUS_OK; +} + +int lc3plus_dec_get_epok_flags(const LC3PLUS_Dec *decoder) +{ + RETURN_IF(decoder == NULL, 0); + return decoder->error_report >> 11; +} + +#ifndef STRIP_ERROR_PROTECTION_API_FL +#endif /* STRIP_ERROR_PROTECTION_API_FL */ + +#ifndef STRIP_ERROR_PROTECTION_API_FL +#endif /* STRIP_ERROR_PROTECTION_API_FL */ + diff --git a/lib_lc3plus/lc3plus.h b/lib_lc3plus/lc3plus.h new file mode 100644 index 0000000000..063714467d --- /dev/null +++ b/lib_lc3plus/lc3plus.h @@ -0,0 +1,520 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +/*! \file lc3plus.h + * This header provides the API for LC3plus. + * + * This library is targeting devices with extreme memory limitations, so memory management + * must be handeled by the user. This includes allocating memory for the structs. The structs are persistent + * between function calls. + * + * The amount of memory needed for various configurations can be obtained from the lc3plus_*_get_size + * function. The LC3PLUS_*_MAX_SIZE macro can be used for all configurations. + * + * Depending on the build configuration some functions might not be available. + */ + +#ifndef LC3PLUS_H +#define LC3PLUS_H + +#ifndef _MSC_VER +#include "options.h" +#include "wmc_auto.h" +#include +#else +typedef unsigned char uint8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +#endif + +/*! Construct version number from major/minor/micro values. */ +#define LC3PLUS_VERSION_INT(major, minor, micro) (((major) << 16) | ((minor) << 8) | (micro)) + +/*! Version number to ensure header and binary are matching. */ +#define LC3PLUS_VERSION LC3PLUS_VERSION_INT(1, 7, 4) + +/*! Maximum number of supported channels. The actual binary might support + * less, use lc3plus_channels_supported() to check. */ +#define LC3PLUS_MAX_CHANNELS 2 + +/*! Maximum number of samples per channel that can be stored in one LC3plus frame. + */ +#define LC3PLUS_MAX_SAMPLES 960 + +/*! Maximum number of bytes of one LC3plus frame. */ +#define LC3PLUS_MAX_BYTES 1250 + +/*! Maximum size needed to store encoder state. */ +#define LC3PLUS_ENC_MAX_SIZE 20392 + +/*! Maximum size needed to store decoder state. */ +#define LC3PLUS_DEC_MAX_SIZE 87528 + +/*! Error codes returned by functions. */ +typedef enum +{ + LC3PLUS_PLC_ADVANCED = 1 /*!< Enhanced concealment method */ +} LC3PLUS_PlcMode; + +/*! Error protection mode. LC3PLUS_EP_ZERO differs to LC3PLUS_EP_OFF in that + * errors can be detected but not corrected. */ +typedef enum +{ + LC3PLUS_EP_OFF = 0, /*!< Error protection is disabled */ + LC3PLUS_EP_ZERO = 1, /*!< Error protection with 0 bit correction */ + LC3PLUS_EP_LOW = 2, /*!< Error protection correcting one symbol per codeword */ + LC3PLUS_EP_MEDIUM = 3, /*!< Error protection correcting two symbols per codeword */ + LC3PLUS_EP_HIGH = 4 /*!< Error protection correcting three symbols per codeword */ +} LC3PLUS_EpMode; + +/*! Error protection mode request. On the encoder sidem, LC3PLUS_EPMR_ZERO to LC3PLUS_EPMR_HIGH + * can be set. The decoder returns mode requests with different confidences. */ +typedef enum +{ + LC3PLUS_EPMR_ZERO = 0, /*!< Request no error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_LOW = 1, /*!< Request low error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_MEDIUM = 2, /*!< Request medium error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_HIGH = 3, /*!< Request high error correction. High confidence if returned by decoder. */ + LC3PLUS_EPMR_ZERO_MC = 4, /*!< No error correction requested, medium confidence. */ + LC3PLUS_EPMR_LOW_MC = 5, /*!< Low error correction requested, medium confidence. */ + LC3PLUS_EPMR_MEDIUM_MC = 6, /*!< Medium error correction requested, medium confidence. */ + LC3PLUS_EPMR_HIGH_MC = 7, /*!< High error correction requested, medium confidence. */ + LC3PLUS_EPMR_ZERO_NC = 8, /*!< No error correction requested, unvalidated. */ + LC3PLUS_EPMR_LOW_NC = 9, /*!< Low error correction requested, unvalidated. */ + LC3PLUS_EPMR_MEDIUM_NC = 10, /*!< Medium error correction requested, unvalidated. */ + LC3PLUS_EPMR_HIGH_NC = 11 /*!< High error correction requested, unvalidated. */ +} LC3PLUS_EpModeRequest; + +/*! Error codes returned by functions. */ +typedef enum +{ + LC3PLUS_OK = 0, /*!< No error occurred */ + LC3PLUS_ERROR = 1, /*!< Function call failed */ + LC3PLUS_DECODE_ERROR = 2, /*!< Frame failed to decode and was concealed */ + LC3PLUS_NULL_ERROR = 3, /*!< Pointer argument is null */ + LC3PLUS_SAMPLERATE_ERROR = 4, /*!< Invalid samplerate value */ + LC3PLUS_CHANNELS_ERROR = 5, /*!< Invalid channels value */ + LC3PLUS_BITRATE_ERROR = 6, /*!< Invalid bitrate value */ + LC3PLUS_NUMBYTES_ERROR = 7, /*!< Invalid num_bytes value */ + LC3PLUS_EPMODE_ERROR = 8, /*!< Invalid plc_method value */ + LC3PLUS_FRAMEMS_ERROR = 9, /*!< Invalid epmode value */ + LC3PLUS_ALIGN_ERROR = 10, /*!< Invalid frame_ms value */ + LC3PLUS_HRMODE_ERROR = 11, /*!< Unaligned pointer */ + LC3PLUS_BITRATE_UNSET_ERROR = 12, /*!< Invalid epmr value */ + LC3PLUS_BITRATE_SET_ERROR = 13, /*!< Invalid usage of hrmode, sampling rate and frame size */ + LC3PLUS_HRMODE_BW_ERROR = 14, /*!< Function called before bitrate has been set */ + LC3PLUS_PLCMODE_ERROR = 15, /*!< Function called after bitrate has been set */ + LC3PLUS_EPMR_ERROR = 16, /*!< Invalid external bad frame index */ + LC3PLUS_PADDING_ERROR = 17, /*!< Incorrect padding value */ + FRAMESIZE_ERROR = 18, /*!< Incorrect frame size during decoding */ + LC3PLUS_LFE_MODE_NOT_SUPPORTED = 19, /*!< LFE support not available */ + + /* START WARNING */ + LC3PLUS_WARNING = 20, + LC3PLUS_BW_WARNING = 21 /*!< Invalid bandwidth cutoff frequency */ + +} LC3PLUS_Error; + +typedef struct LC3PLUS_Enc LC3PLUS_Enc; /*!< Opaque encoder struct. */ +typedef struct LC3PLUS_Dec LC3PLUS_Dec; /*!< Opaque decoder struct. */ + +/*! \addtogroup Misc + * \{ */ + +/*! Test LFE mode support. + * + * Tests the support of the LFE mode. + * + * \return 1 for true, 0 for false. + */ +int32_t lc3_enc_supported_lfe(void); + +/*! Return library version number. It should match LC3PLUS_VERSION. */ +int lc3plus_version(void); + +/*! Tests if the library supports number of channels. + * + * \param[in] channels Number of channels. + * \return 1 for true, 0 for false. + */ +int lc3plus_channels_supported(int channels); + +/*! Tests if the library supports a sampling rate. + * + * \param[in] samplerate Sampling rate + * \return 1 for true, 0 for false + */ +int lc3plus_samplerate_supported(int samplerate); + +/*! \} + * \addtogroup Encoder + * \{ */ + +/*! + * Initialize LC3plus encoder. + * + * This function is used to fill a user-allocated encoder struct. This is typically + * called once for a samplerate / channel configuration. After init and before encoding + * the first frame you must call lc3plus_enc_set_bitrate(). + * + * \param[out] encoder Pointer to allocated encoder memory. It must have a size provided + * by lc3plus_enc_get_size() for matching samplerate / channels + * configuration or LC3PLUS_ENC_MAX_SIZE. + * \param[in] channels Number of channels. + * \param[in] samplerate Input sampling rate. Allowed sampling rates are: + * 8000, 16000, 24000, 32000, 44100, 48000 + * \param[in] hrmode High resolution mode. + * \param[in] lfe_channel_array Array containing activation of LFE mode for each individual channel. Can be NULL if LFE activation is not required. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_init(LC3PLUS_Enc* encoder, int samplerate, int channels, int hrmode, int32_t lfe_channel_array[]); + +/*! + * Encode LC3plus frame with 16 bit input. + * + * Each call consumes a fixed number of samples. The number of input samples + * can be obtained from lc3plus_enc_get_input_samples(). + * Scratch parameter only works as dummy parameter to align fixed-point and floating-point APIs + * + * \param[in] encoder Encoder handle initialized by lc3plus_enc_init(). + * \param[in] input_samples Input samples. The left channel is stored in input_samples[0], + * the right channel in input_samples[1]. The input is not changed + * by the encoder. + * \param[out] output_bytes Output buffer. It must have a at least lc3plus_enc_get_num_bytes() + * or at most LC3PLUS_MAX_BYTES. + * \param[out] num_bytes Number of bytes written to output_bytes. + * \param scratch See comment above. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc16(LC3PLUS_Enc* encoder, int16_t** input_samples, void* output_bytes, int* num_bytes +, void *scratch +); + +/*! Encode LC3plus frame with 24 bit input. + * + * The input samples are expected to be 24-bit values, sign-extended to 32-bit. + * See lc3plus_enc16() for parameter documentation. + */ +LC3PLUS_Error lc3plus_enc24(LC3PLUS_Enc* encoder, int32_t** input_samples, void* output_bytes, int* num_bytes +, void *scratch +); + +/*! + * Internal function. Use lc3plus_enc16() or lc3plus_enc24() for encoding. + */ + +LC3PLUS_Error lc3plus_enc_fl(LC3PLUS_Enc* encoder, void** input_samples, int bitdepth, void* output_bytes, int* num_bytes); + +/*! Get the size of the LC3plus encoder struct for a samplerate / channel + * configuration. If memory is not restricted LC3PLUS_ENC_MAX_SIZE can be used for + * all configurations. + * + * \param[in] samplerate Sampling rate. + * \param[in] channels Number of channels. + * \return Size in bytes or 0 on error. + */ +int lc3plus_enc_get_size(int samplerate, int channels); + +/*! Dummy function as no scratch management available in floating-point code. Returns always zero. Used to align fixed-point and floating-point APIs. + * + * \param[in] encoder Encoder handle. + * \return Size in bytes or 0 on error. + */ +int lc3plus_enc_get_scratch_size(const LC3PLUS_Enc *encoder); + +/*! Get number of samples per channel expected by lc3plus_enc16() or lc3plus_enc24(). + * + * \param[in] encoder Encoder handle. + * \return Number of samples or 0 on error. + */ +int lc3plus_enc_get_input_samples(const LC3PLUS_Enc* encoder); + +/*! Get real internal bitrate of the encoder. It might differ from the requested + * bitrate due to 44.1 kHz input. + * + * \param[in] encoder Encoder handle. + * \return Bitrate in bits per second or 0 on error. + */ +int lc3plus_enc_get_real_bitrate(const LC3PLUS_Enc* encoder); + +/*! Get the maximum number of bytes produced by lc3plus_enc16() or lc3plus_enc24() for the current + * bitrate. It should be equal to the num_bytes output of lc3plus_enc16/24(). + * + * \param[in] encoder Encoder handle. + * \return Size in bytes or 0 on error. + */ +int lc3plus_enc_get_num_bytes(const LC3PLUS_Enc *encoder); + +/*! Set encoder bitrate for all channels. + * This function must be called at least once before encoding the first frame, but + * after other configuration functions such as lc3plus_enc_set_frame_ms(). + * + * Recommended bitrates for input sampling rates with 10 ms framing: + * kHz | kbps + * --------|----- + * 8 | 24 + * 16 | 32 + * 24 | 48 + * 32 | 64 + * 44.1/48 | 80(voice) 128(music) + * 96 | 128 + * + * \param[in] encoder Encoder handle. + * \param[in] bitrate Bitrate in bits per second. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_bitrate(LC3PLUS_Enc* encoder, int bitrate); + +/*! Get the encoder delay in number of samples. + * + * \param[in] encoder Encoder handle. + * \return Encoder in samples or 0 on error. + */ +int lc3plus_enc_get_delay(const LC3PLUS_Enc *encoder); + +/*! Set the frame length for LC3plus decoder in deci milliseconds. + * Not all lengths may be enabled, in that case LC3PLUS_FRAMEMS_ERROR is returned. + * This only works correcly if the encoder was configured with the same vale. + * + * \param[in] decoder Decoder handle. + * \param[in] frame_ms Frame length in ms. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_frame_dms(LC3PLUS_Enc *encoder, int frame_ms); + + +/*! Set encoder Low-frequency effect moded. deactivates LTPF, TNS, NF + * + * \param[in] encoder Encoder handle. + * \param[in] lfe LFE mode flag + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_lfe(LC3PLUS_Enc* encoder, int lfe); + +/*! Free memory allocated within LC3plus encoder struct. + * + * \param[in] encoder Encoder handle. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_free_memory(LC3PLUS_Enc* encoder); + +/*! Set encoder bandwidth to a different value. All frequency bins above the cutoff + * frequency are cut off. Allowed frequencies are: 4 kHz, 8 kHz, 12 kHz, 16 kHz and 24 kHz. + * + * \param[in] encoder Encoder handle. + * \param[in] bandwidth Cutoff Frequency in Hz + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_bandwidth(LC3PLUS_Enc *encoder, int bandwidth); + +/*! Internal function called by lc3plus_enc_free_memory. + * + * \param[in] encoder Encoder handle. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_free_encoder_structs(LC3PLUS_Enc* encoder); + +/*! Sets error protection mode request transmitted in each channel encoded frame. + * The channel coder includes an error protection mode request (EPMR) in every frame. + * The EPMR takes value 0, 1, 2, and 3 which request ep modes 1, 2, 3, and 4 from the + * decoding device. The EPMR can be retrieved from the channel decoder via the interface + * routine lc3plus_dec_get_ep_mode_request(). + * + * \param[in] encoder Encoder handle. + * \param[in] epmr Error Protection Mode Request + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_ep_mode_request(LC3PLUS_Enc *encoder, LC3PLUS_EpModeRequest epmr); + +/*! Set error protection mode. The default is LC3PLUS_EP_OFF. It is possible to switch between + * different modees during encoding. Dynamic switching is only allowed between LC3PLUS_EP_ZERO, + * LC3PLUS_EP_LOW, LC3_EP_MEDIUM, and LC3PLUS_EP_HIGH. The the decoder must be notified with + * lc3plus_dec_set_ep_enabled() to expect protected data if epmode is other than LC3PLUS_EP_OFF. + * + * \param[in] encoder Encoder handle. + * \param[in] epmode Error protection mode. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_enc_set_ep_mode(LC3PLUS_Enc *encoder, LC3PLUS_EpMode epmode); + +/*! \} + * \addtogroup Decoder + * \{ */ + +/*! + * Initialize LC3plus decoder. + * + * This function is used to fill a user-allocated decoder struct. This is + * typically called once for a samplerate / channel configuration. + * + * The samplerate and channel arguments must have the same values that were + * used for encoding. LC3plus does not provide a signalling scheme, transporting + * these values is the responsibility of the application. + * + * \param[out] decoder Pointer to decoder memory. It must have as size + * of least lc3plus_dec_get_size() or at most LC3PLUS_DEC_MAX_SIZE. + * \param[in] samplerate Bitstream sampling rate. \param[in] channels Bitstream + * number of channels. + * + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_init(LC3PLUS_Dec* decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode, int hrmode); + + + +/*! + * Decode compressed LC3plus frame to 16 bit PCM output. + * + * Each call decodes a fixed number of samples. Use lc3plus_dec_get_output_samples() to obtain this + * number. When the input is corrupted and can not be decoded, LC3PLUS_DECODE_ERROR is returned and + * packet loss concealment is applied, so the output is still usable. + * If error protection is enabled and the errors can be corrected the frame is corrected and + * normally decoded. Use lc3plus_dec_get_error_report() to check if errors were corrected. + * + * \param[in] decoder Decoder initialized by lc3plus_dec_init(). + * \param[in] input_bytes Input bytes. If error protection is enabled the input bytes can be + * altered when error correction is applied. This is why this buffer + * must be writable. + * \param[in] num_bytes Number of valid bytes in input_bytes. To signal a lost frame and + * generate concealment output this value must be set to 0. + * \param[out] output_samples Array of pointers to output channel buffers. Each channel buffer + * should provide enough space to hold at most LC3PLUS_MAX_SAMPLES. The + * left channel is stored in output_samples[0], the right channel in + * output_samples[1]. + * \param scratch Scratch parameter only works as dummy parameter to align fixed-point and floating-point APIs. + * \param[in] bfi_ext Bad Frame Indicator. 0: Good Frame. 1: Bad Frame, apply PLC. + * \return Returns LC3PLUS_OK on success or appropriate error code. Note there is + * a special case for LC3PLUS_DECODE_ERROR where the output is still valid. + */ +LC3PLUS_Error lc3plus_dec16(LC3PLUS_Dec* decoder, void* input_bytes, int num_bytes, int16_t** output_samples, + void* scratch, + int bfi_ext); + +/*! Decode compressed LC3plus frame to 24 bit PCM output. + * + * The output samples are 24-bit values, sign-extended to 32-bit. + * See lc3plus_dec16() for parameter documentation. + */ +LC3PLUS_Error lc3plus_dec24(LC3PLUS_Dec* decoder, void* input_bytes, int num_bytes, int32_t** output_samples, + void* scratch, + int bfi_ext); + +/* Internal function */ + LC3PLUS_Error lc3plus_dec_fl(LC3PLUS_Dec* decoder, void* input_bytes, int num_bytes, void** output_samples, int bps, int bfi_ext); + +/*! Get the size of the LC3plus decoder struct for a samplerate / channel + * configuration. If memory is not restricted LC3PLUS_DEC_MAX_SIZE can be used for + * all configurations. + * + * \param[in] channels Number of channels. + * \param[in] samplerate Sampling rate. + * \return Size in bytes or 0 on error. + */ +int lc3plus_dec_get_size(int samplerate, int channels); + +/*! Dummy function as no scratch management available in floating-point code. Returns always zero. Used to align fixed-point and floating-point APIs. + * + * \param[in] decoder Decoder handle. + * \return Size in bytes or 0 on error. + */ +int lc3plus_dec_get_scratch_size(const LC3PLUS_Dec *decoder); + +/*! Get the number of samples per channel produced by lc3plus_dec16() or lc3plus_dec24. + * + * \param[in] decoder Decoder handle. + * \return Number of samples or 0 on error. + */ +int lc3plus_dec_get_output_samples(const LC3PLUS_Dec* decoder); + +/*! Get the decoder delay in number of samples. + * + * \param[in] decoder Decoder handle. + * \return Delay in samples or 0 on error. + */ +int lc3plus_dec_get_delay(const LC3PLUS_Dec* decoder); + +/*! Set the frame length for LC3plus encoder in deci milliseconds. + * Not all lengths may be enabled, in that case LC3PLUS_FRAMEMS_ERROR is returned. + * This function must be called before lc3plus_enc_set_bitrate(). The decoder must be + * configured with lc3plus_dec_set_frame_dms() with the same value. + * + * \param[in] encoder Encoder handle. + * \param[in] frame_ms Frame length in ms. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_set_frame_dms(LC3PLUS_Dec *decoder, int frame_ms); + + +/*! Free memory allocated within LC3plus decoder struct. + * + * \param[in] decoder Decoder handle. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_free_memory(LC3PLUS_Dec* decoder); + +/*! Internal function called by lc3plus_dec_free_memory. + * + * \param[in] decoder Decoder handle. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_free_decoder_structs(LC3PLUS_Dec* decoder); + +/*! Enable or disable error protection. Default value is 0 (disabled). If error protection is + * enabled, the decoder expects that the frames were encoded with error protection mode + * LC3PLUS_EP_ZERO or higher. + * + * \param[in] decoder Decoder handle. + * \param[in] ep_enabled 1 (or any nonzero) for true, 0 for false. + * \return LC3PLUS_OK on success or appropriate error code. + */ +LC3PLUS_Error lc3plus_dec_set_ep_enabled(LC3PLUS_Dec *decoder, int ep_enabled); + +/*! Retrieves the error protection mode reqeust from channel decoder. + * + * The return value encodes both the error protection mode request (EPMR) + * and the confidence of the method by which it was retrieved. + * + * The requested error protection mode is (epmr % 4) + 1, where epmr is the + * function's return value. The confidence is specified as follows. + * + * Confidence | Range + * -----------|------------- + * high | 0 <= epmr < 4 + * medium | 4 <= epmr < 8 + * no | 8 <= epmr < 12 + * + * When receiving stereo content of separately channel encoded audio frames the + * return value is the minimum of two values retrieved from the individual channels. + * + * \param[in] decoder Decoder handle. + * \return Error protection mode reqeust. + */ +LC3PLUS_EpModeRequest lc3plus_dec_get_ep_mode_request(const LC3PLUS_Dec *decoder); + +/*! Get the number of corrected bit errors in the last decoded frame. This only works if + * error protection is active. If the number of errors is greater than the current error + * protection mode can correct, -1 is returned. If the last frame had no errors or the + * decoder handle is NULL, 0 is returned, + * + * \param[in] decoder Decoder handle. + * \return Number of corrected bits or -1. See description for details. + */ +int lc3plus_dec_get_error_report(const LC3PLUS_Dec *decoder); +/*! This function returns an set of flags indicating whether the last frame + * would have been channel decodable in epmode m, m ranging from 1 to 4. Note that + * this information is not available in case the last frame was not channel + * decodable in which case the return value is 0. If the last frame would have + * been decodable in epmode m, m-1th of the return value will be 1. + * Otherwise, if the frame would not have been decodable or if this information + * cannot be retrieved, the m-1th bit of the return value will be 0. + */ +int lc3plus_dec_get_epok_flags(const LC3PLUS_Dec *decoder); + +/*! \} */ +#endif /* LC3plus */ diff --git a/lib_lc3plus/setup_com_lc3plus.c b/lib_lc3plus/setup_com_lc3plus.c new file mode 100644 index 0000000000..f37af56a31 --- /dev/null +++ b/lib_lc3plus/setup_com_lc3plus.c @@ -0,0 +1,31 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "options.h" +#include "wmc_auto.h" +#include "functions.h" + +LC3_FLOAT array_max_abs(LC3_FLOAT *in, LC3_INT32 len) +{ + LC3_FLOAT max; + LC3_INT32 i; + + max = LC3_FABS(in[0]); + + for (i = 0; i < len; i++) + { + if (LC3_FABS(in[i]) > LC3_FABS(max)) + { + max = LC3_FABS(in[i]); + } + } + + return max; +} + diff --git a/lib_lc3plus/setup_dec_lc3plus.c b/lib_lc3plus/setup_dec_lc3plus.c new file mode 100644 index 0000000000..9e9a5ea64e --- /dev/null +++ b/lib_lc3plus/setup_dec_lc3plus.c @@ -0,0 +1,512 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "options.h" +#include "wmc_auto.h" +#include "setup_dec_lc3plus.h" +#include "functions.h" +#include +#include + +/* if decoder is null only size is reported */ +#include "fft/iis_fft.h" + +int alloc_decoder(LC3PLUS_Dec* decoder, int samplerate, int channels) +{ + int ch = 0; + size_t size = sizeof(LC3PLUS_Dec); + size_t frame_len = DYN_MAX_LEN_EXT(samplerate); + + void *PlcAdvSetup = NULL; + LC3_FLOAT *pcmbufHist, *harmonicBuf; + LC3_FLOAT *PhECU_oold_grp_shape, *PhECU_old_grp_shape; + LC3_FLOAT *PhECU_xfp; + Complex *PhECU_X_sav_m; + LC3_INT32 *PhECU_plocs; + LC3_FLOAT *PhECU_f0est, *PhECU_mag_chg_1st, *PhECU_Xavg; + LC3_FLOAT *sine_table1_phecu, *sine_table2_phecu; + HANDLE_IIS_FFT handle_fft_phaseecu; + HANDLE_IIS_FFT handle_ifft_phaseecu; + LC3_FLOAT *q_old_res; + + LC3_INT32 * plc_longterm_advc_tdc = NULL, *plc_longterm_advc_ns = NULL; + LC3_INT16 longterm_analysis_counter_max = 0, longterm_analysis_counter_max_bytebuffer = 0; + + for (ch = 0; ch < channels; ch++) { + DecSetup* setup = balloc(decoder, &size, sizeof(DecSetup)); + + size_t max_pitch = ceilf(228.0 * CODEC_FS(samplerate) / 12800.0); + size_t pcm_plc_len = max_pitch + frame_len; + pcmbufHist = balloc(decoder, &size, sizeof(LC3_FLOAT) * pcm_plc_len); + harmonicBuf = balloc(decoder, &size, sizeof(LC3_FLOAT) * max_pitch); + PlcAdvSetup = balloc(decoder, &size, sizeof(*setup->PlcAdvSetup)); + PhECU_oold_grp_shape = balloc(decoder, &size, sizeof(LC3_FLOAT) *MAX_LGW); /* BASOP Word16 PhECU_oold_grp_shape_fx[MAX_LGW]; */ + PhECU_old_grp_shape = balloc(decoder, &size, sizeof(LC3_FLOAT) *MAX_LGW); /* BASOP Word16 PhECU_old_grp_shape_fx[MAX_LGW] ; */ + PhECU_xfp = balloc(decoder, &size, sizeof(LC3_FLOAT) *(frame_len * 16 / 10)); + PhECU_X_sav_m = balloc(decoder, &size, sizeof(Complex) *(((frame_len * 16 / 10) / 2) + 1));/*MAX_PLC_LMSPEC*/ + PhECU_plocs = balloc(decoder, &size, sizeof(LC3_INT32) * (((frame_len * 16 / 10) / 4) + 1 + 1)); /* BASOP Word16 *PhECU_plocs; */ + + handle_fft_phaseecu = balloc(decoder, &size, sizeof(IIS_FFT) * 1); + handle_ifft_phaseecu = balloc(decoder, &size, sizeof(IIS_FFT) * 1); + PhECU_f0est = balloc(decoder, &size, sizeof(LC3_FLOAT) * (((frame_len * 16 / 10) / 4) + 1)); /*BASOP Word32 *PhECU_f0est;*/ + PhECU_mag_chg_1st = balloc(decoder, &size, sizeof(LC3_FLOAT) *MAX_LGW); /* BASOP Word16 PhECU_mag_chg_1st[MAX_LGW];*/ + PhECU_Xavg = balloc(decoder, &size, sizeof(LC3_FLOAT) * MAX_LGW); /* BASOP Word16 PhECU_Xavg[MAX_LGW] ; */ + + sine_table1_phecu = balloc(decoder, &size, sizeof(LC3_FLOAT) * (((CODEC_FS(samplerate) * 16) / 1000) / 2 + 1)); + sine_table2_phecu = balloc(decoder, &size, sizeof(LC3_FLOAT) * (((CODEC_FS(samplerate) * 16) / 1000) / 2 + 1)); + + longterm_analysis_counter_max = plc_fadeout_param_maxlen[0]; + longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[0]; + + plc_longterm_advc_tdc = balloc(decoder, &size, sizeof(LC3_INT32) * longterm_analysis_counter_max_bytebuffer); + plc_longterm_advc_ns = balloc(decoder, &size, sizeof(LC3_INT32) * longterm_analysis_counter_max_bytebuffer); + + q_old_res = balloc(decoder, &size, sizeof(LC3_FLOAT) * frame_len); + + if (decoder) { + decoder->channel_setup[ch] = setup; + + setup->PlcAdvSetup = PlcAdvSetup; + + setup->PlcAdvSetup->pcmbufHist = pcmbufHist; + setup->PlcAdvSetup->PlcTdcSetup.harmonicBuf = harmonicBuf; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_oold_grp_shape = PhECU_oold_grp_shape; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_old_grp_shape = PhECU_old_grp_shape; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_xfp = PhECU_xfp; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_X_sav_m = PhECU_X_sav_m; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_plocs = PhECU_plocs; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_f0est = PhECU_f0est; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_mag_chg_1st = PhECU_mag_chg_1st; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Xavg = PhECU_Xavg; + setup->PlcAdvSetup->PlcPhEcuSetup.handle_fft_phaseecu = handle_fft_phaseecu; + setup->PlcAdvSetup->PlcPhEcuSetup.handle_ifft_phaseecu = handle_ifft_phaseecu; + + setup->PlcAdvSetup->PlcPhEcuSetup.handle_fft_phaseecu->sine_table = sine_table1_phecu; + setup->PlcAdvSetup->PlcPhEcuSetup.handle_ifft_phaseecu->sine_table = sine_table2_phecu; + + setup->PlcAdvSetup->longterm_analysis_counter_max = longterm_analysis_counter_max; + setup->PlcAdvSetup->longterm_analysis_counter_max_bytebuffer = longterm_analysis_counter_max_bytebuffer; + + setup->PlcAdvSetup->plc_longterm_advc_tdc = plc_longterm_advc_tdc; + setup->PlcAdvSetup->plc_longterm_advc_ns = plc_longterm_advc_ns; + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot = (CODEC_FS(samplerate) * 16) / 1000; + real_fft_init(&(setup->PlcAdvSetup->PlcPhEcuSetup.PhEcu_Fft), setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot, &(setup->PlcAdvSetup->PlcPhEcuSetup.handle_fft_phaseecu)); + real_ifft_init(&(setup->PlcAdvSetup->PlcPhEcuSetup.PhEcu_Ifft), setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot, &(setup->PlcAdvSetup->PlcPhEcuSetup.handle_ifft_phaseecu)); + setup->statePC.q_old_res = q_old_res; + } + } + + return (int)size; +} + +LC3PLUS_Error FillDecSetup(LC3PLUS_Dec* decoder, int samplerate, int channels, LC3PLUS_PlcMode plc_mode + , int hrmode +) +{ + memset(decoder, 0, lc3plus_dec_get_size(samplerate, channels)); + alloc_decoder(decoder, samplerate, channels); + + decoder->fs = CODEC_FS(samplerate); + decoder->fs_out = samplerate; + decoder->fs_idx = FS2FS_IDX(decoder->fs); + decoder->plcMeth = plc_mode; + + decoder->hrmode = hrmode != 0; + + decoder->channels = channels; + decoder->frame_ms = 10; + decoder->frame_dms = 100; + decoder->BW_cutoff_bits = BW_cutoff_bits_all[decoder->fs_idx]; + + if (decoder->fs == 8000) { + decoder->tilt = 14; + } else if (decoder->fs == 16000) { + decoder->tilt = 18; + } else if (decoder->fs == 24000) { + decoder->tilt = 22; + } else if (decoder->fs == 32000) { + decoder->tilt = 26; + } else if (decoder->fs == 48000) { + decoder->tilt = 30; + } + else if (decoder->fs == 96000) { + decoder->tilt = 34; + } + + set_dec_frame_params(decoder); + + lc3plus_dec_set_ep_enabled(decoder, 0); + + return LC3PLUS_OK; +} + +/* set frame config params */ +void set_dec_frame_params(LC3PLUS_Dec* decoder) +{ + int ch = 0; + int n; + + if (decoder->fs_idx == 5) + { + decoder->hrmode = 1; + } + + decoder->frame_length = ceil(decoder->fs * 10 / 1000); /* fs * 0.01*2^6 */ + if (decoder->hrmode == 1) + { + decoder->yLen = decoder->frame_length; + } + else + { + decoder->yLen = MIN(MAX_BW, decoder->frame_length); + } + + decoder->bands_number = 64; + if (decoder->frame_ms == 2.5) + { + decoder->frame_length = decoder->frame_length >> 2; + decoder->yLen /= 4; + if (decoder->hrmode) + { + decoder->bands_number = bands_number_2_5ms_HR[decoder->fs_idx]; + } + else + { + decoder->bands_number = bands_number_2_5ms[decoder->fs_idx]; + } + } + if (decoder->frame_ms == 5) + { + decoder->frame_length = decoder->frame_length >> 1; + decoder->yLen /= 2; + decoder->bands_number = bands_number_5ms[decoder->fs_idx]; + } + if (decoder->frame_ms == 7.5) + { + decoder->frame_length = (decoder->frame_length >> 2) * 3; + decoder->yLen = (decoder->yLen / 4) * 3; + if (decoder->hrmode) + { + decoder->bands_number = bands_number_7_5ms_HR[decoder->fs_idx]; + } + else + { + decoder->bands_number = bands_number_7_5ms[decoder->fs_idx]; + } + } + + if (decoder->hrmode) + { + decoder->BW_cutoff_bits = 0; + } + else + { + decoder->BW_cutoff_bits = BW_cutoff_bits_all[decoder->fs_idx]; + } + + if (decoder->frame_ms == 10) + { + if (decoder->hrmode) + { + decoder->bands_offset = ACC_COEFF_PER_BAND_HR[decoder->fs_idx]; + } + else + { + decoder->bands_offset = ACC_COEFF_PER_BAND[decoder->fs_idx]; + } + decoder->cutoffBins = BW_cutoff_bin_all; + } + else if (decoder->frame_ms == 2.5) + { + if (decoder->hrmode) + { + decoder->bands_offset = ACC_COEFF_PER_BAND_2_5ms_HR[decoder->fs_idx]; + } + else + { + decoder->bands_offset = ACC_COEFF_PER_BAND_2_5ms[decoder->fs_idx]; + } + decoder->cutoffBins = BW_cutoff_bin_all_2_5ms; + } + else if (decoder->frame_ms == 5) + { + if (decoder->hrmode) + { + decoder->bands_offset = ACC_COEFF_PER_BAND_5ms_HR[decoder->fs_idx]; + } + else + { + decoder->bands_offset = ACC_COEFF_PER_BAND_5ms[decoder->fs_idx]; + } + decoder->cutoffBins = BW_cutoff_bin_all_5ms; + } + else if (decoder->frame_ms == 7.5) + { + if (decoder->hrmode) + { + decoder->bands_offset = ACC_COEFF_PER_BAND_7_5ms_HR[decoder->fs_idx]; + } + else + { + decoder->bands_offset = ACC_COEFF_PER_BAND_7_5ms[decoder->fs_idx]; + } + decoder->cutoffBins = BW_cutoff_bin_all_7_5ms; + } + + decoder->n_bandsPLC = MIN(decoder->frame_length, 80); + + if (decoder->frame_ms == 10) + { + decoder->bands_offsetPLC = ACC_COEFF_PER_BAND_PLC[decoder->fs_idx]; + } + else if (decoder->frame_ms == 5) + { + decoder->bands_offsetPLC = ACC_COEFF_PER_BAND_PLC_5ms[decoder->fs_idx]; + + if (decoder->fs == 24000) + { + decoder->n_bandsPLC = 40; + } + } + else if (decoder->frame_ms == 2.5) + { + decoder->bands_offsetPLC = ACC_COEFF_PER_BAND_PLC_2_5ms[decoder->fs_idx]; + + if (decoder->fs == 48000) + { + decoder->n_bandsPLC = 60; + } + } + else if (decoder->frame_ms == 7.5) + { + decoder->bands_offsetPLC = ACC_COEFF_PER_BAND_PLC_7_5ms[decoder->fs_idx]; + + if (decoder->fs != 32000 && decoder->fs != 96000) + { + decoder->n_bandsPLC = 60; + } + } + + assert(decoder->bands_offsetPLC); + + if (decoder->frame_ms == 10) { + decoder->imdct_win = MDCT_WINS_10ms[decoder->hrmode][decoder->fs_idx]; + decoder->imdct_laZeros = MDCT_la_zeroes[decoder->fs_idx]; + decoder->imdct_winLen = MDCT_WINDOWS_LENGTHS_10ms[decoder->fs_idx]; + } + else if (decoder->frame_ms == 2.5) { + decoder->imdct_win = MDCT_WINS_2_5ms[decoder->hrmode][decoder->fs_idx]; + decoder->imdct_laZeros = MDCT_la_zeroes_2_5ms[decoder->fs_idx]; + decoder->imdct_winLen = MDCT_WINDOWS_LENGTHS_2_5ms[decoder->fs_idx]; + } + else if (decoder->frame_ms == 5) { + decoder->imdct_win = MDCT_WINS_5ms[decoder->hrmode][decoder->fs_idx]; + decoder->imdct_laZeros = MDCT_la_zeroes_5ms[decoder->fs_idx]; + decoder->imdct_winLen = MDCT_WINDOWS_LENGTHS_5ms[decoder->fs_idx]; + } + else if (decoder->frame_ms == 7.5) { + decoder->imdct_win = MDCT_WINS_7_5ms[decoder->hrmode][decoder->fs_idx]; + decoder->imdct_laZeros = MDCT_la_zeroes_7_5ms[decoder->fs_idx]; + decoder->imdct_winLen = MDCT_WINDOWS_LENGTHS_7_5ms[decoder->fs_idx]; + } + + decoder->la_zeroes = decoder->imdct_laZeros; + + decoder->imdct_memLen = decoder->frame_length - decoder->imdct_laZeros; + + for (ch = 0; ch < decoder->channels; ch++) { + DecSetup* setup = decoder->channel_setup[ch]; + + setup->ltpf_mem_beta_idx = -1; + + setup->statePC.seed = 24607; + + if (decoder) { + /* Init DCT4 structs */ + if (setup->dct4structImdct.length != 0) { + dct4_free(&setup->dct4structImdct); + dct4_init(&setup->dct4structImdct, decoder->frame_length); + } else { + dct4_init(&setup->dct4structImdct, decoder->frame_length); + } + + setup->PlcNsSetup.cum_alpha = 1; + setup->PlcNsSetup.seed = 24607; + setup->alpha = 1; + if (setup->PlcAdvSetup) + { + LC3_INT32 pitch_max = 0, pitch_ana_len = 0, tdc_synt_len = 0; + pitch_max = ceil(228.0 * (LC3_FLOAT) decoder->fs / 12800.0); + pitch_ana_len = pitch_max + decoder->frame_length * (LC3_FLOAT) 100 / decoder->frame_dms; + tdc_synt_len = 16 + 1 + pitch_max + ceil(decoder->frame_length / 2); + setup->PlcAdvSetup->max_len_pcm_plc = MAX(pitch_ana_len, tdc_synt_len); + setup->PlcAdvSetup->PlcTdcSetup.preemphFac = plc_preemph_fac[decoder->fs_idx]; + setup->PlcAdvSetup->PlcTdcSetup.seed = 24607; + setup->PlcAdvSetup->PlcTdcSetup.lpcorder = 16; + + if (decoder->fs_idx == 0 && decoder->frame_dms == 25) + { + setup->PlcAdvSetup->PlcTdcSetup.lpcorder = 8; + } + + setup->PlcAdvSetup->stabFac = 1; + setup->PlcAdvSetup->cum_fading_fast = 1; + setup->PlcAdvSetup->cum_fading_slow = 1; + setup->PlcAdvSetup->cum_fflcAtten = 1; + + setup->PlcAdvSetup->longterm_analysis_counter_max = plc_fadeout_param_maxlen[(decoder->frame_dms / 25) - 1]; + setup->PlcAdvSetup->longterm_analysis_counter_max_bytebuffer = plc_fadeout_param_maxbytes[(decoder->frame_dms / 25) - 1]; + + if (decoder->fs_idx <= 4 && decoder->frame_dms == 100) + { + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot = (decoder->fs * 16) / 1000; /* 16 ms of samples at fs*/ + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_f0hzLtpBin = 0; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_norm_corr = 0; + + set_vec(PHECU_GRP_SHAPE_INIT, setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_oold_grp_shape, MAX_LGW); + set_vec(PHECU_GRP_SHAPE_INIT, setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_old_grp_shape, MAX_LGW); + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_L_oold_xfp_w_E = (LC3_FLOAT)PHECU_LTOT_MIN_MAN * LC3_POW(2.0, PHECU_LTOT_MIN_EXP - 31); + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_L_old_xfp_w_E = (LC3_FLOAT)PHECU_LTOT_MIN_MAN * LC3_POW(2.0, PHECU_LTOT_MIN_EXP - 31); + + /* CFL uses separate buffers for pcmHist, xfp and Xsav and q_d , BASOP uses an optimized joint buffer*/ + zero_float(setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_xfp, setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot); + zero_cmplx(setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_X_sav_m, (setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot/2 + 1)); + + set_vec(POS_ONE_Q15, setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_mag_chg_1st, MAX_LGW); + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_beta_mute = (16384.0/32768.0); + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_seed = 21845; + + assert(decoder->frame_dms == 100); + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_LDWIN_OLAP = (decoder->frame_length / 4 ); /* 2.5 ms for regular 10 ms MDCT */ + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_t_adv = ( + decoder->frame_length + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_Lprot + + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_LDWIN_OLAP )/ 2; + } + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_short_flag_prev = 0; /* fullband transient */ + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_num_plocs = 0; + setup->PlcAdvSetup->PlcPhEcuSetup.PhECU_nonpure_tone_flag = -1; /* nonpure tone flag, -1==new calc., 0==pure, 1==nonpure */ + } + } + } + for (n=0; n < LC3_ROUND(PLC_FADEOUT_TYPE_1_IN_MS*10/decoder->frame_dms);n++){ + decoder->alpha_type_2_table[n] = type_2_fadeout(n, decoder->frame_dms); + } +} + +LC3PLUS_Error update_dec_bitrate(LC3PLUS_Dec* decoder, int ch, int nBytes) +{ + int totalBits = 0, bitsTmp = 0, channel_bytes = 0, maxBytes = 0, minBytes = 0; + DecSetup* setup; + + if (decoder->hrmode) + { + switch (decoder->frame_dms) + { + case 25: + maxBytes = 210; + minBytes = MIN_NBYTES; + break; + case 50: + maxBytes = 375; + minBytes = MIN_NBYTES; + break; + case 75: + maxBytes = 625; + minBytes = MIN_NBYTES; + break; + case 100: + maxBytes = 625; + minBytes = MIN_NBYTES; + break; + default: + return LC3PLUS_HRMODE_ERROR; + } + } + else + { + minBytes = MIN_NBYTES; + maxBytes = MAX_NBYTES_100; /* for backward compatibility, MAX_NBYTES_100 is used for all frame lengths */ + } + + channel_bytes = nBytes; + + setup = decoder->channel_setup[ch]; + + if (channel_bytes < minBytes || channel_bytes > maxBytes) + { + return LC3PLUS_NUMBYTES_ERROR; + } + + setup->targetBytes = channel_bytes; + setup->total_bits = setup->targetBytes << 3; + setup->enable_lpc_weighting = (setup->total_bits < 480); + setup->quantizedGainOff = + -(MIN(115, setup->total_bits / (10 * (decoder->fs_idx + 1))) + 105 + 5 * (decoder->fs_idx + 1)); + + if (decoder->hrmode && decoder->fs_idx == 5) + { + setup->quantizedGainOff = MAX(setup->quantizedGainOff, -181); + } + + totalBits = setup->total_bits; + + if (decoder->frame_ms == 2.5) { + setup->enable_lpc_weighting = setup->total_bits < 120; + totalBits = setup->total_bits * 4.0 * (1.0 - 0.4); + } + if (decoder->frame_ms == 5) { + setup->enable_lpc_weighting = (setup->total_bits < 240); + totalBits = setup->total_bits * 2 - 160; + } + if (decoder->frame_ms == 7.5) { + setup->enable_lpc_weighting = (setup->total_bits < 360); + totalBits = round(setup->total_bits * 10 / 7.5); + } + + if (decoder->frame_length > 40 * ((LC3_FLOAT) (decoder->frame_dms) / 10.0)) { + setup->N_red_tns = 40 * ((LC3_FLOAT) (decoder->frame_dms) / 10.0); + setup->fs_red_tns = 40000; + } else { + setup->N_red_tns = decoder->frame_length; + setup->fs_red_tns = decoder->fs; + } + + bitsTmp = totalBits; + + if (bitsTmp < 400 + (decoder->fs_idx - 1) * 80) { + setup->ltpf_conf_beta = 0.4; + setup->ltpf_conf_beta_idx = 0; + } else if (bitsTmp < 480 + (decoder->fs_idx - 1) * 80) { + setup->ltpf_conf_beta = 0.35; + setup->ltpf_conf_beta_idx = 1; + } else if (bitsTmp < 560 + (decoder->fs_idx - 1) * 80) { + setup->ltpf_conf_beta = 0.3; + setup->ltpf_conf_beta_idx = 2; + } else if (bitsTmp < 640 + (decoder->fs_idx - 1) * 80) { + setup->ltpf_conf_beta = 0.25; + setup->ltpf_conf_beta_idx = 3; + } else { + setup->ltpf_conf_beta = 0; + setup->ltpf_conf_beta_idx = -1; + } + + /* No LTPF in hrmode */ + if (decoder->hrmode == 1) { + setup->ltpf_conf_beta = 0; + setup->ltpf_conf_beta_idx = -1; + } + + return LC3PLUS_OK; +} diff --git a/lib_lc3plus/setup_dec_lc3plus.h b/lib_lc3plus/setup_dec_lc3plus.h new file mode 100644 index 0000000000..c3d26ee8eb --- /dev/null +++ b/lib_lc3plus/setup_dec_lc3plus.h @@ -0,0 +1,114 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef SETUP_DEC_LC3_FL_H +#define SETUP_DEC_LC3_FL_H + +#include "options.h" +#include "wmc_auto.h" +#include "constants.h" + +/* Channel state and bitrate-derived values go in this struct */ +typedef struct { + LC3_INT* stDec_ola_mem_fx; /* MDCT_MEM_LEN_MAX */ + LC3_INT total_bits; + LC3_INT enable_lpc_weighting; + LC3_INT targetBytes; + LC3_INT quantizedGainOff; + LC3_INT ltpf_param[3]; + LC3_INT ltpf_param_mem[3]; + LC3_INT ltpf_mem_pitch; + LC3_INT ltpf_mem_active; + LC3_INT ltpf_mem_pitch_fr; + LC3_INT ltpf_mem_beta_idx; + LC3_INT ltpf_conf_beta_idx; + LC3_INT spec_inv_idx; + LC3_INT concealMethod; + LC3_INT last_size; + LC3_INT BW_cutoff_idx_nf; + LC3_INT prev_BW_cutoff_idx_nf; + LC3_INT fs_red_tns; + LC3_INT N_red_tns; + LC3_INT scf_idx[SCF_MAX_PARAM]; + uint8_t resBits[MAX_RESBITS_LEN]; + LC3_INT tns_idx[TNS_NUMFILTERS_MAX * MAXLAG]; + + LC3_FLOAT prev_fac_ns; + LC3_FLOAT ltpf_mem_x[3 * MAX_LEN]; + LC3_FLOAT ltpf_mem_y[3 * MAX_LEN]; + LC3_FLOAT ltpf_mem_gain; + LC3_FLOAT ltpf_conf_beta; + LC3_FLOAT sqQdec_fl[MAX_LEN]; + LC3_FLOAT scf_q[M]; + LC3_FLOAT int_scf[MAX_BANDS_NUMBER]; + LC3_FLOAT x_fl[MAX_LEN]; + LC3_FLOAT imdct_mem[MAX_LEN]; + LC3_FLOAT alpha; + LC3_FLOAT rel_pitch_change; + Dct4 dct4structImdct; + + PlcSetup PlcSetup; + PlcNsSetup PlcNsSetup; + + pcState statePC; + PlcAdvSetup* PlcAdvSetup; +} DecSetup; + +/* Constants and sampling rate derived values go in this struct */ +struct LC3PLUS_Dec { + LC3_FLOAT alpha_type_2_table[PLC_FADEOUT_TYPE_1_IN_MS*10/25]; /* [80] */ + DecSetup* channel_setup[MAX_CHANNELS]; + const LC3_INT* W_fx; + const LC3_INT* bands_offset; + const LC3_INT* cutoffBins; + + LC3_INT fs; /* sampling rate, 44.1 maps to 48 */ + LC3_INT fs_out; /* output sampling rate */ + LC3_INT fs_idx; /* sampling rate index */ + LC3_INT frame_length; /* sampling rate index */ + LC3_INT channels; /* number of channels */ + LC3_FLOAT frame_ms; /* frame length in ms (wrong for 44.1) */ + LC3_INT frame_dms; /* frame length in ms * 10 (wrong for 44.1) */ + LC3_INT last_size; /* size of last frame, without error protection */ + LC3_INT ep_enabled; /* error protection enabled */ + LC3_INT error_report; /* corrected errors in last frame or -1 on error */ + + LC3_INT imdct_memLen; + LC3_INT imdct_winLen; + LC3_INT imdct_laZeros; + const LC3_FLOAT* imdct_win; + + LC3_INT yLen; + LC3_INT W_size; + LC3_INT la_zeroes; + LC3_INT bands_number; + LC3_INT ltpf_mem_x_len; + LC3_INT ltpf_mem_y_len; + LC3_INT BW_cutoff_bits; + LC3_INT tilt; + + LC3_INT hrmode; + LC3_INT specflip; + + const LC3_INT* bands_offsetPLC; + LC3_INT n_bandsPLC; + + LC3_INT32 rframe; + int plcMeth; /* PLC method for all channels */ + LC3_INT16 n_pccw; + LC3_INT16 be_bp_left; + LC3_INT16 be_bp_right; + LC3_INT16 n_pc; + LC3_INT16 m_fec; + int epmr; + LC3_INT16 combined_channel_coding; + int last_error; +}; + +#endif diff --git a/lib_lc3plus/setup_enc_lc3plus.c b/lib_lc3plus/setup_enc_lc3plus.c new file mode 100644 index 0000000000..80bd909ab3 --- /dev/null +++ b/lib_lc3plus/setup_enc_lc3plus.c @@ -0,0 +1,610 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#include "options.h" +#include "wmc_auto.h" +#include "setup_enc_lc3plus.h" +#include "functions.h" +#include + +/* if encoder is null only size is reported */ +int alloc_encoder(LC3PLUS_Enc* encoder, int channels) +{ + int ch = 0; + size_t size = sizeof(LC3PLUS_Enc); + + for (ch = 0; ch < channels; ch++) { + EncSetup* setup = balloc(encoder, &size, sizeof(EncSetup)); + if (encoder) { + encoder->channel_setup[ch] = setup; + } + } + + return (int)size; +} + +LC3PLUS_Error FillEncSetup(LC3PLUS_Enc* encoder, int samplerate, int channels + , int hrmode + , int32_t lfe_channel_array[] +) +{ + int ch = 0; + memset(encoder, 0, lc3plus_enc_get_size(samplerate, channels)); + alloc_encoder(encoder, channels); + + encoder->fs = CODEC_FS(samplerate); + encoder->fs_in = samplerate; + encoder->fs_idx = FS2FS_IDX(encoder->fs); + encoder->frame_dms = 100; + + if (encoder->fs_idx > 4) { + encoder->fs_idx = 5; + } + + encoder->hrmode = hrmode != 0; + + encoder->channels = channels; + encoder->frame_ms = 10; + encoder->envelope_bits = 38; + encoder->global_gain_bits = 8; + encoder->noise_fac_bits = 3; + encoder->BW_cutoff_bits = BW_cutoff_bits_all[encoder->fs_idx]; + + encoder->r12k8_mem_in_len = 2 * 8 * encoder->fs / 12800; + encoder->r12k8_mem_out_len = 24; + + if (lfe_channel_array != NULL) + { + for (ch = 0; ch < encoder->channels; ch++) + { + encoder->channel_setup[ch]->lfe = lfe_channel_array[ch] != 0; + } + } + + encoder->bw_ctrl_active = 0; + encoder->bandwidth = encoder->fs / 2; + encoder->bandwidth_preset = encoder->fs / 2; + + + if (encoder->fs == 8000) { + encoder->tilt = 14; + } else if (encoder->fs == 16000) { + encoder->tilt = 18; + } else if (encoder->fs == 24000) { + encoder->tilt = 22; + } else if (encoder->fs == 32000) { + encoder->tilt = 26; + } else if (encoder->fs == 48000) { + encoder->tilt = 30; + } + else if (encoder->fs == 96000) { + encoder->tilt = 34; + } + + set_enc_frame_params(encoder); + return LC3PLUS_OK; +} + +/* set frame config params */ +void set_enc_frame_params(LC3PLUS_Enc* encoder) +{ + int ch = 0; + EncSetup* setup; + + encoder->frame_length = ceil(encoder->fs * 10 / 1000); /* fs * 0.01*2^6 */ + if (encoder->hrmode == 1) + { + encoder->yLen = encoder->frame_length; + } + else + { + encoder->yLen = MIN(MAX_BW, encoder->frame_length); + encoder->sns_damping = 0.85; + } + + encoder->stEnc_mdct_mem_len = encoder->frame_length - encoder->la_zeroes; + encoder->bands_number = 64; + encoder->nSubdivisions = 3; + encoder->near_nyquist_index = encoder->bands_number - 2; + encoder->near_nyquist_flag = 0; + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN; + + if (encoder->fs_idx == 5) + { + encoder->hrmode = 1; + } + + if (encoder->hrmode) + { + encoder->BW_cutoff_bits = 0; + } + else + { + encoder->BW_cutoff_bits = BW_cutoff_bits_all[encoder->fs_idx]; + } + + if (encoder->frame_ms == 10) { + encoder->la_zeroes = MDCT_la_zeroes[encoder->fs_idx]; + if (encoder->hrmode) + { + encoder->bands_offset = ACC_COEFF_PER_BAND_HR[encoder->fs_idx]; + } + else + { + encoder->bands_offset = ACC_COEFF_PER_BAND[encoder->fs_idx]; + } + encoder->cutoffBins = BW_cutoff_bin_all; + + encoder->attdec_nblocks = 4; + encoder->attdec_damping = 0.5; + encoder->attdec_hangover_thresh = 2; + } + else if (encoder->frame_ms == 7.5) { + if (encoder->hrmode) + { + encoder->bands_offset = ACC_COEFF_PER_BAND_7_5ms_HR[encoder->fs_idx]; + } + else + { + encoder->bands_offset = ACC_COEFF_PER_BAND_7_5ms[encoder->fs_idx]; + } + encoder->la_zeroes = MDCT_la_zeroes_7_5ms[encoder->fs_idx]; + encoder->cutoffBins = BW_cutoff_bin_all_7_5ms; + encoder->attdec_nblocks = 3; + encoder->attdec_damping = 0.3; + encoder->attdec_hangover_thresh = 1; + + encoder->frame_length = (encoder->frame_length >> 2) * 3; + encoder->yLen = (encoder->yLen >> 2) * 3; + + encoder->stEnc_mdct_mem_len = encoder->frame_length - encoder->la_zeroes; + if (encoder->hrmode) + { + encoder->bands_number = bands_number_7_5ms_HR[encoder->fs_idx]; + } + else + { + encoder->bands_number = bands_number_7_5ms[encoder->fs_idx]; + } + encoder->nSubdivisions = 3; + encoder->near_nyquist_index = encoder->bands_number - 4; + encoder->r12k8_mem_out_len = ceil(2.0 * ((LC3_FLOAT) encoder->frame_length / 2.0 - (LC3_FLOAT) encoder->la_zeroes) * 12800.0 / (LC3_FLOAT) encoder->fs - 8.0); + } + else if (encoder->frame_ms == 5) { + encoder->frame_length = encoder->frame_length >> 1; + encoder->yLen /= 2; + encoder->stEnc_mdct_mem_len = encoder->frame_length - encoder->la_zeroes; + encoder->bands_number = bands_number_5ms[encoder->fs_idx]; + encoder->nSubdivisions = 2; + encoder->near_nyquist_index = encoder->bands_number - 3; + encoder->la_zeroes = MDCT_la_zeroes_5ms[encoder->fs_idx]; + if (encoder->hrmode) + { + encoder->bands_offset = ACC_COEFF_PER_BAND_5ms_HR[encoder->fs_idx]; + } + else + { + encoder->bands_offset = ACC_COEFF_PER_BAND_5ms[encoder->fs_idx]; + } + encoder->cutoffBins = BW_cutoff_bin_all_5ms; + } + else if (encoder->frame_ms == 2.5) { + encoder->la_zeroes = MDCT_la_zeroes_2_5ms[encoder->fs_idx]; + if (encoder->hrmode) + { + encoder->bands_offset = ACC_COEFF_PER_BAND_2_5ms_HR[encoder->fs_idx]; + } + else + { + encoder->bands_offset = ACC_COEFF_PER_BAND_2_5ms[encoder->fs_idx]; + } + encoder->cutoffBins = BW_cutoff_bin_all_2_5ms; + encoder->frame_length = encoder->frame_length >> 2; + encoder->yLen /= 4; + encoder->stEnc_mdct_mem_len = encoder->frame_length - encoder->la_zeroes; + if (encoder->hrmode) + { + encoder->bands_number = bands_number_2_5ms_HR[encoder->fs_idx]; + } + else + { + encoder->bands_number = bands_number_2_5ms[encoder->fs_idx]; + } + + encoder->nSubdivisions = 2; + encoder->near_nyquist_index = encoder->bands_number - 2; + encoder->ltpf_mem_in_len = LTPF_MEMIN_LEN + (LEN_12K8 >> 2); + } + + for (ch = 0; ch < encoder->channels; ch++) { + setup = encoder->channel_setup[ch]; + + setup->olpa_mem_pitch = 17; + setup->pitch_flag = 0; + if (setup->mdctStruct.mem != NULL) { + mdct_free(&setup->mdctStruct); + mdct_init(&setup->mdctStruct, encoder->frame_length, encoder->frame_dms, encoder->fs_idx, encoder->hrmode); + + dct2_free(&setup->dct2StructSNS); + dct2_init(&setup->dct2StructSNS, M); + } + else + { + mdct_init(&setup->mdctStruct, encoder->frame_length, encoder->frame_dms, encoder->fs_idx, encoder->hrmode); + dct2_init(&setup->dct2StructSNS, M); + } + } +} + +/* change encoder bitrate */ +LC3PLUS_Error update_enc_bitrate(LC3PLUS_Enc* encoder, int bitrate) +{ + int ch = 0, bitsTmp = 0, minBR = 0, maxBR = 0, totalBytes = 0; + LC3_INT channel_bytes = 0, max_bytes = 0; + +#ifdef ENABLE_HR_MODE_FL + if (encoder->hrmode) + { + switch (encoder->frame_dms) + { + case 25: + maxBR = 672000; + if (encoder->fs == 48000) {minBR = MIN_BR_25MS_48KHZ_HR;} + else if (encoder->fs == 96000) {minBR = MIN_BR_25MS_96KHZ_HR;} + else { return LC3PLUS_HRMODE_ERROR;} + break; + case 50: + maxBR = 600000; + if (encoder->fs == 48000) {minBR = MIN_BR_50MS_48KHZ_HR;} + else if (encoder->fs == 96000) {minBR = MIN_BR_50MS_96KHZ_HR;} + else { return LC3PLUS_HRMODE_ERROR;} + break; + case 75: + maxBR = 500000; + if (encoder->fs == 48000) {minBR = MIN_BR_075DMS_48KHZ_HR;} + else if (encoder->fs == 96000) {minBR = MIN_BR_075DMS_96KHZ_HR;} + else {return LC3PLUS_HRMODE_ERROR;} + break; + case 100: + maxBR = 500000; + if (encoder->fs == 48000) {minBR = MIN_BR_100MS_48KHZ_HR;} + else if (encoder->fs == 96000) {minBR = MIN_BR_100MS_96KHZ_HR;} + else { return LC3PLUS_HRMODE_ERROR;} + break; + default: + return LC3PLUS_HRMODE_ERROR; + } + } + else +#endif /* ENABLE_HR_MODE_FL */ + { + minBR = (MIN_NBYTES << 3); + maxBR = MAX_BR; + + switch (encoder->frame_dms) + { + case 25: + minBR = MIN_BR_025DMS; + maxBR = MAX_BR; + break; + case 50: + minBR = MIN_BR_050DMS; + maxBR = MAX_BR; + /* have additional limitations for 5.0ms */ + switch (encoder->fs_in) + { + case 8000: maxBR = MAX_BR_050DMS_NB; break; + default: break; + } + break; + case 75: + minBR = MIN_BR_075DMS; + maxBR = MAX_BR_075DMS; + /* have additional limitations for 7.5ms */ + switch (encoder->fs_in) + { + case 8000: maxBR = MAX_BR_075DMS_NB ; break; + case 16000: maxBR = MAX_BR_075DMS_WB ; break; + case 24000: maxBR = MAX_BR_075DMS_SSWB; break; + default: break; + } + break; + case 100: + /* have additional limitations for 10ms */ + minBR = MIN_BR_100DMS; + maxBR = MAX_BR; + switch (encoder->fs_in) + { + case 8000: maxBR = MAX_BR_100DMS_NB ; break; + case 16000: maxBR = MAX_BR_100DMS_WB ; break; + case 24000: maxBR = MAX_BR_100DMS_SSWB; break; + default: maxBR = MAX_BR; break; + } + break; + default: return LC3PLUS_FRAMEMS_ERROR; + } + maxBR *= (encoder->fs_in == 44100 ? 441. / 480 : 1); + } + minBR *= encoder->channels; + maxBR *= encoder->channels; + + encoder->combined_channel_coding = 0; + + if (encoder->channels > 1 && encoder->epmode) + { + if (encoder->bitrate * encoder->frame_length / (8 * encoder->fs_in) <= 160) + { + encoder->combined_channel_coding = 1; + } + } + + if (encoder->epmode > 0) + { + max_bytes = bitrate * encoder->frame_length / (8 * encoder->fs_in * encoder->channels); + if (max_bytes < FEC_SLOT_BYTES_MIN || max_bytes > FEC_SLOT_BYTES_MAX) + { + encoder->lc3_br_set = 0; + return LC3PLUS_BITRATE_ERROR; + } + } + + if (encoder->combined_channel_coding) + { + totalBytes = fec_get_data_size(encoder->epmode, encoder->combined_channel_coding, + bitrate * encoder->frame_length / (8 * encoder->fs_in)); + + encoder->channel_setup[0]->n_pccw = + fec_get_n_pccw(bitrate * encoder->frame_length / (8 * encoder->fs_in), encoder->epmode, + encoder->combined_channel_coding); + + encoder->channel_setup[0]->n_pc = fec_get_n_pc(encoder->epmode, encoder->channel_setup[0]->n_pccw, + bitrate * encoder->frame_length / (8 * encoder->fs_in)); + } + else + { + totalBytes = bitrate * encoder->frame_length / (8 * encoder->fs_in); + } + + if (encoder->frame_dms <= 50) + { + encoder->tnsMaxOrder = 4; + } else { + encoder->tnsMaxOrder = 8; + } + + if (bitrate < minBR || bitrate > maxBR) { + return LC3PLUS_BITRATE_ERROR; + } + + encoder->lc3_br_set = 1; + for (ch = 0; ch < encoder->channels; ch++) { + + EncSetup* setup = encoder->channel_setup[ch]; + + setup->targetBytes = totalBytes / encoder->channels + (ch < (totalBytes % encoder->channels)); + channel_bytes = totalBytes / encoder->channels + (ch < (totalBytes % encoder->channels)); + + if (encoder->combined_channel_coding) + { + setup->targetBytes = channel_bytes; + } + else + { + setup->targetBytes = fec_get_data_size(encoder->epmode, encoder->combined_channel_coding, channel_bytes); + setup->n_pccw = fec_get_n_pccw(channel_bytes, encoder->epmode, encoder->combined_channel_coding); + setup->n_pc = fec_get_n_pc(encoder->epmode, setup->n_pccw, channel_bytes); + } + // reduce bandwith to 12kHz if bitrate is low + if (encoder->frame_dms == 100 && + ((setup->targetBytes < 40 && encoder->fs == 48000) || + (setup->targetBytes < 36 && encoder->fs == 32000))) + { + encoder->bandwidth = MIN(12000, encoder->bandwidth_preset); + } + else + { + /* channel with highest index has lowest bitrate. + For a second channel with lower targetBytes, bandwidth is overwritten */ + encoder->bandwidth = encoder->bandwidth_preset; + } + encoder->bw_ctrl_cutoff_bin = encoder->bandwidth * encoder->frame_dms / 5000; + encoder->bw_index = (encoder->bandwidth / 4000) - 1; + setup->total_bits = setup->targetBytes << 3; + setup->targetBitsInit = setup->total_bits - encoder->envelope_bits - encoder->global_gain_bits - + encoder->noise_fac_bits - encoder->BW_cutoff_bits - + ceil(LC3_LOGTWO(encoder->frame_length / 2)) - 2 - 1; + + if (setup->total_bits > 1280) { + setup->targetBitsInit = setup->targetBitsInit - 1; + } + if (setup->total_bits > 2560) { + setup->targetBitsInit = setup->targetBitsInit - 1; + } + + if (encoder->hrmode) + { + setup->targetBitsInit -= 1; + } + + setup->targetBitsAri = setup->total_bits; + setup->enable_lpc_weighting = setup->total_bits < 480; + + if (encoder->frame_ms == 7.5) { + setup->enable_lpc_weighting = setup->total_bits < 360; + } + if (encoder->frame_ms == 5) { + setup->enable_lpc_weighting = setup->total_bits < 240; + } + if (encoder->frame_ms == 2.5) { + setup->enable_lpc_weighting = setup->total_bits < 120; + } + + setup->quantizedGainOff = + -(MIN(115, setup->total_bits / (10 * (encoder->fs_idx + 1))) + 105 + 5 * (encoder->fs_idx + 1)); + + if (encoder->hrmode && encoder->fs_idx == 5) + { + setup->quantizedGainOff = MAX(setup->quantizedGainOff, -181); + } + + if (encoder->frame_ms == 10 && ((encoder->fs_in >= 44100 && setup->targetBytes >= 100) || + (encoder->fs_in == 32000 && setup->targetBytes >= 81)) && setup->targetBytes < 340 && encoder->hrmode == 0) { + setup->attack_handling = 1; + + } + else if (encoder->frame_dms == 75 && ((encoder->fs_in >= 44100 && setup->targetBytes >= 75) || + (encoder->fs_in == 32000 && setup->targetBytes >= 61)) && setup->targetBytes < 150 && encoder->hrmode == 0) + { + setup->attack_handling = 1; + } + else + { + /* reset for bitrate switching */ + setup->attack_handling = 0; + + setup->attdec_filter_mem[0] = 0; + setup->attdec_filter_mem[1] = 0; + + setup->attdec_detected = 0; + setup->attdec_position = 0; + setup->attdec_acc_energy = 0; + } + + bitsTmp = setup->total_bits; + if (encoder->frame_ms == 2.5) { + bitsTmp = bitsTmp * 4.0 * (1.0 - 0.4); + } + if (encoder->frame_ms == 5) { + bitsTmp = bitsTmp * 2 - 160; + } + if (encoder->frame_ms == 7.5) { + bitsTmp = round(bitsTmp * 10 / 7.5); + } + + if (bitsTmp < 400 + (encoder->fs_idx - 1) * 80) { + setup->ltpf_enable = 1; + } else if (bitsTmp < 480 + (encoder->fs_idx - 1) * 80) { + setup->ltpf_enable = 1; + } else if (bitsTmp < 560 + (encoder->fs_idx - 1) * 80) { + setup->ltpf_enable = 1; + } else if (bitsTmp < 640 + (encoder->fs_idx - 1) * 80) { + setup->ltpf_enable = 1; + } else { + setup->ltpf_enable = 0; + } + if (encoder->hrmode) { + setup->ltpf_enable = 0; + } + + /* turn down SNS shaping for higher rates */ + if (encoder->hrmode == 0) { + encoder->sns_damping = 0.85; + } else { + encoder->sns_damping = 0.6; + if (encoder->fs_idx >= 4) { + if (encoder->frame_ms == 10) + { + if (setup->total_bits > 4400) { + encoder->sns_damping = 6881.0/32768.0; + } + } + if (encoder->frame_ms == 7.5) + { + if (setup->total_bits > 3*4400/4) { + encoder->sns_damping = 5898.0/32768.0; + } + } + if (encoder->frame_ms == 5) + { + if (setup->total_bits > 4600/2) { + encoder->sns_damping = 4915.0/32768.0; + } + } + if (encoder->frame_ms == 2.5) + { + if (setup->total_bits > 4600/4) { + encoder->sns_damping = 4915.0/32768.0; + } + } + } + } + + if (encoder->hrmode && encoder->fs_idx >= 4) + { + int real_rate = setup->targetBytes * 8000 / encoder->frame_ms; + setup->regBits = real_rate / 12500; + + if (encoder->fs_idx == 5) + { + if (encoder->frame_ms == 10) + { + setup->regBits +=2; + } + if (encoder->frame_ms == 7.5) + { + setup->regBits +=1; + } + if (encoder->frame_ms == 2.5) + { + setup->regBits -= 6; + } + } + else + { + if (encoder->frame_ms == 2.5) + { + setup->regBits -= 6; + } + else if (encoder->frame_ms == 5) + { + setup->regBits += 0; + } + if (encoder->frame_ms == 7.5) + { + setup->regBits +=2; + } + if (encoder->frame_ms == 10) + { + setup->regBits += 5; + } + } + if (setup->regBits < 6) + { + setup->regBits = 6; + } + if (setup->regBits > 23) + { + setup->regBits = 23; + } + } + else + { + setup->regBits = -1; + } + } + + encoder->bitrate = bitrate; + + return LC3PLUS_OK; +} + +void update_enc_bandwidth(LC3PLUS_Enc* encoder, int bandwidth) +{ + int index = 0; + + if (bandwidth >= encoder->fs_in) { + encoder->bandwidth = 0; + } + else + { + encoder->bandwidth = bandwidth; + index = FS2FS_IDX(bandwidth); + encoder->bw_ctrl_cutoff_bin = encoder->cutoffBins[index]; + } +} diff --git a/lib_lc3plus/setup_enc_lc3plus.h b/lib_lc3plus/setup_enc_lc3plus.h new file mode 100644 index 0000000000..7947a0e649 --- /dev/null +++ b/lib_lc3plus/setup_enc_lc3plus.h @@ -0,0 +1,121 @@ +/****************************************************************************** +* ETSI TS 103 634 V1.5.1 * +* Low Complexity Communication Codec Plus (LC3plus) * +* * +* Copyright licence is solely granted through ETSI Intellectual Property * +* Rights Policy, 3rd April 2019. No patent licence is granted by implication, * +* estoppel or otherwise. * +******************************************************************************/ + +#ifndef SETUP_ENC_LC3_FL_H +#define SETUP_ENC_LC3_FL_H + +#include "options.h" +#include "wmc_auto.h" +#include "constants.h" + +/* Channel state and bitrate-derived values go in this struct */ +typedef struct { + LC3_FLOAT targetBitsOff; + LC3_FLOAT ltpf_mem_normcorr; + LC3_FLOAT ltpf_mem_mem_normcorr; + LC3_FLOAT attdec_filter_mem[2]; + LC3_FLOAT attdec_acc_energy; + LC3_FLOAT r12k8_mem_50[2]; + LC3_FLOAT r12k8_mem_in[120]; + LC3_FLOAT r12k8_mem_out[44]; + LC3_FLOAT olpa_mem_s12k8[3]; + LC3_FLOAT olpa_mem_s6k4[LEN_6K4 + MAX_PITCH_6K4 + 16]; + LC3_FLOAT ltpf_mem_in[LTPF_MEMIN_LEN + LEN_12K8 + 1]; + LC3_FLOAT s_in_scaled[MAX_LEN]; + LC3_FLOAT s_12k8[LEN_12K8 + 1]; + LC3_FLOAT ener[MAX_BANDS_NUMBER]; + LC3_FLOAT scf_q[M]; + LC3_FLOAT scf[M]; + LC3_FLOAT int_scf[MAX_BANDS_NUMBER]; + LC3_FLOAT ltpf_mem_pitch; + + LC3_INT targetBytes; + LC3_INT total_bits; + LC3_INT targetBitsInit; + LC3_INT targetBitsAri; + LC3_INT enable_lpc_weighting; + LC3_INT ltpf_enable; + LC3_INT quantizedGainOff; + LC3_INT tns_bits; + LC3_INT targetBitsQuant; + LC3_INT olpa_mem_pitch; + LC3_INT pitch_flag; + LC3_INT ltpf_mem_ltpf_on; + LC3_INT mem_targetBits; + LC3_INT mem_specBits; + LC3_INT attack_handling; /* flag to enable attack handling */ + LC3_INT attdec_detected; + LC3_INT attdec_position; + LC3_INT ltpf_param[3]; + LC3_INT L_scf_idx[SCF_MAX_PARAM]; + LC3_INT codingdata[3 * MAX_LEN]; + uint8_t resBits[MAX_RESBITS_LEN]; + LC3_INT regBits; + + LC3_INT16 n_pc; + LC3_INT16 n_pccw; + LC3_INT16 be_bp_left; + LC3_INT16 be_bp_right; + + Mdct mdctStruct; + Dct2 dct2StructSNS; + + LC3_INT lfe; +} EncSetup; + +/* Constants and sampling rate derived values go in this struct */ +struct LC3PLUS_Enc { + EncSetup* channel_setup[MAX_CHANNELS]; + const LC3_INT* W_fx; + const LC3_INT* bands_offset; + const LC3_INT* cutoffBins; + + LC3_INT fs; /* encoder sampling rate 44.1 -> 48 */ + LC3_INT fs_in; /* input sampling rate */ + LC3_INT bitrate; /* global bitrate */ + LC3_INT fs_idx; /* sampling rate index */ + LC3_INT frame_length; /* audio samples / frame */ + LC3_INT channels; /* number of channels */ + LC3_INT epmode; /* error protection mode */ + LC3_FLOAT frame_ms; /* frame length in ms (wrong for 44.1) */ + LC3_INT frame_dms; /* frame length in ms * 10 (wrong for 44.1) */ + LC3_INT tilt; + LC3_INT lc3_br_set; + LC3_INT yLen; + LC3_INT W_size; + LC3_INT la_zeroes; + LC3_INT stEnc_mdct_mem_len; + LC3_INT bands_number; + LC3_INT nSubdivisions; + LC3_INT ltpf_mem_in_len; + LC3_INT envelope_bits; + LC3_INT global_gain_bits; + LC3_INT noise_fac_bits; + LC3_INT BW_cutoff_bits; + LC3_INT r12k8_mem_in_len; + LC3_INT r12k8_mem_out_len; + LC3_INT16 near_nyquist_index; + LC3_INT16 near_nyquist_flag; + LC3_INT tnsMaxOrder; + LC3_INT hrmode; + LC3_INT bandwidth; + LC3_INT bandwidth_preset; + LC3_INT bw_ctrl_active; + LC3_INT bw_ctrl_cutoff_bin; + LC3_INT bw_index; + LC3_FLOAT sns_damping; + LC3_INT attdec_nblocks; + LC3_FLOAT attdec_damping; + LC3_INT attdec_hangover_thresh; + + LC3_INT16 combined_channel_coding; + LC3_INT16 epmr; +}; + +#endif diff --git a/lib_rend/ivas_td_ring_buffer.c b/lib_rend/ivas_td_ring_buffer.c new file mode 100644 index 0000000000..5c9c6089bb --- /dev/null +++ b/lib_rend/ivas_td_ring_buffer.c @@ -0,0 +1,288 @@ +/****************************************************************************************************** + + (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 +#include +#include "ivas_error_utils.h" +#include "ivas_prot_rend.h" +#include "options.h" +#include "wmc_auto.h" + + +/*-----------------------------------------------------------------------* + * 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 + *-----------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------* + * 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( + 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; + + capacity = capacity_per_channel * num_channels; + + 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" ); + } + 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; +} + + +/*---------------------------------------------------------------------* + * ivas_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; + + if ( ph == NULL ) + { + return; + } + h = *ph; + + if ( h == NULL ) + { + return; + } + + if ( h->data != NULL ) + { + free( h->data ); + } + + free( h ); + *ph = NULL; + + return; +} + + +/*---------------------------------------------------------------------* + * 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( + 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( 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 ) + { + 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; +} + + +/*---------------------------------------------------------------------* + * ivas_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( ivas_td_ringbuf_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; +} + + +/*---------------------------------------------------------------------* + * ivas_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( ivas_td_ringbuf_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; +} + + +/*---------------------------------------------------------------------* + * ivas_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 ivas_td_ringbuf_total_size( h ) / (uint32_t) h->num_channels; +} -- GitLab From a401b93ccd869ac44f1b1f4c572758e01d779abf Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 3 Sep 2025 07:22:35 +0200 Subject: [PATCH 48/61] Merge apps with main --- apps/decoder.c | 15 +++++- apps/renderer.c | 135 ++++++++++++++++++++++++++---------------------- 2 files changed, 87 insertions(+), 63 deletions(-) diff --git a/apps/decoder.c b/apps/decoder.c index 71379c6575..4a28b4470b 100644 --- a/apps/decoder.c +++ b/apps/decoder.c @@ -1617,6 +1617,18 @@ static bool parseCmdlIVAS_dec( return false; } +#ifdef SUPPORT_JBM_TRACEFILE + /* Validate options that depend on other options */ + if ( arg->jbmTraceFilename != NULL && arg->delayCompensationEnabled + /* This decMode check should be removed once timestamp sync issues between JBM trace and audio are fixed in EVS */ + && arg->decMode != IVAS_DEC_MODE_EVS ) + { + fprintf( stderr, "Error: Writing to a JBM trace file requires delay compensation to be disabled with -no_delay_cmp\n\n" ); + usage_dec(); + return false; + } +#endif + return true; } @@ -1653,7 +1665,8 @@ static void usage_dec( void ) fprintf( stdout, " EVS RTP Payload Format. The SDP parameter hf_only is required.\n" ); fprintf( stdout, " Reading RFC4867 AMR/AMR-WB RTP payload format is not supported.\n" ); #ifdef SUPPORT_JBM_TRACEFILE - fprintf( stdout, "-Tracefile TF : VoIP mode: Generate trace file named TF\n" ); + fprintf( stdout, "-Tracefile TF : VoIP mode: Generate trace file named TF. Requires -no_delay_cmp to\n" ); + fprintf( stdout, " be enabled so that trace contents remain in sync with audio output.\n" ); #endif #ifdef DEBUGGING #ifdef VARIABLE_SPEED_DECODING diff --git a/apps/renderer.c b/apps/renderer.c index 8124dfefe7..26c4b349d2 100644 --- a/apps/renderer.c +++ b/apps/renderer.c @@ -68,6 +68,8 @@ #define IVAS_MAX16B_FLT 32767.0f #define IVAS_MIN16B_FLT ( -32768.0f ) +#define OMASA_TDREND_MATCHING_GAIN_DB ( -2.0f ) + #if !defined( DEBUGGING ) && !defined( WMOPS ) static #endif @@ -705,6 +707,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; @@ -749,8 +752,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; @@ -1071,7 +1077,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; @@ -1160,20 +1169,30 @@ int main( } } - /* Set the total number of objects */ if ( args.inConfig.numAudioObjects > 0 ) { + /* Set the total number of objects */ if ( ( error = IVAS_REND_SetTotalNumberOfObjects( hIvasRend, args.inConfig.numAudioObjects ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_SetTotalNumberOfObjects(): %s\n", ivas_error_to_string( error ) ); goto cleanup; } + /* Set the metadata delay for objects */ if ( ( error = IVAS_REND_SetIsmMetadataDelay( hIvasRend, args.syncMdDelay ) ) != IVAS_ERR_OK ) { fprintf( stderr, "\nError in IVAS_REND_SetIsmMetadataDelay(): %s\n", ivas_error_to_string( error ) ); goto cleanup; } + + /* For OMASA input and BINAURAL output, apply a gain to objects to match the loudness with MASA part */ + if ( args.inConfig.numMasaBuses > 0 && args.outConfig.audioConfig == IVAS_AUDIO_CONFIG_BINAURAL ) + { + for ( i = 0; i < args.inConfig.numAudioObjects; ++i ) + { + args.inConfig.audioObjects[i].gain_dB += OMASA_TDREND_MATCHING_GAIN_DB; + } + } } IVAS_REND_LfePanMtx lfePanMatrix; @@ -1358,7 +1377,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; @@ -1373,8 +1392,16 @@ int main( } } - 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 ) { + 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" ); @@ -1387,36 +1414,15 @@ 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 ( 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 ); @@ -1542,16 +1548,23 @@ 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 ); + } + 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; - if ( isCurrentFrameMultipleOf20ms ) + if ( isCurrentFrameMultipleOf20ms && !flushRendererLastFrame ) { IsmPositionProvider_getNextFrame( positionProvider, &mtdBuffer ); @@ -1663,7 +1676,7 @@ int main( } 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 ) + 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; @@ -1678,7 +1691,7 @@ int main( { 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 ) + 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; @@ -1695,7 +1708,7 @@ int main( { 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 ) + 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; @@ -1718,7 +1731,7 @@ int main( } 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 ) + 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; @@ -1734,13 +1747,13 @@ int main( } 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 ) + 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 ) { @@ -1803,7 +1816,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 ) @@ -1813,7 +1826,7 @@ int main( } } - if ( audioWriter != NULL ) + if ( audioWriter != NULL && !flushRendererLastFrame ) { if ( delayNumSamples * num_out_channels < outBufferSize ) { @@ -1834,7 +1847,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; @@ -1906,7 +1919,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 ) @@ -1923,6 +1937,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 ) { @@ -1935,12 +1956,13 @@ int main( #endif } - /* 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" ); @@ -1948,7 +1970,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" ); @@ -1957,9 +1978,10 @@ 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.f / IVAS_NUM_FRAMES_PER_SEC / IVAS_MAX_PARAM_SPATIAL_SUBFRAMES ) ) ); } if ( !args.quietModeEnabled && args.delayCompensationEnabled ) @@ -3290,7 +3312,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 ) { @@ -3499,20 +3522,8 @@ static void parseCombinedFormatInput( inConfig->numAmbisonicsBuses = 1; inConfig->ambisonicsBuses[0].audioConfig = audioConfig; inConfig->ambisonicsBuses[0].inputChannelIndex = inConfig->numAudioObjects; -#ifdef NONBE_1352_HARMONIZE_OSBA_LOUDNESS inConfig->ambisonicsBuses[0].gain_dB = 0.f; -#else - inConfig->ambisonicsBuses[0].gain_dB = -6.f; -#endif *configString += 4; - -#ifndef NONBE_1352_HARMONIZE_OSBA_LOUDNESS - /* Modify input gain for objects too */ - for ( int16_t i = 0; i < inConfig->numAudioObjects; ++i ) - { - inConfig->audioObjects[i].gain_dB = -6.f; - } -#endif } else if ( audioConfig == IVAS_AUDIO_CONFIG_MASA1 || audioConfig == IVAS_AUDIO_CONFIG_MASA2 ) { -- GitLab From d38933e7a0b4ec9319d356516be4fcae8a47d6c8 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Wed, 3 Sep 2025 07:33:57 +0200 Subject: [PATCH 49/61] Restore Workspace_msvc from main --- Workspace_msvc/lib_com.vcxproj | 2 +- Workspace_msvc/lib_lc3plus.vcxproj | 32 +++++------ Workspace_msvc/lib_rend.vcxproj | 1 + Workspace_msvc/lib_rend.vcxproj.filters | 73 +------------------------ 4 files changed, 19 insertions(+), 89 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_lc3plus.vcxproj b/Workspace_msvc/lib_lc3plus.vcxproj index 55a291fa9c..3f1527357a 100644 --- a/Workspace_msvc/lib_lc3plus.vcxproj +++ b/Workspace_msvc/lib_lc3plus.vcxproj @@ -106,7 +106,6 @@ - @@ -116,13 +115,13 @@ - - + + - + @@ -133,35 +132,36 @@ + - - - + + + + - - - + + + - @@ -169,14 +169,12 @@ - - - - + + + + - - diff --git a/Workspace_msvc/lib_rend.vcxproj b/Workspace_msvc/lib_rend.vcxproj index 27d4a19a69..854c99a979 100644 --- a/Workspace_msvc/lib_rend.vcxproj +++ b/Workspace_msvc/lib_rend.vcxproj @@ -175,6 +175,7 @@ + diff --git a/Workspace_msvc/lib_rend.vcxproj.filters b/Workspace_msvc/lib_rend.vcxproj.filters index 942c63712f..2d1d7d46c0 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,12 +140,6 @@ rend_h - - rend_h - - - rend_h - -- GitLab From 9b4f2ec753c773885bdb5bb4d7de9a69a4db7a9f Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 3 Sep 2025 09:28:12 +0200 Subject: [PATCH 50/61] fix FIX_1995_REVERB_INIT --- lib_com/options.h | 1 + lib_rend/ivas_prot_rend.h | 3 +-- lib_rend/ivas_reverb.c | 30 +++++++++++++++++------------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 62cb9b3b78..83a32c2eab 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -163,6 +163,7 @@ /*#define FIX_I4_OL_PITCH*/ /* fix open-loop pitch used for EVS core switching */ #define TMP_FIX_1119_SPLIT_RENDERING_VOIP /* FhG: Add error check for unsupported config: split rendering with VoIP mode */ +#define FIX_1995_REVERB_INIT /* issue 1995: Fix use-of-uninitialized-value in ivas_binaural_reverb_init() */ /* #################### End BE switches ################################## */ diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 2268f62add..126112a7db 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -945,8 +945,7 @@ ivas_error ivas_binaural_reverb_init( const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */ const int32_t sampling_rate, /* i : sampling rate */ const float *defaultTimes, /* i : default reverberation times */ - const float *defaultEne /* i : default reverberation energies */ - , + const float *defaultEne, /* i : default reverberation energies */ float *earlyEne /* i/o: Early part energies to be modified */ ); diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index c12fa8488b..7d78522e84 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1859,12 +1859,13 @@ static ivas_error ivas_binaural_reverb_open( return IVAS_ERR_OK; } + /*------------------------------------------------------------------------- * ivas_binaural_reverb_init() * - * Allocate and initialize binaural room reverberator handle - * for CLDFB renderers + * Initialize binaural room reverberator handle for FastConv renderer *------------------------------------------------------------------------*/ + ivas_error ivas_binaural_reverb_init( REVERB_STRUCT_HANDLE *hReverbPr, /* i/o: binaural reverb handle */ const HRTFS_STATISTICS_HANDLE hHrtfStatistics, /* i : HRTF statistics handle */ @@ -1873,9 +1874,8 @@ ivas_error ivas_binaural_reverb_init( const IVAS_ROOM_ACOUSTICS_CONFIG_DATA *roomAcoustics, /* i/o: room acoustics parameters */ const int32_t sampling_rate, /* i : sampling rate */ const float *defaultTimes, /* i : default reverberation times */ - const float *defaultEne /* i : default reverberation energies */ - , - float *earlyEne /* i/o: Early part energies to be modified */ + const float *defaultEne, /* i : default reverberation energies */ + float *earlyEne /* i/o: Early part energies to be modified */ ) { ivas_error error; @@ -1883,24 +1883,23 @@ ivas_error ivas_binaural_reverb_init( float revTimes[CLDFB_NO_CHANNELS_MAX]; float revEne[CLDFB_NO_CHANNELS_MAX]; - error = IVAS_ERR_OK; - if ( roomAcoustics != NULL ) { - - if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, - hHrtfStatistics, - sampling_rate, - revTimes, - revEne ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_reverb_prepare_cldfb_params( roomAcoustics, hHrtfStatistics, sampling_rate, revTimes, revEne ) ) != IVAS_ERR_OK ) { return error; } + + /* preDelay parameter = acousticPreDelay * sampling_rate / numBins */ preDelay = (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ); } else { +#ifdef FIX_1995_REVERB_INIT + for ( bin = 0; bin < numBins; bin++ ) +#else for ( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) +#endif { revTimes[bin] = defaultTimes[bin]; revEne[bin] = defaultEne[bin]; @@ -1908,7 +1907,11 @@ ivas_error ivas_binaural_reverb_init( preDelay = 10; } +#ifdef FIX_1995_REVERB_INIT + for ( bin = 0; bin < numBins; bin++ ) +#else for ( bin = 0; bin < CLDFB_NO_CHANNELS_MAX; bin++ ) +#endif { /* Adjust the room effect parameters when the reverberation time is less than a threshold value, to avoid spectral artefacts with the synthetic reverberator. */ @@ -1943,6 +1946,7 @@ ivas_error ivas_binaural_reverb_init( return error; } + /*------------------------------------------------------------------------- * ivas_binaural_reverb_close() * -- GitLab From fa419702187c48f47f6e82b0a5809f6e533ed112 Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 3 Sep 2025 09:53:39 +0200 Subject: [PATCH 51/61] update comment --- lib_rend/ivas_reverb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 7d78522e84..a6ade569bc 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1890,7 +1890,7 @@ ivas_error ivas_binaural_reverb_init( return error; } - /* preDelay parameter = acousticPreDelay * sampling_rate / numBins */ + /* Convert preDelay from seconds to CLDFB slots as needed by binaural reverb */ preDelay = (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ); } else -- GitLab From 67463e132433ad91dd69a0530e135f81e2d56bc1 Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 3 Sep 2025 10:13:20 +0200 Subject: [PATCH 52/61] improvement --- lib_rend/ivas_reverb.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index a6ade569bc..052c238589 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -79,10 +79,10 @@ #define MAX_NR_OUTPUTS ( 2 ) -const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 }; -const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 }; -const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 }; -const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 }; +static const int16_t init_loop_delay[IVAS_REV_MAX_NR_BRANCHES] = { 37, 31, 29, 23, 19, 17, 13, 11 }; +static const int16_t default_loop_delay_48k[IVAS_REV_MAX_NR_BRANCHES] = { 2309, 1861, 1523, 1259, 1069, 919, 809, 719 }; +static const int16_t default_loop_delay_32k[IVAS_REV_MAX_NR_BRANCHES] = { 1531, 1237, 1013, 839, 709, 613, 541, 479 }; +static const int16_t default_loop_delay_16k[IVAS_REV_MAX_NR_BRANCHES] = { 769, 619, 509, 421, 353, 307, 269, 239 }; /*------------------------------------------------------------------------------------------* * Local Struct definition @@ -682,8 +682,6 @@ static ivas_error initialize_reverb_filters( { ivas_error error; - error = IVAS_ERR_OK; - /* init correlation and coloration filters */ if ( ( error = ivas_reverb_t2f_f2t_init( &hReverb->fft_filter_ols, hReverb->fft_size, hReverb->fft_subblock_size ) ) != IVAS_ERR_OK ) { @@ -710,7 +708,7 @@ static ivas_error initialize_reverb_filters( return error; } - return error; + return IVAS_ERR_OK; } @@ -1060,7 +1058,6 @@ ivas_error ivas_reverb_open( int16_t fft_hist_size, transition_start, transition_length; int16_t nr_fc_input, nr_fc_fft_filter; - error = IVAS_ERR_OK; output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); subframe_len = output_frame / MAX_PARAM_SPATIAL_SUBFRAMES; predelay_bf_len = output_frame; @@ -1240,7 +1237,7 @@ ivas_error ivas_reverb_open( *hReverb = pState; - return error; + return IVAS_ERR_OK; } -- GitLab From 4e3192936c282de45fdd0e5ef5f1da6c8293d061 Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 3 Sep 2025 10:40:46 +0200 Subject: [PATCH 53/61] use CLDFB_SLOTS_PER_SECOND macro --- lib_rend/ivas_reverb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_rend/ivas_reverb.c b/lib_rend/ivas_reverb.c index 052c238589..b4adf013fb 100644 --- a/lib_rend/ivas_reverb.c +++ b/lib_rend/ivas_reverb.c @@ -1888,7 +1888,7 @@ ivas_error ivas_binaural_reverb_init( } /* Convert preDelay from seconds to CLDFB slots as needed by binaural reverb */ - preDelay = (int16_t) roundf( 48000.0f * roomAcoustics->acousticPreDelay / CLDFB_NO_CHANNELS_MAX ); + preDelay = (int16_t) roundf( roomAcoustics->acousticPreDelay * CLDFB_SLOTS_PER_SECOND ); } else { -- GitLab From 5d8d7bdd49a52b8e06867c6a7f1026066ea6ec27 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Thu, 4 Sep 2025 09:07:51 +0200 Subject: [PATCH 54/61] Remove decoder/renderer coverage report --- ci/basop-pages/basop_index.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ci/basop-pages/basop_index.html b/ci/basop-pages/basop_index.html index c7203a9259..4368a15ff2 100644 --- a/ci/basop-pages/basop_index.html +++ b/ci/basop-pages/basop_index.html @@ -27,8 +27,7 @@

Test Coverage

-- GitLab From df01165bf7dc24b6b0e3ac50a35d83a11167b0d9 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Fri, 5 Sep 2025 07:16:35 +0200 Subject: [PATCH 55/61] Split regressions script in two. Add thresholds to find_regressions_from_logs.py --- scripts/find_regressions_from_logs.py | 202 +++++-------------- scripts/generate_scripts_from_regressions.py | 155 ++++++++++++++ 2 files changed, 203 insertions(+), 154 deletions(-) create mode 100644 scripts/generate_scripts_from_regressions.py diff --git a/scripts/find_regressions_from_logs.py b/scripts/find_regressions_from_logs.py index 068fe77871..67a7447ddf 100644 --- a/scripts/find_regressions_from_logs.py +++ b/scripts/find_regressions_from_logs.py @@ -4,99 +4,7 @@ import argparse from pathlib import Path import pandas as pd -REPRODUCE_REGRESSION_SCRIPT_TMPL = """ -#!/bin/bash -x - -SCRIPTS_DIR=/usr/local/scripts -LTV_DIR=/usr/local/ltv - -MIN_DATE={min_date} -MIN_SHA={min_sha} -LEVEL_SCALING={level_scaling} -TESTCASE="{testcase}" - -REF_ENC1={REF_ENC1} -REF_DEC1={REF_DEC1} -DUT_ENC1={DUT_ENC1} -DUT_DEC1={DUT_DEC1} - -REF_ENC2={REF_ENC2} -REF_DEC2={REF_DEC2} -DUT_ENC2={DUT_ENC2} -DUT_DEC2={DUT_DEC2} - -INV_LEVEL_SCALING=$(awk "BEGIN {{print 1.0 / $LEVEL_SCALING}}") - -# Obtain executables from past reference -git checkout `git rev-list -1 --before="$MIN_DATE 22:00:00" ivas-float-update` -echo "ivas_float_update, min version: `git rev-parse HEAD`" > versions.txt -make clean -make -j -mv IVAS_cod IVAS_cod_ref_1 -mv IVAS_dec IVAS_dec_ref_1 -mv IVAS_rend IVAS_rend_ref_1 - -git checkout $MIN_SHA -echo "main, min version: `git rev-parse HEAD`" >> versions.txt -make clean -make -j -mv IVAS_cod IVAS_cod_1 -mv IVAS_dec IVAS_dec_1 -mv IVAS_rend IVAS_rend_1 - -# Obtain latest executables -git checkout ivas-float-update -git pull -echo "ivas-float-update, current version: `git rev-parse HEAD`" >> versions.txt -make clean -make -j -mv IVAS_cod IVAS_cod_ref_2 -mv IVAS_dec IVAS_dec_ref_2 -mv IVAS_rend IVAS_rend_ref_2 - -git checkout main -git pull -echo "main, current version: `git rev-parse HEAD`" >> versions.txt -make clean -make -j -mv IVAS_cod IVAS_cod_2 -mv IVAS_dec IVAS_dec_2 -mv IVAS_rend IVAS_rend_2 - -# Get fresh copy of scripts, tests and ci -cp -r $SCRIPTS_DIR/{{scripts,tests,ci,pytest.ini}} . -rm -rf tests/ref tests/dut tests/renderer/ref tests/renderer/cut -python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm - -# Get LTVs -cp $LTV_DIR/* scripts/testv - -# Apply level scaling -tests/scale_pcm.py ./scripts/testv/ "$LEVEL_SCALING" - -# Run tests -cp IVAS_rend_ref_1 IVAS_rend_ref -cp IVAS_rend_1 IVAS_rend -python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg --scalefac $INV_LEVEL_SCALING --junit-xml=report1.xml --html=report1.html --self-contained-html -python3 scripts/parse_xml_report.py report1.xml report1.csv - -# Store results from first run -mkdir -p tests1/renderer -cp -r tests/ref tests/dut tests1 -cp -r tests/renderer/ref tests1/renderer -cp -r tests/renderer/cut tests1/renderer - -cp IVAS_rend_ref_2 IVAS_rend_ref -cp IVAS_rend_2 IVAS_rend -python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 -python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg --scalefac $INV_LEVEL_SCALING --junit-xml=report2.xml --html=report2.html --self-contained-html -python3 scripts/parse_xml_report.py report2.xml report2.csv - -""" - - -def main(logs_dir, output_filename, measure): +def main(logs_dir, output_filename, measure, days, all_results, diff_thr, ratio_thr, curr_value_thr): input_path = Path(logs_dir) logs = [f for f in input_path.iterdir() if f.is_dir()] @@ -142,6 +50,14 @@ def main(logs_dir, output_filename, measure): index=["job", "testcase"], columns="date", values="format" ).reset_index() + if days != -1: + len_history = len(result.columns) - 2 + if len_history < days: + print(f"*** Warning: Requested number of days exceeds the number of days in the logs. Will use all {len_history} available days.") + if len_history > days: + remove_days = len_history - days + result = result.drop(result.columns[2:2+remove_days], axis=1) + values = result.iloc[:, 2:] last_date = values.columns[-1] @@ -156,69 +72,16 @@ def main(logs_dir, output_filename, measure): 1 # Set ratio to 1 for denominator 0 ) - result["min_sha"] = "'" + result["min_sha"] + if not all_results: + # Filter out test cases above thresholds + result = result[result["diff"] > diff_thr] + result = result[result["ratio"] > ratio_thr] + result = result[result["curr_value"] > curr_value_thr] + + result["min_sha"] = "'" + result["min_sha"] # Add apostrophy to prevent Excel reading this as a number result.to_csv(output_filename, sep=";", index=False) - critical = result.iloc[:, 0:9] - formats = list(set(critical["format"])) - formats.sort() - critical3 = pd.DataFrame() - - for format in formats: - top3 = ( - critical[critical["format"] == format] - .sort_values(by="ratio", ascending=False) - .head(3) - ) - critical3 = pd.concat([critical3, top3], ignore_index=True) - - critical3.to_csv("critical3.csv", sep=";", index=False) - - for row_counter, row in critical3.iterrows(): - - # Find level - level_scaling = 1.0 - if "lev+10" in row["job"]: - level_scaling = 3.162 - if "lev-10" in row["job"]: - level_scaling = 0.3162 - - # Find executables setup - REF_ENC1 = "IVAS_cod_ref_1" - REF_DEC1 = "IVAS_dec_ref_1" - DUT_ENC1 = "IVAS_cod_1" - DUT_DEC1 = "IVAS_dec_1" - REF_ENC2 = "IVAS_cod_ref_2" - REF_DEC2 = "IVAS_dec_ref_2" - DUT_ENC2 = "IVAS_cod_2" - DUT_DEC2 = "IVAS_dec_2" - - if "dec" in row["job"]: - DUT_ENC1 = "IVAS_cod_ref_1" - DUT_ENC2 = "IVAS_cod_ref_2" - if "enc" in row["job"]: - DUT_DEC1 = "IVAS_dec_ref_1" - DUT_DEC2 = "IVAS_dec_ref_2" - - script_content = REPRODUCE_REGRESSION_SCRIPT_TMPL.format( - min_date=row["min_date"], - min_sha=row["min_sha"][1:], - level_scaling=level_scaling, - testcase=row["testcase"], - REF_ENC1=REF_ENC1, - REF_DEC1=REF_DEC1, - DUT_ENC1=DUT_ENC1, - DUT_DEC1=DUT_DEC1, - REF_ENC2=REF_ENC2, - REF_DEC2=REF_DEC2, - DUT_ENC2=DUT_ENC2, - DUT_DEC2=DUT_DEC2, - ) - - script_filename = f"regression_{row_counter+2:03d}.bash" - with open(script_filename, "w") as f: - f.write(script_content) if __name__ == "__main__": @@ -239,7 +102,38 @@ if __name__ == "__main__": help="Measure for summary, one of MLD MIN_SSNR MAX_ABS_DIFF MIN_ODG, (default: MLD)", default="MLD", ) + parser.add_argument( + "--days", + type=int, + help="Number of days in history, (default: whole history)", + default=-1, + ) + parser.add_argument( + "--all_results", + action="store_true", + help="Output all results, including cases without regression (default: off)", + default=False, + ) + parser.add_argument( + "--diff_thr", + type=float, + help="Include test cases with diff above diff_thr, (default: 0.0)", + default=0.0, + ) + parser.add_argument( + "--ratio_thr", + type=float, + help="Include test cases with ratio above ratio_thr, (default: 1.0)", + default=1.0, + ) + parser.add_argument( + "--curr_value_thr", + type=float, + help="Include test cases with curr_value above curr_value_thr, (default: 0.0)", + default=0.0, + ) args = parser.parse_args() - main(args.logs_dir, args.output_filename, args.measure) + main(args.logs_dir, args.output_filename, args.measure, args.days, args.all_results, args.diff_thr, args.ratio_thr, args.curr_value_thr) + diff --git a/scripts/generate_scripts_from_regressions.py b/scripts/generate_scripts_from_regressions.py new file mode 100644 index 0000000000..4487f84480 --- /dev/null +++ b/scripts/generate_scripts_from_regressions.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python3 + +import argparse +import pandas as pd + +REPRODUCE_REGRESSION_SCRIPT_TMPL = """ +#!/bin/bash -x + +SCRIPTS_DIR=/usr/local/scripts +LTV_DIR=/usr/local/ltv + +MIN_DATE={min_date} +MIN_SHA={min_sha} +LEVEL_SCALING={level_scaling} +TESTCASE="{testcase}" + +REF_ENC1={REF_ENC1} +REF_DEC1={REF_DEC1} +DUT_ENC1={DUT_ENC1} +DUT_DEC1={DUT_DEC1} + +REF_ENC2={REF_ENC2} +REF_DEC2={REF_DEC2} +DUT_ENC2={DUT_ENC2} +DUT_DEC2={DUT_DEC2} + +INV_LEVEL_SCALING=$(awk "BEGIN {{print 1.0 / $LEVEL_SCALING}}") + +# Obtain executables from past reference +git checkout `git rev-list -1 --before="$MIN_DATE 22:00:00" ivas-float-update` +echo "ivas_float_update, min version: `git rev-parse HEAD`" > versions.txt +make clean +make -j +mv IVAS_cod IVAS_cod_ref_1 +mv IVAS_dec IVAS_dec_ref_1 +mv IVAS_rend IVAS_rend_ref_1 + +git checkout $MIN_SHA +echo "main, min version: `git rev-parse HEAD`" >> versions.txt +make clean +make -j +mv IVAS_cod IVAS_cod_1 +mv IVAS_dec IVAS_dec_1 +mv IVAS_rend IVAS_rend_1 + +# Obtain latest executables +git checkout ivas-float-update +git pull +echo "ivas-float-update, current version: `git rev-parse HEAD`" >> versions.txt +make clean +make -j +mv IVAS_cod IVAS_cod_ref_2 +mv IVAS_dec IVAS_dec_ref_2 +mv IVAS_rend IVAS_rend_ref_2 + +git checkout main +git pull +echo "main, current version: `git rev-parse HEAD`" >> versions.txt +make clean +make -j +mv IVAS_cod IVAS_cod_2 +mv IVAS_dec IVAS_dec_2 +mv IVAS_rend IVAS_rend_2 + +# Get fresh copy of scripts, tests and ci +cp -r $SCRIPTS_DIR/{{scripts,tests,ci,pytest.ini}} . +rm -rf tests/ref tests/dut tests/renderer/ref tests/renderer/cut +python3 ci/remove_unsupported_testcases.py scripts/config/self_test.prm scripts/config/self_test_ltv.prm + +# Get LTVs +cp $LTV_DIR/* scripts/testv + +# Apply level scaling +tests/scale_pcm.py ./scripts/testv/ "$LEVEL_SCALING" + +# Run tests +cp IVAS_rend_ref_1 IVAS_rend_ref +cp IVAS_rend_1 IVAS_rend +python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC1 --ref_decoder_path $REF_DEC1 +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC1 --dut_decoder_path $DUT_DEC1 --mld --ssnr --odg --scalefac $INV_LEVEL_SCALING --junit-xml=report1.xml --html=report1.html --self-contained-html +python3 scripts/parse_xml_report.py report1.xml report1.csv + +# Store results from first run +mkdir -p tests1/renderer +cp -r tests/ref tests/dut tests1 +cp -r tests/renderer/ref tests1/renderer +cp -r tests/renderer/cut tests1/renderer + +cp IVAS_rend_ref_2 IVAS_rend_ref +cp IVAS_rend_2 IVAS_rend +python3 -m pytest "$TESTCASE" -n 1 --update_ref 1 --create_ref --param_file scripts/config/self_test_ltv.prm --use_ltv --ref_encoder_path $REF_ENC2 --ref_decoder_path $REF_DEC2 +python3 -m pytest "$TESTCASE" -n 1 --create_cut --param_file scripts/config/self_test_ltv.prm --use_ltv --dut_encoder_path $DUT_ENC2 --dut_decoder_path $DUT_DEC2 --mld --ssnr --odg --scalefac $INV_LEVEL_SCALING --junit-xml=report2.xml --html=report2.html --self-contained-html +python3 scripts/parse_xml_report.py report2.xml report2.csv + +""" + + +def main(critical_list): + + critical = pd.read_csv(critical_list, sep=";") + + for row_counter, row in critical.iterrows(): + + # Find level + level_scaling = 1.0 + if "lev+10" in row["job"]: + level_scaling = 3.162 + if "lev-10" in row["job"]: + level_scaling = 0.3162 + + # Find executables setup + REF_ENC1 = "IVAS_cod_ref_1" + REF_DEC1 = "IVAS_dec_ref_1" + DUT_ENC1 = "IVAS_cod_1" + DUT_DEC1 = "IVAS_dec_1" + REF_ENC2 = "IVAS_cod_ref_2" + REF_DEC2 = "IVAS_dec_ref_2" + DUT_ENC2 = "IVAS_cod_2" + DUT_DEC2 = "IVAS_dec_2" + + if "dec" in row["job"]: + DUT_ENC1 = "IVAS_cod_ref_1" + DUT_ENC2 = "IVAS_cod_ref_2" + if "enc" in row["job"]: + DUT_DEC1 = "IVAS_dec_ref_1" + DUT_DEC2 = "IVAS_dec_ref_2" + + script_content = REPRODUCE_REGRESSION_SCRIPT_TMPL.format( + min_date=row["min_date"], + min_sha=row["min_sha"][1:], + level_scaling=level_scaling, + testcase=row["testcase"], + REF_ENC1=REF_ENC1, + REF_DEC1=REF_DEC1, + DUT_ENC1=DUT_ENC1, + DUT_DEC1=DUT_DEC1, + REF_ENC2=REF_ENC2, + REF_DEC2=REF_DEC2, + DUT_ENC2=DUT_ENC2, + DUT_DEC2=DUT_DEC2, + ) + + script_filename = f"regression_{row_counter+2:03d}.bash" + with open(script_filename, "w") as f: + f.write(script_content) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(description="Generate bash scripts to reproduce test cases from critical testcase csv list") + parser.add_argument( + "critical_list", + type=str, + help="critical file list, e.g. critical.csv", + ) + args = parser.parse_args() + main(args.critical_list) -- GitLab From 9eabb5ac9cf78cb0bd1b9e1fb390a6d491ced087 Mon Sep 17 00:00:00 2001 From: Markus Multrus Date: Sun, 7 Sep 2025 14:10:00 +0200 Subject: [PATCH 56/61] fix for MDCT concealment artifacts after DTX, if the transition frame is lost --- lib_com/options.h | 1 + lib_dec/ivas_mdct_core_dec.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/lib_com/options.h b/lib_com/options.h index 83a32c2eab..4b8f2828b7 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -176,6 +176,7 @@ #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 NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0 */ #define NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING /* FhG: Fix assert being hit in JBM code during rate switching */ +#define NONBE_FIX_1376_MDCT_CONCEALMENT /* FhG: fix concealment artifact in MDCT Stereo with DTX, in case transition frame gets lost */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_dec/ivas_mdct_core_dec.c b/lib_dec/ivas_mdct_core_dec.c index 7ba536809c..426be4d02d 100644 --- a/lib_dec/ivas_mdct_core_dec.c +++ b/lib_dec/ivas_mdct_core_dec.c @@ -1104,7 +1104,17 @@ void ivas_mdct_core_tns_ns( decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 1 ); sns_shape_spectrum( x[ch][k], st->hTcxCfg->psychParamsCurrent, &sns_int_scf[0], st->hTcxCfg->psychParamsCurrent->nBins ); +#ifdef NONBE_FIX_1376_MDCT_CONCEALMENT + /* + 2025-09-07, mul: + in case of PLC, applying SNS up to L_spec might not be enough: In case the transition frame from DTX after an inactive period is lost, L_spec is assumed to represent a regular TCX frame, + however, this frame is nevertheless acting as an transition frame as also visible in L_frameTCX; thus, the safer approach to prevent high frequency artifacts is to apply the SNS up to L_frameTCX; + in case this is not necessary, x[] is filled with zeros, and the multiplication is not causing any additional harm + */ + v_multc( x[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, sns_int_scf[FDNS_NPTS - 1], x[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, max( L_spec[ch], L_frameTCX[ch] ) - st->hTcxCfg->psychParamsCurrent->nBins ); +#else v_multc( x[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, sns_int_scf[FDNS_NPTS - 1], x[ch][k] + st->hTcxCfg->psychParamsCurrent->nBins, L_spec[ch] - st->hTcxCfg->psychParamsCurrent->nBins ); +#endif decoder_tcx_tns( st, L_frame_global[ch], L_spec[ch], L_frame[ch], L_frameTCX[ch], &x[ch][k][0], fUseTns[ch][k], &tnsData[ch][k], bfi, k, 0 ); } -- GitLab From d789e12285b751eb2412153f077c549a17f5987c Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 8 Sep 2025 14:17:33 +0200 Subject: [PATCH 57/61] Add fix NONBE_1377_REND_DIRATT_CONF for renderer configuration issue --- lib_com/options.h | 1 + lib_rend/ivas_objectRenderer.c | 23 +++++++++++++++++++++-- lib_rend/ivas_prot_rend.h | 5 +++++ lib_rend/lib_rend.c | 20 ++++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/lib_com/options.h b/lib_com/options.h index 83a32c2eab..ca82f49bfa 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -176,6 +176,7 @@ #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 NONBE_1328_FIX_NON_LINEARITY /* VA: Fix possible issue when computing bwe_exc_extended and previous frame were almost 0 */ #define NONBE_1321_JBM_ASSERT_BITRATE_SWITCHING /* FhG: Fix assert being hit in JBM code during rate switching */ +#define NONBE_1377_REND_DIRATT_CONF /* Eri: Issue 1377: Error in directivity attenuation configuration for both IVAS_dec and IVAS_rend */ /* ##################### End NON-BE switches ########################### */ diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index ed4fb71c42..9ec748af04 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -534,13 +534,16 @@ ivas_error TDREND_Update_object_positions( const ISM_METADATA_HANDLE *hIsmMetaData /* i : Input metadata for ISM objects */ ) { +#ifndef NONBE_1377_REND_DIRATT_CONF TDREND_DirAtten_t *DirAtten_p; +#endif int16_t nS; float Pos[3]; float Dir[3]; ivas_error error; - +#ifndef NONBE_1377_REND_DIRATT_CONF DirAtten_p = hBinRendererTd->DirAtten_p; +#endif /* For each source, write the frame data to the source object*/ for ( nS = 0; nS < num_src; nS++ ) @@ -557,11 +560,12 @@ ivas_error TDREND_Update_object_positions( return error; } +#ifndef NONBE_1377_REND_DIRATT_CONF if ( ( error = TDREND_MIX_SRC_SetDirAtten( hBinRendererTd, nS, DirAtten_p ) ) != IVAS_ERR_OK ) { return error; } - +#endif if ( ( error = TDREND_MIX_SRC_SetGain( hBinRendererTd, nS, hIsmMetaData[nS]->gain ) ) != IVAS_ERR_OK ) { return error; @@ -675,13 +679,24 @@ ivas_error ivas_td_binaural_open_ext( AUDIO_CONFIG inConfig, RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */ LSSETUP_CUSTOM_STRUCT *customLsInput, +#ifdef NONBE_1377_REND_DIRATT_CONF + const int32_t outFs, /* i: output sampling rate */ + const IVAS_REND_InputId id /* i: ISM ID */ +) +#else const int32_t outFs ) +#endif { int16_t nchan_transport; AUDIO_CONFIG transport_config; IVAS_FORMAT ivas_format; IVAS_OUTPUT_SETUP hTransSetup; ivas_error error; +#ifdef NONBE_1377_REND_DIRATT_CONF + int16_t ism_number; + + ism_number = id & 0x00FF; /* Exctract ISM number from ID */ +#endif float *distAtt = NULL; float *directivity = NULL; @@ -716,7 +731,11 @@ ivas_error ivas_td_binaural_open_ext( distAtt = hRendCfg->distAtt; } +#ifdef NONBE_1377_REND_DIRATT_CONF + return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity + 3 * ism_number, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); +#else return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); +#endif } diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 126112a7db..2617bae683 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -661,7 +661,12 @@ ivas_error ivas_td_binaural_open_ext( const AUDIO_CONFIG inConfig, RENDER_CONFIG_DATA *hRendCfg, /* i : Renderer configuration */ LSSETUP_CUSTOM_STRUCT *customLsInput, +#ifdef NONBE_1377_REND_DIRATT_CONF + const int32_t outFs, /* i: output sampling rate */ + const IVAS_REND_InputId id /* i: ISM ID */ +#else const int32_t output_Fs +#endif ); void ivas_td_binaural_close( diff --git a/lib_rend/lib_rend.c b/lib_rend/lib_rend.c index 180fd5dabd..4d12d71e39 100644 --- a/lib_rend/lib_rend.c +++ b/lib_rend/lib_rend.c @@ -1608,7 +1608,11 @@ static ivas_error setRendInputActiveIsm( if ( outConfig == IVAS_AUDIO_CONFIG_BINAURAL || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || outConfig == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { +#ifdef NONBE_1377_REND_DIRATT_CONF + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, id ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1616,7 +1620,11 @@ static ivas_error setRendInputActiveIsm( /* Open TD renderer wrappers */ for ( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) { +#ifdef NONBE_1377_REND_DIRATT_CONF + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->splitTdRendWrappers[i], inConfig, hRendCfg, NULL, *inputIsm->base.ctx.pOutSampleRate, id ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputIsm->splitTdRendWrappers[i], inConfig, hRendCfg, NULL, *inputIsm->base.ctx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -1634,7 +1642,11 @@ static ivas_error setRendInputActiveIsm( } else { +#ifdef NONBE_1377_REND_DIRATT_CONF + if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate, id ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputIsm->tdRendWrapper, inConfig, hRendCfg, NULL, *rendCtx.pOutSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -2391,7 +2403,11 @@ static ivas_error initMcBinauralRendering( if ( useTDRend && inputMc->tdRendWrapper.hBinRendererTd == NULL ) { +#ifdef NONBE_1377_REND_DIRATT_CONF + if ( ( error = ivas_td_binaural_open_ext( &inputMc->tdRendWrapper, inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate, 0 ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputMc->tdRendWrapper, inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -2401,7 +2417,11 @@ static ivas_error initMcBinauralRendering( /* Open TD renderer wrappers */ for ( i = 0; i < MAX_HEAD_ROT_POSES - 1; ++i ) { +#ifdef NONBE_1377_REND_DIRATT_CONF + if ( ( error = ivas_td_binaural_open_ext( &inputMc->splitTdRendWrappers[i], inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate, 0 ) ) != IVAS_ERR_OK ) +#else if ( ( error = ivas_td_binaural_open_ext( &inputMc->splitTdRendWrappers[i], inConfig, hRendCfg, &inputMc->customLsInput, outSampleRate ) ) != IVAS_ERR_OK ) +#endif { return error; } -- GitLab From 82516ccb698dce429ee52733586e66bdb815d0ca Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 8 Sep 2025 14:49:15 +0200 Subject: [PATCH 58/61] Move init of ism_number away from declaration section. --- lib_rend/ivas_objectRenderer.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index 9ec748af04..c8152349c3 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -694,13 +694,15 @@ ivas_error ivas_td_binaural_open_ext( ivas_error error; #ifdef NONBE_1377_REND_DIRATT_CONF int16_t ism_number; - - ism_number = id & 0x00FF; /* Exctract ISM number from ID */ #endif float *distAtt = NULL; float *directivity = NULL; +#ifdef NONBE_1377_REND_DIRATT_CONF + ism_number = id & 0x00FF; /* Exctract ISM number from ID */ +#endif + if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM ) { if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ) != IVAS_ERR_OK ) -- GitLab From a600c7071a3c5293279cf0184f58d6a730ba48c5 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Mon, 8 Sep 2025 15:15:55 +0200 Subject: [PATCH 59/61] Fix for null pointer access --- lib_rend/ivas_objectRenderer.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/lib_rend/ivas_objectRenderer.c b/lib_rend/ivas_objectRenderer.c index c8152349c3..6e836e141c 100644 --- a/lib_rend/ivas_objectRenderer.c +++ b/lib_rend/ivas_objectRenderer.c @@ -699,10 +699,6 @@ ivas_error ivas_td_binaural_open_ext( float *distAtt = NULL; float *directivity = NULL; -#ifdef NONBE_1377_REND_DIRATT_CONF - ism_number = id & 0x00FF; /* Exctract ISM number from ID */ -#endif - if ( inConfig != IVAS_AUDIO_CONFIG_LS_CUSTOM ) { if ( ( error = getAudioConfigNumChannels( inConfig, &nchan_transport ) ) != IVAS_ERR_OK ) @@ -729,15 +725,16 @@ ivas_error ivas_td_binaural_open_ext( if ( NULL != hRendCfg ) { +#ifdef NONBE_1377_REND_DIRATT_CONF + ism_number = id & 0x00FF; /* Exctract ISM number from ID */ + directivity = hRendCfg->directivity + 3 * ism_number; +#else directivity = hRendCfg->directivity; +#endif distAtt = hRendCfg->distAtt; } -#ifdef NONBE_1377_REND_DIRATT_CONF - return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity + 3 * ism_number, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); -#else return ivas_td_binaural_open_unwrap( pTDRend->hHrtfTD, outFs, nchan_transport, ivas_format, transport_config, directivity, distAtt, hTransSetup, &pTDRend->hBinRendererTd, &pTDRend->binaural_latency_ns ); -#endif } -- GitLab From 3b9dbde7a3fb19322843992d71068ecdf1ce8a27 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 9 Sep 2025 16:43:19 +0200 Subject: [PATCH 60/61] Postpone change to renderer/utils.py --- tests/renderer/utils.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tests/renderer/utils.py b/tests/renderer/utils.py index 3eb3a1e5a4..1e66afd606 100644 --- a/tests/renderer/utils.py +++ b/tests/renderer/utils.py @@ -271,13 +271,6 @@ def run_renderer( if in_meta_files is None and in_fmt in format_to_metadata_files: in_meta_files = format_to_metadata_files[in_fmt] - # If metadata not given with ISM input, use default NULL - if in_meta_files is None and isinstance(in_fmt, str) and "ism" in in_fmt.lower(): - match = re.search(r"ism(\d)", in_fmt.lower()) - assert match is not None - num_obj = int(match[1]) - in_meta_files = ["NULL"] * num_obj - if out_file is None: out_file_stem = f"{in_name}_to_{out_name}{trj_name}{non_diegetic_pan}{refrot_name}{refvec_name}{refveclev_name}{config_name}{framing_name}{hrtf_file_name}{name_extension}{aeid_name}.wav" out_file = str(output_path_base.joinpath(out_file_stem)) -- GitLab From 70bc133aba9bb64a7fc269367891574324f5e5d2 Mon Sep 17 00:00:00 2001 From: Erik Norvell Date: Tue, 9 Sep 2025 18:55:15 +0200 Subject: [PATCH 61/61] Add object editing test case to ci/remove_unsupported_testcases.py --- ci/remove_unsupported_testcases.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/remove_unsupported_testcases.py b/ci/remove_unsupported_testcases.py index 66b62b04ef..3d483deca7 100644 --- a/ci/remove_unsupported_testcases.py +++ b/ci/remove_unsupported_testcases.py @@ -55,6 +55,7 @@ TESTCASES = [ "OSBA 3OA 4ISM at 256 kbps, 48kHz in, 48kHz out, BINAURAL out, object editing, DISC", "OSBA 2OA 3ISM at 128 kbps, 48kHz in, 48kHz out, FOA out, object editing, JBM Prof 5, DISC", "OSBA 2OA 3ISM at bitrate switching 13.2 to 512 kbps, 48kHz in, 48kHz out, BINAURAL out, object editing", + "OSBA 3OA 4ISM at 256 kbps, 48kHz in, 48kHz out, BINAURAL_ROOM_IR out, object editing, DISC", # self_test_ltv.prm "OMASA 2TC 4ISM at br sw techs 13.2 to 512 kbps start 80 kbps, 48kHz in, 48kHz out, EXT out", "OMASA 2TC 2ISM at 96 kbps, 48kHz in, 48kHz out, FOA out, object editing, JBM Prof 5, DISC", -- GitLab