From c88444aae12dd387a2661877b2c239bf3edbb8ce Mon Sep 17 00:00:00 2001 From: vaclav Date: Tue, 21 Oct 2025 13:26:46 +0200 Subject: [PATCH 1/3] port UNIFIED_DECODING_PATHS_LEFTOVERS --- lib_com/ivas_cnst.h | 4 + lib_com/ivas_prot.h | 8 +- lib_com/options.h | 8 +- lib_dec/ivas_dirac_dec.c | 2 +- lib_dec/ivas_ism_param_dec.c | 93 +- lib_dec/ivas_jbm_dec.c | 173 +- lib_dec/ivas_mc_param_dec.c | 2713 +++++++++++++------------ lib_dec/ivas_osba_dec.c | 2 +- lib_dec/ivas_sba_rendering_internal.c | 6 +- lib_dec/ivas_stat_dec.h | 20 +- lib_dec/lib_dec.c | 2 + 11 files changed, 1628 insertions(+), 1403 deletions(-) diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 0dfee8036..61b980fd7 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -175,7 +175,11 @@ typedef enum #define MAX_JBM_L_FRAME48k 1920 #define MAX_JBM_L_FRAME_NS 40000000L #define MAX_SPAR_INTERNAL_CHANNELS IVAS_SPAR_MAX_CH +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS +#define MAX_CLDFB_DIGEST_CHANNELS 3 /* == maximum of ParamISM TCs and ParamMC TCs */ +#else #define MAX_CLDFB_DIGEST_CHANNELS (FOA_CHANNELS + MAX_NUM_OBJECTS) +#endif typedef enum { diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index a4db085e2..999249ca0 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -888,12 +888,13 @@ int16_t ivas_jbm_dec_get_num_tc_channels( Decoder_Struct *st_ivas /* i : IVAS decoder handle */ ); +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS void ivas_jbm_dec_copy_tc_no_tsm( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ float *tc[], /* i : transport channels */ const int16_t output_frame /* i : output frame size */ ); - +#endif void ivas_jbm_dec_get_md_map_even_spacing( const int16_t len, /* i : length of the modfied frames in metadata slots */ const int16_t subframe_len, /* i : default length of a subframe */ @@ -1142,7 +1143,7 @@ void ivas_ism_dec_digest_tc( void ivas_param_ism_dec_digest_tc( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nCldfbSlots, /* i : number of CLDFB slots in transport channels */ - float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ + float *p_data_f[] /* i : synthesized core-coder transport channels/DirAC output */ ); #ifdef OBJ_EDITING_API @@ -1156,13 +1157,14 @@ void ivas_param_ism_dec_prepare_renderer( ); #endif +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS void ivas_ism_param_dec_tc_gain_ajust( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nSamples, /* i : number of samples to be compensate */ const uint16_t nFadeLength, /* i : length of the crossfade in samples */ float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output */ ); - +#endif void ivas_param_ism_dec_render( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ diff --git a/lib_com/options.h b/lib_com/options.h index eecc2fe25..98a17a78d 100644 --- a/lib_com/options.h +++ b/lib_com/options.h @@ -196,15 +196,9 @@ #define FIX_1388_MSAN_ivas_init_decoder /* VA: issue 1388: fix use-of-uninitialized value in ivas_init_decoder() */ #define FIX_1288_SPLIT_REND_XSAN /* Dlb: Fix asan, msan and usan issues in split rendering mode*/ #define LIB_DEC_REVISION /* VA: cleaning and simplification of lib_dec.c */ +#define UNIFIED_DECODING_PATHS_LEFTOVERS /* VA: issue 880: remove leftovers after NONBE_UNIFIED_DECODING_PATHS */ // object-editing feature porting -#define OBJ_EDITING_API /* object editing changes related to the API */ -#ifdef OBJ_EDITING_API -#define TMP_FIX_SPLIT_REND // temporary fix to split-rendering (it follows the later state of the framework but it is needed now because of current test-conditions) -#define TMP_FIX_OMASA_SR_BE // temporary fix to keep OMASA split-rendering BE -#endif - -// objject-editing feature porting #define OBJ_EDITING_INTERFACE /* Interface for object editing */ #ifdef OBJ_EDITING_INTERFACE #define OBJ_EDITING_API /* object editing changes related to the API */ diff --git a/lib_dec/ivas_dirac_dec.c b/lib_dec/ivas_dirac_dec.c index 493c38e44..afdd6b1c2 100644 --- a/lib_dec/ivas_dirac_dec.c +++ b/lib_dec/ivas_dirac_dec.c @@ -1552,7 +1552,7 @@ void ivas_dirac_dec_render( uint16_t slot_size, n_samples_sf, ch, nchan_intern; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; float *output_f_local[MAX_OUTPUT_CHANNELS]; - float output_f_local_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; // VE2SB: TBV + float output_f_local_buff[MAX_OUTPUT_CHANNELS][L_FRAME48k]; hSpatParamRendCom = st_ivas->hSpatParamRendCom; diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index d2144ea84..2239c602d 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -45,12 +45,21 @@ #include "wmc_auto.h" +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS +/*-----------------------------------------------------------------------* + * Local function declarations + *-----------------------------------------------------------------------*/ + +static void ivas_ism_param_dec_tc_gain_adjust( Decoder_Struct *st_ivas, const int16_t nSamples, const int16_t nFadeLength, float *p_data_f[] ); + +#endif + /*-----------------------------------------------------------------------* * Local function definitions *-----------------------------------------------------------------------*/ static void ivas_param_ism_dec_dequant_DOA( - PARAM_ISM_DEC_HANDLE hParamIsmDec, /* i/o: decoder ParamISM handle */ + PARAM_ISM_DEC_HANDLE hParamIsmDec, /* i/o: decoder ParamISM handle */ const int16_t nchan_ism /* i : number of ISM channels */ ) { @@ -818,11 +827,16 @@ void ivas_ism_dec_digest_tc( *-------------------------------------------------------------------------*/ void ivas_param_ism_dec_digest_tc( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint16_t nCldfbSlots, /* i : number of CLDFB slots in transport channels */ - float *transport_channels_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nCldfbSlots, /* i : number of CLDFB slots in transport channels */ + float *p_data_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ ) { +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + int16_t ch, slot_idx, output_frame; + int16_t num_freq_bands, cldfb_ch, n_ch_cldfb; + float *cldfb_real_buffer, *cldfb_imag_buffer; +#else #ifndef OBJ_EDITING_API int16_t ch, nchan_transport, nchan_out, nchan_out_woLFE, i; int16_t slot_idx, bin_idx; @@ -841,8 +855,17 @@ void ivas_param_ism_dec_digest_tc( PARAM_ISM_DEC_HANDLE hParamIsmDec; SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; int16_t fade_len; +#endif /* Initialization */ +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + num_freq_bands = st_ivas->hSpatParamRendCom->num_freq_bands; + output_frame = nCldfbSlots * num_freq_bands; + n_ch_cldfb = st_ivas->hTcBuffer->nchan_transport_jbm - st_ivas->hTcBuffer->nchan_buffer_full; + + cldfb_real_buffer = st_ivas->hParamIsmDec->hParamIsmRendering->Cldfb_RealBuffer_tc; + cldfb_imag_buffer = st_ivas->hParamIsmDec->hParamIsmRendering->Cldfb_ImagBuffer_tc; +#else hParamIsmDec = st_ivas->hParamIsmDec; assert( hParamIsmDec ); hSpatParamRendCom = st_ivas->hSpatParamRendCom; @@ -851,6 +874,7 @@ void ivas_param_ism_dec_digest_tc( fade_len = output_frame / 2; nchan_transport = st_ivas->nchan_transport; +#endif #ifndef OBJ_EDITING_API ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; @@ -867,9 +891,6 @@ void ivas_param_ism_dec_digest_tc( nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; } #endif - - push_wmops( "ivas_param_ism_dec_digest_tc" ); - #ifndef OBJ_EDITING_API /* general setup */ ivas_jbm_dec_get_adapted_linear_interpolator( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbSlots, hParamIsmDec->hParamIsmRendering->interpolator ); @@ -946,12 +967,29 @@ void ivas_param_ism_dec_digest_tc( } } #endif +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + ivas_ism_param_dec_tc_gain_adjust( st_ivas, output_frame, output_frame / 2, p_data_f ); +#else if ( st_ivas->hDecoderConfig->Opt_tsm ) { /*TODO : FhG to check*/ - ivas_ism_param_dec_tc_gain_ajust( st_ivas, output_frame, fade_len, transport_channels_f ); + ivas_ism_param_dec_tc_gain_ajust( st_ivas, output_frame, fade_len, p_data_f ); } +#endif +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + /* CLDFB Analysis */ + for ( ch = 0, cldfb_ch = 0; cldfb_ch < n_ch_cldfb; cldfb_ch++, ch++ ) + { + for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) + { + cldfbAnalysis_ts( &( p_data_f[ch][num_freq_bands * slot_idx] ), + &cldfb_real_buffer[slot_idx * num_freq_bands * n_ch_cldfb + cldfb_ch * num_freq_bands], + &cldfb_imag_buffer[slot_idx * num_freq_bands * n_ch_cldfb + cldfb_ch * num_freq_bands], + num_freq_bands, st_ivas->cldfbAnaDec[cldfb_ch] ); + } + } +#else for ( ch = 0; ch < nchan_transport; ch++ ) { /* CLDFB Analysis */ @@ -963,7 +1001,7 @@ void ivas_param_ism_dec_digest_tc( float RealBuffer[CLDFB_NO_CHANNELS_MAX]; float ImagBuffer[CLDFB_NO_CHANNELS_MAX]; - cldfbAnalysis_ts( &( transport_channels_f[ch][hSpatParamRendCom->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hSpatParamRendCom->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); + cldfbAnalysis_ts( &( p_data_f[ch][hSpatParamRendCom->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hSpatParamRendCom->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); mvr2r( RealBuffer, &hParamIsmDec->hParamIsmRendering->Cldfb_RealBuffer_tc[slot_idx * hSpatParamRendCom->num_freq_bands * nchan_transport + ch * hSpatParamRendCom->num_freq_bands], hSpatParamRendCom->num_freq_bands ); mvr2r( ImagBuffer, &hParamIsmDec->hParamIsmRendering->Cldfb_ImagBuffer_tc[slot_idx * hSpatParamRendCom->num_freq_bands * nchan_transport + ch * hSpatParamRendCom->num_freq_bands], hSpatParamRendCom->num_freq_bands ); } @@ -983,8 +1021,7 @@ void ivas_param_ism_dec_digest_tc( /* Compute mixing matrix */ ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hParamIsmDec, st_ivas->hISMDTX, direct_response, nchan_transport, nchan_out_woLFE, cx_diag, ref_power, hParamIsmDec->hParamIsmRendering->mixing_matrix_lin ); #endif - - pop_wmops(); +#endif return; } @@ -1057,8 +1094,6 @@ void ivas_param_ism_dec_prepare_renderer( nchan_out_woLFE = st_ivas->hIntSetup.nchan_out_woLFE; } - push_wmops( "ivas_param_ism_dec_digest_tc" ); - /* general setup */ ivas_jbm_dec_get_adapted_linear_interpolator( DEFAULT_JBM_CLDFB_TIMESLOTS, nCldfbSlots, hParamIsmDec->hParamIsmRendering->interpolator ); @@ -1143,24 +1178,26 @@ void ivas_param_ism_dec_prepare_renderer( /* Compute mixing matrix */ ivas_param_ism_compute_mixing_matrix( st_ivas->nchan_ism, hParamIsmDec, st_ivas->hISMDTX, direct_response, nchan_transport, nchan_out_woLFE, cx_diag, ref_power, hParamIsmDec->hParamIsmRendering->mixing_matrix_lin ); - pop_wmops(); - return; } #endif /*-------------------------------------------------------------------------* - * ivas_ism_param_dec_tc_gain_ajust() + * ivas_ism_param_dec_tc_gain_adjust() * * *-------------------------------------------------------------------------*/ +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS +static void ivas_ism_param_dec_tc_gain_adjust( +#else void ivas_ism_param_dec_tc_gain_ajust( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint16_t nSamples, /* i : number of samples to be compensate */ - const uint16_t nFadeLength, /* i : length of the crossfade in samples */ - float *transport_channels_f[] /* i : synthesized core-coder transport channels/DirAC output*/ +#endif + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamples, /* i : number of samples to be compensate */ + const uint16_t nFadeLength, /* i : length of the crossfade in samples */ + float *p_data_f[] /* i : synthesized core-coder transport channels/DirAC output*/ ) { @@ -1174,8 +1211,8 @@ void ivas_ism_param_dec_tc_gain_ajust( for ( i = 0; i < nSamples; i++ ) { - ene_tc += transport_channels_f[0][i] * transport_channels_f[0][i] + transport_channels_f[1][i] * transport_channels_f[1][i]; /* L*L + R*R */ - ene_sum += ( transport_channels_f[0][i] + transport_channels_f[1][i] ) * ( transport_channels_f[0][i] + transport_channels_f[1][i] ); /* (L+R)*(L+R) */ + ene_tc += p_data_f[0][i] * p_data_f[0][i] + p_data_f[1][i] * p_data_f[1][i]; /* L*L + R*R */ + ene_sum += ( p_data_f[0][i] + p_data_f[1][i] ) * ( p_data_f[0][i] + p_data_f[1][i] ); /* (L+R)*(L+R) */ } gain = sqrtf( ene_tc / ( ene_sum + EPSILON ) ); if ( st_ivas->hSCE[0]->hCoreCoder[0]->ini_frame > 1 ) @@ -1186,21 +1223,21 @@ void ivas_ism_param_dec_tc_gain_ajust( grad = ( gain - last_gain ) / (float) nFadeLength; /* slope between two consecutive gains, 480 samples length */ for ( i = 0; i < ( nFadeLength ); i++ ) { - transport_channels_f[0][i] *= ( last_gain + i * grad ); - transport_channels_f[1][i] *= ( last_gain + i * grad ); + p_data_f[0][i] *= ( last_gain + i * grad ); + p_data_f[1][i] *= ( last_gain + i * grad ); } for ( ; i < nSamples; i++ ) { - transport_channels_f[0][i] *= gain; - transport_channels_f[1][i] *= gain; + p_data_f[0][i] *= gain; + p_data_f[1][i] *= gain; } } else { for ( i = 0; i < nSamples; i++ ) { - transport_channels_f[0][i] *= gain; - transport_channels_f[1][i] *= gain; + p_data_f[0][i] *= gain; + p_data_f[1][i] *= gain; } } diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 62006552c..8e048026e 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -50,8 +50,9 @@ * Local function prototypes *-----------------------------------------------------------------------*/ +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS static void ivas_jbm_dec_copy_tc( Decoder_Struct *st_ivas, const int16_t nSamplesForRendering, int16_t *nSamplesResidual, float *data, float *tc_digest_f[] ); - +#endif static void ivas_jbm_dec_tc_buffer_playout( Decoder_Struct *st_ivas, const uint16_t nSamplesAsked, uint16_t *nSamplesRendered, float *output[] ); static void ivas_jbm_dec_copy_masa_meta_to_buffer( Decoder_Struct *st_ivas ); @@ -97,6 +98,7 @@ ivas_error ivas_jbm_dec_tc( output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + /* set pointers to transport channels audio */ for ( n = 0; n < MAX_TRANSPORT_CHANNELS; n++ ) { p_output[n] = st_ivas->p_output_f[n]; @@ -214,11 +216,12 @@ ivas_error ivas_jbm_dec_tc( { return error; } - +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->hDecoderConfig->Opt_tsm ) { ivas_jbm_dec_copy_masa_meta_to_buffer( st_ivas ); } +#endif } else if ( st_ivas->ivas_format == SBA_FORMAT ) { @@ -312,8 +315,9 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->ivas_format == MASA_FORMAT ) { ivas_masa_prerender( st_ivas, p_output, output_frame, nchan_remapped ); + /* external output */ - if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->hMasa->config.input_ivas_format == MASA_ISM_FORMAT ) + if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->hMasa->config.input_ivas_format == MASA_ISM_FORMAT ) { for ( n = 0; n < st_ivas->nchan_ism; n++ ) { @@ -412,10 +416,12 @@ ivas_error ivas_jbm_dec_tc( /* Extract objects from MASA, output MASA + all objects (i.e., extracted and separated objects) */ ivas_omasa_render_objects_from_mix( st_ivas, p_output, st_ivas->nchan_ism, output_frame ); } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS if ( st_ivas->hDecoderConfig->Opt_tsm ) { ivas_jbm_dec_copy_masa_meta_to_buffer( st_ivas ); } +#endif } } else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) @@ -726,6 +732,7 @@ ivas_error ivas_jbm_dec_tc( } } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS /*----------------------------------------------------------------* * Write IVAS transport channels *----------------------------------------------------------------*/ @@ -743,7 +750,7 @@ ivas_error ivas_jbm_dec_tc( /* directly copy to tc buffers */ ivas_jbm_dec_copy_tc_no_tsm( st_ivas, p_output, output_frame ); } - +#endif /*----------------------------------------------------------------* * Common updates *----------------------------------------------------------------*/ @@ -780,6 +787,112 @@ ivas_error ivas_jbm_dec_tc( } +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + +/*--------------------------------------------------------------------------* + * ivas_dec_feed_tc_to_renderer() + * + * Feed decoded transport channels to the IVAS renderer routine + * + digest TC channels in ParamISM and ParamMC + *--------------------------------------------------------------------------*/ + +void ivas_jbm_dec_feed_tc_to_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ + int16_t *nSamplesResidual, /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ + float *data /* i : transport channels */ +) +{ + float data_f[MAX_CLDFB_DIGEST_CHANNELS][MAX_JBM_L_FRAME48k]; /* 'float' buffer for transport channels that will be directly converted with the CLDFB */ + float *p_data_f[MAX_CLDFB_DIGEST_CHANNELS]; + int16_t n, n_render_timeslots, n_ch_cldfb; + int16_t ch; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + hTcBuffer = st_ivas->hTcBuffer; + n_ch_cldfb = hTcBuffer->nchan_transport_jbm - hTcBuffer->nchan_buffer_full; + + if ( st_ivas->hDecoderConfig->Opt_tsm ) + { + int16_t n_samples_still_available, m; + int16_t n_ch_full_copy; + int16_t n_ch_res_copy; + + for ( n = 0; n < n_ch_cldfb; n++ ) + { + p_data_f[n] = &data_f[n][0]; + } + + n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; + hTcBuffer->n_samples_buffered = n_samples_still_available + nSamplesForRendering + hTcBuffer->n_samples_discard; + hTcBuffer->n_samples_available = hTcBuffer->n_samples_granularity * ( hTcBuffer->n_samples_buffered / hTcBuffer->n_samples_granularity ); + *nSamplesResidual = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_available; + 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; + + for ( ch = 0; ch < n_ch_full_copy; ch++ ) + { + set_zero( hTcBuffer->tc[ch], hTcBuffer->n_samples_discard ); + mvr2r( hTcBuffer->tc[ch] + hTcBuffer->n_samples_rendered, hTcBuffer->tc[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); + for ( m = 0; m < nSamplesForRendering; m++ ) + { + hTcBuffer->tc[ch][n_samples_still_available + hTcBuffer->n_samples_discard + m] = data[m * hTcBuffer->nchan_transport_jbm + ch]; + } + } + + if ( n_ch_res_copy > 0 ) + { + for ( ; ch < hTcBuffer->nchan_transport_jbm; ch++ ) + { + mvr2r( hTcBuffer->tc[ch], p_data_f[ch], n_samples_still_available ); + + for ( m = 0; m < nSamplesForRendering; m++ ) + { + p_data_f[ch][n_samples_still_available + m] = data[m * hTcBuffer->nchan_transport_jbm + ch]; + } + mvr2r( p_data_f[ch] + hTcBuffer->n_samples_available, hTcBuffer->tc[ch], *nSamplesResidual ); + } + } + + n_render_timeslots = hTcBuffer->n_samples_available / hTcBuffer->n_samples_granularity; + } + else + { + for ( n = 0; n < n_ch_cldfb; n++ ) + { + p_data_f[n] = &st_ivas->p_output_f[n][0]; + } + + for ( n = 0; n < ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ); n++ ) + { + hTcBuffer->tc[n] = st_ivas->p_output_f[n]; /* note: buffers needed in the TD decorellator */ + } + + hTcBuffer->n_samples_buffered = nSamplesForRendering; + hTcBuffer->n_samples_available = hTcBuffer->n_samples_buffered; + *nSamplesResidual = 0; + + n_render_timeslots = DEFAULT_JBM_CLDFB_TIMESLOTS; + } + + /* CLDFB analysis for ParamMC/ParamISM */ + if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) ) + { + ivas_param_ism_dec_digest_tc( st_ivas, n_render_timeslots, p_data_f ); + } + else if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC && hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_RENDERER ) + { + ivas_param_mc_dec_digest_tc( st_ivas, (uint8_t) n_render_timeslots, p_data_f ); + } + + hTcBuffer->n_samples_rendered = 0; + hTcBuffer->subframes_rendered = 0; + + return; +} + +#else + /*--------------------------------------------------------------------------* * ivas_jbm_dec_feed_tc_to_renderer() * @@ -991,6 +1104,7 @@ void ivas_jbm_dec_feed_tc_to_renderer( return; } +#endif /*--------------------------------------------------------------------------* * ivas_dec_render() @@ -1016,7 +1130,9 @@ ivas_error ivas_jbm_dec_render( ivas_error error; float *p_output[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; float *p_tc[MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS]; +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS SPAT_PARAM_REND_COMMON_DATA_HANDLE hSpatParamRendCom; +#endif int16_t nchan_out_syn_output; push_wmops( "ivas_dec_render" ); @@ -1024,7 +1140,9 @@ ivas_error ivas_jbm_dec_render( * Initialization of local vars after struct has been set *----------------------------------------------------------------*/ +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS hSpatParamRendCom = st_ivas->hSpatParamRendCom; +#endif output_Fs = st_ivas->hDecoderConfig->output_Fs; nchan_out = st_ivas->hDecoderConfig->nchan_out; nchan_transport = st_ivas->hTcBuffer->nchan_transport_jbm; @@ -1038,24 +1156,29 @@ ivas_error ivas_jbm_dec_render( if ( !st_ivas->hDecoderConfig->Opt_tsm ) { +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS for ( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) { p_tc[n] = &p_output[n][st_ivas->hTcBuffer->n_samples_rendered]; } - +#endif for ( n = 0; n < MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS; n++ ) { st_ivas->hTcBuffer->tc[n] = p_output[n]; } } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS else { +#endif for ( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) { p_tc[n] = &st_ivas->hTcBuffer->tc[n][st_ivas->hTcBuffer->n_samples_rendered]; } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS } +#endif /*----------------------------------------------------------------* * Update combined orientation access index @@ -1132,7 +1255,11 @@ ivas_error ivas_jbm_dec_render( #endif { /* Convert to Ambisonics */ +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + ivas_ism2sba_sf( p_tc, p_output, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); +#else ivas_ism2sba_sf( st_ivas->hTcBuffer->tc, p_output, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); +#endif } /* Binaural rendering */ @@ -1259,7 +1386,7 @@ ivas_error ivas_jbm_dec_render( return error; } } - else if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) /*EXT output = individual objects + HOA3*/ + else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) /*EXT output = individual objects + HOA3*/ { if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, &p_output[st_ivas->nchan_ism] ) ) != IVAS_ERR_OK ) { @@ -1268,7 +1395,11 @@ ivas_error ivas_jbm_dec_render( for ( n = 0; n < st_ivas->nchan_ism; n++ ) { +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + mvr2r( p_tc[n], p_output[n], *nSamplesRendered ); +#else mvr2r( st_ivas->hTcBuffer->tc[n] + st_ivas->hTcBuffer->n_samples_rendered, p_output[n], *nSamplesRendered ); +#endif } } else @@ -1294,7 +1425,7 @@ ivas_error ivas_jbm_dec_render( return error; } - if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) + if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { #ifdef DEBUGGING assert( st_ivas->ism_mode == ISM_MODE_NONE ); @@ -1308,6 +1439,7 @@ ivas_error ivas_jbm_dec_render( set_zero( p_output[n], *nSamplesRendered ); } } + for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) { v_multc( p_output[n], 2.0f, p_output[n], *nSamplesRendered ); @@ -1316,11 +1448,12 @@ ivas_error ivas_jbm_dec_render( } else if ( st_ivas->ivas_format == MC_FORMAT ) { - +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS for ( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) { p_tc[n] = &st_ivas->hTcBuffer->tc[n][st_ivas->hTcBuffer->n_samples_rendered]; } +#endif if ( st_ivas->mc_mode == MC_MODE_MCT ) { int16_t crendInPlaceRotation = FALSE; @@ -1415,7 +1548,9 @@ ivas_error ivas_jbm_dec_render( } else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) { +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS int16_t offset = hSpatParamRendCom->slots_rendered * hSpatParamRendCom->slot_size; +#endif nchan_remapped = st_ivas->nchan_transport; if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { @@ -1430,7 +1565,11 @@ ivas_error ivas_jbm_dec_render( /* we still need to copy the separate channel if available */ if ( st_ivas->hOutSetup.separateChannelEnabled ) { +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); +#else mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL - 1] + offset, p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); +#endif } ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); @@ -1451,13 +1590,23 @@ ivas_error ivas_jbm_dec_render( output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) { +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + mvr2r( p_tc[LFE_CHANNEL], p_output[LFE_CHANNEL], *nSamplesRendered ); + mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); +#else mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL] + offset, p_output[LFE_CHANNEL], *nSamplesRendered ); mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL - 1] + offset, p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); +#endif } else if ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) { /* Delay the separated channel to sync with the DirAC rendering */ + +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); +#else mvr2r( st_ivas->hTcBuffer->tc[LFE_CHANNEL - 1] + offset, p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); +#endif } } } @@ -2209,6 +2358,7 @@ int16_t ivas_jbm_dec_get_num_tc_channels( return num_tc; } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS /*--------------------------------------------------------------------------* * ivas_jbm_dec_copy_tc() @@ -2268,6 +2418,7 @@ static void ivas_jbm_dec_copy_tc( return; } +#endif /*--------------------------------------------------------------------------* * ivas_jbm_dec_get_render_granularity() @@ -2794,6 +2945,7 @@ TC_BUFFER_MODE ivas_jbm_dec_get_tc_buffer_mode( return buffer_mode; } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS /*--------------------------------------------------------------------------* * ivas_jbm_dec_copy_tc_no_tsm() @@ -2867,6 +3019,7 @@ void ivas_jbm_dec_copy_tc_no_tsm( return; } +#endif /*--------------------------------------------------------------------------* * ivas_jbm_dec_metadata_open() @@ -2956,6 +3109,10 @@ static void ivas_jbm_masa_sf_to_slot_map( int16_t slot_idx; int16_t write_idx, sf_index; +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + ivas_jbm_dec_copy_masa_meta_to_buffer( st_ivas ); + +#endif /* Set values */ hJbmMetadata = st_ivas->hJbmMetadata; num_slots_in_subfr = CLDFB_NO_COL_MAX / MAX_PARAM_SPATIAL_SUBFRAMES; diff --git a/lib_dec/ivas_mc_param_dec.c b/lib_dec/ivas_mc_param_dec.c index 77c048a06..ac55ec200 100644 --- a/lib_dec/ivas_mc_param_dec.c +++ b/lib_dec/ivas_mc_param_dec.c @@ -1335,6 +1335,10 @@ void ivas_param_mc_dec_digest_tc( float *p_data_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ ) { +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + int16_t ch, num_freq_bands, slot_idx, cldfb_ch, n_ch_cldfb; + float *cldfb_real_buffer, *cldfb_imag_buffer; +#else PARAM_MC_DEC_HANDLE hParamMC; #ifdef OBJ_EDITING_API int16_t ch, slot_idx; @@ -1357,17 +1361,25 @@ void ivas_param_mc_dec_digest_tc( /* format converter */ int16_t channel_active[MAX_OUTPUT_CHANNELS]; IVAS_OUTPUT_SETUP *hSynthesisOutputSetup; +#endif #endif + /* Initialization */ +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + num_freq_bands = st_ivas->hParamMC->num_freq_bands; + n_ch_cldfb = st_ivas->hTcBuffer->nchan_transport_jbm - st_ivas->hTcBuffer->nchan_buffer_full; + + cldfb_real_buffer = st_ivas->hParamMC->Cldfb_RealBuffer_tc; + cldfb_imag_buffer = st_ivas->hParamMC->Cldfb_ImagBuffer_tc; +#else hParamMC = st_ivas->hParamMC; assert( hParamMC ); - push_wmops( "param_mc_dec_digest_tc" ); - #ifndef OBJ_EDITING_API set_s( channel_active, 0, MAX_CICP_CHANNELS ); #endif nchan_transport = st_ivas->nchan_transport; +#endif #ifndef OBJ_EDITING_API nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; @@ -1427,1709 +1439,1722 @@ void ivas_param_mc_dec_digest_tc( set_zero( cx_imag_next_band, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); #endif - /* slot loop for gathering the input data */ - for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + /* CLDFB Analysis */ + for ( ch = 0, cldfb_ch = 0; cldfb_ch < n_ch_cldfb; cldfb_ch++, ch++ ) { - if ( st_ivas->hDecoderConfig->Opt_tsm ) + for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) { -#ifndef OBJ_EDITING_API - if ( param_band_idx == 0 ) /* only run cldfbAna once */ - { -#endif - float RealBuffer[CLDFB_NO_CHANNELS_MAX]; - float ImagBuffer[CLDFB_NO_CHANNELS_MAX]; - - /* CLDFB Analysis*/ - for ( ch = 0; ch < nchan_transport; ch++ ) - { - cldfbAnalysis_ts( &( p_data_f[ch][hParamMC->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hParamMC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); - - mvr2r( RealBuffer, &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport + ch * hParamMC->num_freq_bands], hParamMC->num_freq_bands ); - mvr2r( ImagBuffer, &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport + ch * hParamMC->num_freq_bands], hParamMC->num_freq_bands ); - } -#ifndef OBJ_EDITING_API - } -#endif + cldfbAnalysis_ts( &( p_data_f[ch][num_freq_bands * slot_idx] ), + &cldfb_real_buffer[slot_idx * num_freq_bands * n_ch_cldfb + cldfb_ch * num_freq_bands], + &cldfb_imag_buffer[slot_idx * num_freq_bands * n_ch_cldfb + cldfb_ch * num_freq_bands], + num_freq_bands, st_ivas->cldfbAnaDec[cldfb_ch] ); } - + } +#else + /* slot loop for gathering the input data */ + for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) + { + if ( st_ivas->hDecoderConfig->Opt_tsm ) + { #ifndef OBJ_EDITING_API - if ( slot_idx >= 2 * hParamMC->hMetadataPMC->attackIndex ) + if ( param_band_idx == 0 ) /* only run cldfbAna once */ { - for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) +#endif + float RealBuffer[CLDFB_NO_CHANNELS_MAX]; + float ImagBuffer[CLDFB_NO_CHANNELS_MAX]; + + /* CLDFB Analysis*/ + for ( ch = 0; ch < nchan_transport; ch++ ) { - if ( is_next_band && skip_next_band ) - { - continue; - } + cldfbAnalysis_ts( &( p_data_f[ch][hParamMC->num_freq_bands * slot_idx] ), RealBuffer, ImagBuffer, hParamMC->num_freq_bands, st_ivas->cldfbAnaDec[ch] ); - ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], - &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], - is_next_band ? cx_next_band : cx, - is_next_band ? cx_imag_next_band : cx_imag, - param_band_idx + is_next_band, - hParamMC, - nchan_transport ); + mvr2r( RealBuffer, &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport + ch * hParamMC->num_freq_bands], hParamMC->num_freq_bands ); + mvr2r( ImagBuffer, &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport + ch * hParamMC->num_freq_bands], hParamMC->num_freq_bands ); } +#ifndef OBJ_EDITING_API } #endif } #ifndef OBJ_EDITING_API - /* map from complex input covariance to real values */ - for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + if ( slot_idx >= 2 * hParamMC->hMetadataPMC->attackIndex ) { - if ( is_next_band && skip_next_band ) + for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) { - continue; - } - - /* Cx for transport channels */ - pCx = is_next_band ? &cx_next_band[0] : &cx[0]; - pCx_imag = is_next_band ? &cx_imag_next_band[0] : &cx_imag[0]; - for ( i = 0; i < nchan_transport * nchan_transport; i++ ) - { - real_part = pCx[i]; - imag_part = pCx_imag[i]; - - /* (a-ib)(c+id) = ac + bd + i(ad-bc) */ - if ( param_band_idx < hParamMC->max_param_band_abs_cov ) + if ( is_next_band && skip_next_band ) { - pCx[i] = sqrtf( real_part * real_part + imag_part * imag_part ); - } - else - { - pCx[i] = real_part; + continue; } + + ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], + &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], + is_next_band ? cx_next_band : cx, + is_next_band ? cx_imag_next_band : cx_imag, + param_band_idx + is_next_band, + hParamMC, + nchan_transport ); } } +#endif + } - /* we have to do it similar to the encoder in case of attacks (i.e. accumulate two bands) to ensure correct DMX of the target covariance*/ - if ( hParamMC->hMetadataPMC->bAttackPresent && ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) ) +#ifndef OBJ_EDITING_API + /* map from complex input covariance to real values */ + for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + { + if ( is_next_band && skip_next_band ) { - v_add( cx, cx_next_band, cx, nchan_transport * nchan_transport ); - mvr2r( cx, cx_next_band, nchan_transport * nchan_transport ); + continue; } - - for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + /* Cx for transport channels */ + pCx = is_next_band ? &cx_next_band[0] : &cx[0]; + pCx_imag = is_next_band ? &cx_imag_next_band[0] : &cx_imag[0]; + for ( i = 0; i < nchan_transport * nchan_transport; i++ ) { - if ( is_next_band && skip_next_band ) + real_part = pCx[i]; + imag_part = pCx_imag[i]; + + /* (a-ib)(c+id) = ac + bd + i(ad-bc) */ + if ( param_band_idx < hParamMC->max_param_band_abs_cov ) + { + pCx[i] = sqrtf( real_part * real_part + imag_part * imag_part ); + } + else { - continue; + pCx[i] = real_part; } + } + } + + /* we have to do it similar to the encoder in case of attacks (i.e. accumulate two bands) to ensure correct DMX of the target covariance*/ + if ( hParamMC->hMetadataPMC->bAttackPresent && ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) ) + { + v_add( cx, cx_next_band, cx, nchan_transport * nchan_transport ); + mvr2r( cx, cx_next_band, nchan_transport * nchan_transport ); + } - /* generate mixing matrices */ - ivas_param_mc_get_mixing_matrices( hParamMC, - hSynthesisOutputSetup, - is_next_band ? cx_next_band : cx, - param_band_idx + is_next_band, - hParamMC->h_output_synthesis_cov_state.mixing_matrix, - hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, - nchan_out_transport, - hParamMC->synthesis_conf, - nchan_transport, - nchan_out_cov ); + + for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + { + if ( is_next_band && skip_next_band ) + { + continue; } + + /* generate mixing matrices */ + ivas_param_mc_get_mixing_matrices( hParamMC, + hSynthesisOutputSetup, + is_next_band ? cx_next_band : cx, + param_band_idx + is_next_band, + hParamMC->h_output_synthesis_cov_state.mixing_matrix, + hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, + nchan_out_transport, + hParamMC->synthesis_conf, + nchan_transport, + nchan_out_cov ); } +} +#endif #endif - pop_wmops(); - return; -} + return; + } #ifdef OBJ_EDITING_API -/*------------------------------------------------------------------------- - * ivas_param_mc_dec_prepare_renderer() - * - * - *------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------- + * ivas_param_mc_dec_prepare_renderer() + * + * + *------------------------------------------------------------------------*/ + + void ivas_param_mc_dec_prepare_renderer( + Decoder_Struct * st_ivas, /* i/o: IVAS decoder handle */ + const uint8_t nCldfbSlots /* i : number of CLDFB slots in transport channels */ + ) + { + PARAM_MC_DEC_HANDLE hParamMC; + int16_t i; + int16_t is_next_band, skip_next_band; + int16_t slot_idx, param_band_idx; + int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; + int16_t nchan_out_cov; + /*CLDFB*/ + float *pCx, *pCx_imag; + float cx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float cx_imag[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float cx_next_band[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float cx_imag_next_band[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float real_part, imag_part; + /* format converter */ + int16_t channel_active[MAX_OUTPUT_CHANNELS]; + IVAS_OUTPUT_SETUP *hSynthesisOutputSetup; + + hParamMC = st_ivas->hParamMC; + assert( hParamMC ); + + push_wmops( "param_mc_dec_digest_tc" ); + + set_s( channel_active, 0, MAX_CICP_CHANNELS ); + nchan_transport = st_ivas->nchan_transport; + nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; -void ivas_param_mc_dec_prepare_renderer( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint8_t nCldfbSlots /* i : number of CLDFB slots in transport channels */ -) -{ - PARAM_MC_DEC_HANDLE hParamMC; - int16_t i; - int16_t is_next_band, skip_next_band; - int16_t slot_idx, param_band_idx; - int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; - int16_t nchan_out_cov; - /*CLDFB*/ - float *pCx, *pCx_imag; - float cx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; - float cx_imag[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; - float cx_next_band[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; - float cx_imag_next_band[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; - float real_part, imag_part; - /* format converter */ - int16_t channel_active[MAX_OUTPUT_CHANNELS]; - IVAS_OUTPUT_SETUP *hSynthesisOutputSetup; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + nchan_out_cldfb = BINAURAL_CHANNELS; + set_s( channel_active, 1, nchan_out_cldfb ); + nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + hSynthesisOutputSetup = &st_ivas->hTransSetup; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + hSynthesisOutputSetup = &st_ivas->hTransSetup; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) + { + nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + nchan_out_cldfb = nchan_out_cov; + set_s( channel_active, 1, nchan_out_cov ); + hSynthesisOutputSetup = &st_ivas->hOutSetup; + } + else + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = nchan_out_transport; + set_s( channel_active, 1, nchan_out_cov ); + hSynthesisOutputSetup = &st_ivas->hTransSetup; + } - hParamMC = st_ivas->hParamMC; - assert( hParamMC ); + /* adapt transient position */ + if ( hParamMC->hMetadataPMC->bAttackPresent ) + { + hParamMC->hMetadataPMC->attackIndex = (int16_t) max( 0, hParamMC->hMetadataPMC->attackIndex + ( ( nCldfbSlots - DEFAULT_JBM_CLDFB_TIMESLOTS ) / 2 ) ); + } - push_wmops( "param_mc_dec_digest_tc" ); + /* adapt subframes */ + hParamMC->num_slots = nCldfbSlots; + hParamMC->slots_rendered = 0; + hParamMC->subframes_rendered = 0; + ivas_jbm_dec_get_adapted_subframes( nCldfbSlots, hParamMC->subframe_nbslots, &hParamMC->nb_subframes ); + st_ivas->hTcBuffer->nb_subframes = hParamMC->nb_subframes; + mvs2s( hParamMC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, hParamMC->nb_subframes ); - set_s( channel_active, 0, MAX_CICP_CHANNELS ); - nchan_transport = st_ivas->nchan_transport; - nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + ivas_param_mc_dec_compute_interpolator( hParamMC->hMetadataPMC->bAttackPresent, hParamMC->hMetadataPMC->attackIndex, nCldfbSlots, hParamMC->h_output_synthesis_params.interpolator ); - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { - nchan_out_cldfb = BINAURAL_CHANNELS; - set_s( channel_active, 1, nchan_out_cldfb ); - nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; - hSynthesisOutputSetup = &st_ivas->hTransSetup; - } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) - { - nchan_out_cov = nchan_out_transport; - nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - hSynthesisOutputSetup = &st_ivas->hTransSetup; - } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) - { - nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - nchan_out_cldfb = nchan_out_cov; - set_s( channel_active, 1, nchan_out_cov ); - hSynthesisOutputSetup = &st_ivas->hOutSetup; - } - else - { - nchan_out_cov = nchan_out_transport; - nchan_out_cldfb = nchan_out_transport; - set_s( channel_active, 1, nchan_out_cov ); - hSynthesisOutputSetup = &st_ivas->hTransSetup; - } + /* loop over two bands at a time */ + for ( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx += 2 ) + { + /* don't process next band if it exceeds the limit */ + skip_next_band = ( ( param_band_idx + 1 ) == hParamMC->num_param_bands_synth ) ? 1 : 0; - /* adapt transient position */ - if ( hParamMC->hMetadataPMC->bAttackPresent ) - { - hParamMC->hMetadataPMC->attackIndex = (int16_t) max( 0, hParamMC->hMetadataPMC->attackIndex + ( ( nCldfbSlots - DEFAULT_JBM_CLDFB_TIMESLOTS ) / 2 ) ); - } + set_zero( cx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); + set_zero( cx_imag, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); + set_zero( cx_next_band, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); + set_zero( cx_imag_next_band, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); - /* adapt subframes */ - hParamMC->num_slots = nCldfbSlots; - hParamMC->slots_rendered = 0; - hParamMC->subframes_rendered = 0; - ivas_jbm_dec_get_adapted_subframes( nCldfbSlots, hParamMC->subframe_nbslots, &hParamMC->nb_subframes ); - st_ivas->hTcBuffer->nb_subframes = hParamMC->nb_subframes; - mvs2s( hParamMC->subframe_nbslots, st_ivas->hTcBuffer->subframe_nbslots, hParamMC->nb_subframes ); + /* slot loop for gathering the input data */ + for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) + { + if ( slot_idx >= 2 * hParamMC->hMetadataPMC->attackIndex ) + { + for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + { + if ( is_next_band && skip_next_band ) + { + continue; + } - ivas_param_mc_dec_compute_interpolator( hParamMC->hMetadataPMC->bAttackPresent, hParamMC->hMetadataPMC->attackIndex, nCldfbSlots, hParamMC->h_output_synthesis_params.interpolator ); + ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], + &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], + is_next_band ? cx_next_band : cx, + is_next_band ? cx_imag_next_band : cx_imag, + param_band_idx + is_next_band, + hParamMC, + nchan_transport ); + } + } + } - /* loop over two bands at a time */ - for ( param_band_idx = 0; param_band_idx < hParamMC->num_param_bands_synth; param_band_idx += 2 ) - { - /* don't process next band if it exceeds the limit */ - skip_next_band = ( ( param_band_idx + 1 ) == hParamMC->num_param_bands_synth ) ? 1 : 0; + /* map from complex input covariance to real values */ + for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + { + if ( is_next_band && skip_next_band ) + { + continue; + } - set_zero( cx, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); - set_zero( cx_imag, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); - set_zero( cx_next_band, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); - set_zero( cx_imag_next_band, PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS ); + /* Cx for transport channels */ + pCx = is_next_band ? &cx_next_band[0] : &cx[0]; + pCx_imag = is_next_band ? &cx_imag_next_band[0] : &cx_imag[0]; - /* slot loop for gathering the input data */ - for ( slot_idx = 0; slot_idx < nCldfbSlots; slot_idx++ ) - { - if ( slot_idx >= 2 * hParamMC->hMetadataPMC->attackIndex ) - { - for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + for ( i = 0; i < nchan_transport * nchan_transport; i++ ) { - if ( is_next_band && skip_next_band ) + real_part = pCx[i]; + imag_part = pCx_imag[i]; + + /* (a-ib)(c+id) = ac + bd + i(ad-bc) */ + if ( param_band_idx < hParamMC->max_param_band_abs_cov ) { - continue; + pCx[i] = sqrtf( real_part * real_part + imag_part * imag_part ); + } + else + { + pCx[i] = real_part; } - - ivas_dirac_dec_output_synthesis_cov_param_mc_collect_slot( &hParamMC->Cldfb_RealBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], - &hParamMC->Cldfb_ImagBuffer_tc[slot_idx * hParamMC->num_freq_bands * nchan_transport], - is_next_band ? cx_next_band : cx, - is_next_band ? cx_imag_next_band : cx_imag, - param_band_idx + is_next_band, - hParamMC, - nchan_transport ); } } - } - /* map from complex input covariance to real values */ - for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) - { - if ( is_next_band && skip_next_band ) + /* we have to do it similar to the encoder in case of attacks (i.e. accumulate two bands) to ensure correct DMX of the target covariance*/ + if ( hParamMC->hMetadataPMC->bAttackPresent && ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) ) { - continue; + v_add( cx, cx_next_band, cx, nchan_transport * nchan_transport ); + mvr2r( cx, cx_next_band, nchan_transport * nchan_transport ); } - /* Cx for transport channels */ - pCx = is_next_band ? &cx_next_band[0] : &cx[0]; - pCx_imag = is_next_band ? &cx_imag_next_band[0] : &cx_imag[0]; - - for ( i = 0; i < nchan_transport * nchan_transport; i++ ) + for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) { - real_part = pCx[i]; - imag_part = pCx_imag[i]; - - /* (a-ib)(c+id) = ac + bd + i(ad-bc) */ - if ( param_band_idx < hParamMC->max_param_band_abs_cov ) - { - pCx[i] = sqrtf( real_part * real_part + imag_part * imag_part ); - } - else + if ( is_next_band && skip_next_band ) { - pCx[i] = real_part; + continue; } + + /* generate mixing matrices */ + ivas_param_mc_get_mixing_matrices( hParamMC, + hSynthesisOutputSetup, + is_next_band ? cx_next_band : cx, + param_band_idx + is_next_band, + hParamMC->h_output_synthesis_cov_state.mixing_matrix, + hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, + nchan_out_transport, + hParamMC->synthesis_conf, + nchan_transport, + nchan_out_cov ); } } - /* we have to do it similar to the encoder in case of attacks (i.e. accumulate two bands) to ensure correct DMX of the target covariance*/ - if ( hParamMC->hMetadataPMC->bAttackPresent && ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) ) + pop_wmops(); + + return; + } +#endif + + + /*------------------------------------------------------------------------- + * ivas_param_mc_dec_render() + * + * Parametric MC rendering process + *------------------------------------------------------------------------*/ + + void ivas_param_mc_dec_render( + Decoder_Struct * st_ivas, /* i/o: IVAS decoder handle */ + const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ + uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ + uint16_t *nSamplesAvailableNext, /* o : number of CLDFB slots still to render */ + float *output_f[] /* o : rendered time signal */ + ) + { + PARAM_MC_DEC_HANDLE hParamMC; + int16_t i, ch; + int16_t subframe_idx; + int16_t slot_idx, slot_idx_start, slot_idx_start_cldfb_synth, first_sf, last_sf, slots_to_render; + int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; + int16_t nchan_out_cov; + /*CLDFB*/ + float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; + /*Decorrelator*/ + float onset_filter[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; + /* format converter */ + int16_t channel_active[MAX_OUTPUT_CHANNELS]; + uint16_t nband_synth, nbands_to_zero; + uint16_t nchan_out_init; + uint32_t output_Fs; + + hParamMC = st_ivas->hParamMC; + assert( hParamMC ); + + push_wmops( "param_mc_dec_render" ); + + set_s( channel_active, 0, MAX_CICP_CHANNELS ); + nchan_transport = st_ivas->nchan_transport; + nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + nchan_out_init = nchan_out_transport; + output_Fs = st_ivas->hDecoderConfig->output_Fs; + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + nchan_out_cldfb = BINAURAL_CHANNELS; + set_s( channel_active, 1, nchan_out_cldfb ); + if ( st_ivas->hCombinedOrientationData ) + { + nchan_out_init = MAX_INTERN_CHANNELS; + } + nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) { - v_add( cx, cx_next_band, cx, nchan_transport * nchan_transport ); - mvr2r( cx, cx_next_band, nchan_transport * nchan_transport ); + nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + nchan_out_cldfb = nchan_out_cov; + set_s( channel_active, 1, nchan_out_cov ); + } + else + { + nchan_out_cov = nchan_out_transport; + nchan_out_cldfb = nchan_out_transport; + set_s( channel_active, 1, nchan_out_cov ); } - for ( is_next_band = 0; is_next_band < 2; is_next_band++ ) + /* set everything to zero that will not be decoded */ + nband_synth = hParamMC->band_grouping[hParamMC->num_param_bands_synth]; + nbands_to_zero = hParamMC->num_freq_bands - nband_synth; + for ( ch = 0; ch < nchan_out_init; ch++ ) { - if ( is_next_band && skip_next_band ) + for ( slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++ ) { - continue; + set_zero( &( Cldfb_RealBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); + set_zero( &( Cldfb_ImagBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); } + } - /* generate mixing matrices */ - ivas_param_mc_get_mixing_matrices( hParamMC, - hSynthesisOutputSetup, - is_next_band ? cx_next_band : cx, - param_band_idx + is_next_band, - hParamMC->h_output_synthesis_cov_state.mixing_matrix, - hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, - nchan_out_transport, - hParamMC->synthesis_conf, - nchan_transport, - nchan_out_cov ); + /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ + slots_to_render = min( hParamMC->num_slots - hParamMC->slots_rendered, nSamplesAsked / NS2SA( output_Fs, CLDFB_SLOT_NS ) ); + *nSamplesRendered = slots_to_render * NS2SA( output_Fs, CLDFB_SLOT_NS ); + first_sf = hParamMC->subframes_rendered; + last_sf = first_sf; + while ( slots_to_render > 0 ) + { + slots_to_render -= hParamMC->subframe_nbslots[last_sf]; + last_sf++; } - } +#ifdef DEBUGGING + assert( slots_to_render == 0 ); +#endif + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + slots_to_render += hParamMC->subframe_nbslots[subframe_idx]; + } + } + slot_idx_start = hParamMC->slots_rendered; + slot_idx_start_cldfb_synth = 0; + for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) + { + for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++ ) + { - pop_wmops(); + if ( hParamMC->max_band_decorr > 0 ) + { + /*-----------------------------------------------------------------* + * protoype signal computation + *-----------------------------------------------------------------*/ + + param_mc_protoSignalComputation( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + hParamMC->proto_frame_f, hParamMC->diff_proto_info, + hParamMC->num_freq_bands ); + + /*-----------------------------------------------------------------* + * frequency domain decorrelation + *-----------------------------------------------------------------*/ + + /* decorrelate prototype frame */ + ivas_dirac_dec_decorr_process( hParamMC->num_freq_bands, + hParamMC->num_outputs_diff, + hParamMC->diff_proto_info->num_protos_diff, + DIRAC_SYNTHESIS_COV_MC_LS, + nchan_transport, + hParamMC->proto_frame_f, + hParamMC->diff_proto_info->num_protos_diff, + hParamMC->diff_proto_info->proto_index_diff, + hParamMC->proto_frame_dec_f, + onset_filter, + hParamMC->h_freq_domain_decorr_ap_params, + hParamMC->h_freq_domain_decorr_ap_state ); + + /* copy decorrelated frame directly to output CLDFB buffer, acts also as intermediate */ + /* memory for the decorrelated signal */ + ivas_param_mc_dec_copy_diffuse_proto( hParamMC, Cldfb_RealBuffer, Cldfb_ImagBuffer, nchan_out_cov, slot_idx ); + } - return; -} -#endif + /*-----------------------------------------------------------------* + * output synthesis + *-----------------------------------------------------------------*/ + ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], + Cldfb_RealBuffer, Cldfb_ImagBuffer, + hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, slot_idx, slot_idx + slot_idx_start, + nchan_transport, nchan_out_cov, hParamMC ); -/*------------------------------------------------------------------------- - * ivas_param_mc_dec_render() - * - * Parametric MC rendering process - *------------------------------------------------------------------------*/ + if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) + { + if ( + st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) + { + ivas_param_mc_mc2sba_cldfb( st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE ); + } + else + { + /* remove LFE */ + uint16_t idx_out; + uint16_t idx_lfe; + IVAS_OUTPUT_SETUP hLsSetup; -void ivas_param_mc_dec_render( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint16_t nSamplesAsked, /* i : number of CLDFB slots requested */ - uint16_t *nSamplesRendered, /* o : number of CLDFB slots rendered */ - uint16_t *nSamplesAvailableNext, /* o : number of CLDFB slots still to render */ - float *output_f[] /* o : rendered time signal */ -) -{ - PARAM_MC_DEC_HANDLE hParamMC; - int16_t i, ch; - int16_t subframe_idx; - int16_t slot_idx, slot_idx_start, slot_idx_start_cldfb_synth, first_sf, last_sf, slots_to_render; - int16_t nchan_transport, nchan_out_transport, nchan_out_cldfb; - int16_t nchan_out_cov; - /*CLDFB*/ - float Cldfb_RealBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer[MAX_INTERN_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_RealBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - float Cldfb_ImagBuffer_Binaural[MAX_HEAD_ROT_POSES][BINAURAL_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX]; - /*Decorrelator*/ - float onset_filter[MAX_CICP_CHANNELS * CLDFB_NO_CHANNELS_MAX]; - /* format converter */ - int16_t channel_active[MAX_OUTPUT_CHANNELS]; - uint16_t nband_synth, nbands_to_zero; - uint16_t nchan_out_init; - uint32_t output_Fs; + hLsSetup = st_ivas->hTransSetup; - hParamMC = st_ivas->hParamMC; - assert( hParamMC ); + /* If LFE should be rendered, add it to other channels before removing */ + if ( st_ivas->hBinRenderer->render_lfe ) + { + for ( idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++ ) + { + /* Copy just the first band of LFE*/ + v_multc( Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); + v_multc( Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); - push_wmops( "param_mc_dec_render" ); + for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + { + if ( hLsSetup.index_lfe[idx_lfe] != ch ) + { + v_add( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer[ch][slot_idx], 1 ); + v_add( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], 1 ); + } + } + } + } - set_s( channel_active, 0, MAX_CICP_CHANNELS ); - nchan_transport = st_ivas->nchan_transport; - nchan_out_transport = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; - nchan_out_init = nchan_out_transport; - output_Fs = st_ivas->hDecoderConfig->output_Fs; + idx_out = 0; + idx_lfe = 0; - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { - nchan_out_cldfb = BINAURAL_CHANNELS; - set_s( channel_active, 1, nchan_out_cldfb ); - if ( st_ivas->hCombinedOrientationData ) - { - nchan_out_init = MAX_INTERN_CHANNELS; - } - nchan_out_cov = st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe; - } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) - { - nchan_out_cov = nchan_out_transport; - nchan_out_cldfb = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_COV || hParamMC->synthesis_conf == PARAM_MC_SYNTH_MONO_STEREO ) - { - nchan_out_cov = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - nchan_out_cldfb = nchan_out_cov; - set_s( channel_active, 1, nchan_out_cov ); - } - else - { - nchan_out_cov = nchan_out_transport; - nchan_out_cldfb = nchan_out_transport; - set_s( channel_active, 1, nchan_out_cov ); - } - - /* set everything to zero that will not be decoded */ - nband_synth = hParamMC->band_grouping[hParamMC->num_param_bands_synth]; - nbands_to_zero = hParamMC->num_freq_bands - nband_synth; - for ( ch = 0; ch < nchan_out_init; ch++ ) - { - for ( slot_idx = 0; slot_idx < JBM_CLDFB_SLOTS_IN_SUBFRAME; slot_idx++ ) - { - set_zero( &( Cldfb_RealBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); - set_zero( &( Cldfb_ImagBuffer[ch][slot_idx][nband_synth] ), nbands_to_zero ); - } - } - - /* loop for synthesis, assume we always have to render in multiples of 5ms subframes with spills */ - slots_to_render = min( hParamMC->num_slots - hParamMC->slots_rendered, nSamplesAsked / NS2SA( output_Fs, CLDFB_SLOT_NS ) ); - *nSamplesRendered = slots_to_render * NS2SA( output_Fs, CLDFB_SLOT_NS ); - first_sf = hParamMC->subframes_rendered; - last_sf = first_sf; - while ( slots_to_render > 0 ) - { - slots_to_render -= hParamMC->subframe_nbslots[last_sf]; - last_sf++; - } -#ifdef DEBUGGING - assert( slots_to_render == 0 ); -#endif - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) - { - slots_to_render += hParamMC->subframe_nbslots[subframe_idx]; - } - } - slot_idx_start = hParamMC->slots_rendered; - slot_idx_start_cldfb_synth = 0; - for ( subframe_idx = first_sf; subframe_idx < last_sf; subframe_idx++ ) - { - for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++, hParamMC->slots_rendered++ ) - { - - if ( hParamMC->max_band_decorr > 0 ) - { - /*-----------------------------------------------------------------* - * protoype signal computation - *-----------------------------------------------------------------*/ - - param_mc_protoSignalComputation( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - hParamMC->proto_frame_f, hParamMC->diff_proto_info, - hParamMC->num_freq_bands ); - - /*-----------------------------------------------------------------* - * frequency domain decorrelation - *-----------------------------------------------------------------*/ - - /* decorrelate prototype frame */ - ivas_dirac_dec_decorr_process( hParamMC->num_freq_bands, - hParamMC->num_outputs_diff, - hParamMC->diff_proto_info->num_protos_diff, - DIRAC_SYNTHESIS_COV_MC_LS, - nchan_transport, - hParamMC->proto_frame_f, - hParamMC->diff_proto_info->num_protos_diff, - hParamMC->diff_proto_info->proto_index_diff, - hParamMC->proto_frame_dec_f, - onset_filter, - hParamMC->h_freq_domain_decorr_ap_params, - hParamMC->h_freq_domain_decorr_ap_state ); - - /* copy decorrelated frame directly to output CLDFB buffer, acts also as intermediate */ - /* memory for the decorrelated signal */ - ivas_param_mc_dec_copy_diffuse_proto( hParamMC, Cldfb_RealBuffer, Cldfb_ImagBuffer, nchan_out_cov, slot_idx ); - } - - /*-----------------------------------------------------------------* - * output synthesis - *-----------------------------------------------------------------*/ - - ivas_dirac_dec_output_synthesis_cov_param_mc_synthesise_slot( &hParamMC->Cldfb_RealBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - &hParamMC->Cldfb_ImagBuffer_tc[hParamMC->slots_rendered * nchan_transport * hParamMC->num_freq_bands], - Cldfb_RealBuffer, Cldfb_ImagBuffer, - hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, slot_idx, slot_idx + slot_idx_start, - nchan_transport, nchan_out_cov, hParamMC ); - - if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) ) - { - if ( - st_ivas->hCombinedOrientationData && st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) - { - ivas_param_mc_mc2sba_cldfb( st_ivas->hTransSetup, hParamMC->hoa_encoder, slot_idx, Cldfb_RealBuffer, Cldfb_ImagBuffer, nband_synth, GAIN_LFE ); - } - else - { - /* remove LFE */ - uint16_t idx_out; - uint16_t idx_lfe; - IVAS_OUTPUT_SETUP hLsSetup; - - hLsSetup = st_ivas->hTransSetup; - - /* If LFE should be rendered, add it to other channels before removing */ - if ( st_ivas->hBinRenderer->render_lfe ) - { - for ( idx_lfe = 0; idx_lfe < hLsSetup.num_lfe; idx_lfe++ ) + for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) { - /* Copy just the first band of LFE*/ - v_multc( Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); - v_multc( Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], ( GAIN_LFE / hLsSetup.nchan_out_woLFE ), Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], 1 ); - - for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) + if ( ( hLsSetup.num_lfe > 0 ) && ( hLsSetup.index_lfe[idx_lfe] == ch ) ) { - if ( hLsSetup.index_lfe[idx_lfe] != ch ) + if ( idx_lfe < ( hLsSetup.num_lfe - 1 ) ) { - v_add( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_RealBuffer[ch][slot_idx], 1 ); - v_add( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[hLsSetup.index_lfe[idx_lfe]][slot_idx], Cldfb_ImagBuffer[ch][slot_idx], 1 ); + idx_lfe++; } } - } - } - - idx_out = 0; - idx_lfe = 0; - - for ( ch = 0; ch < ( hLsSetup.nchan_out_woLFE + hLsSetup.num_lfe ); ch++ ) - { - if ( ( hLsSetup.num_lfe > 0 ) && ( hLsSetup.index_lfe[idx_lfe] == ch ) ) - { - if ( idx_lfe < ( hLsSetup.num_lfe - 1 ) ) + else if ( ch != idx_out ) { - idx_lfe++; + mvr2r( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[idx_out][slot_idx], nband_synth ); + mvr2r( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[idx_out][slot_idx], nband_synth ); + idx_out++; + } + else + { + idx_out++; } - } - else if ( ch != idx_out ) - { - mvr2r( Cldfb_RealBuffer[ch][slot_idx], Cldfb_RealBuffer[idx_out][slot_idx], nband_synth ); - mvr2r( Cldfb_ImagBuffer[ch][slot_idx], Cldfb_ImagBuffer[idx_out][slot_idx], nband_synth ); - idx_out++; - } - else - { - idx_out++; } } } } - } - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { - if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { - if ( st_ivas->hSplitBinRend->hCldfbDataOut != NULL ) + if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - for ( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) + if ( st_ivas->hSplitBinRend->hCldfbDataOut != NULL ) { - for ( ch = 0; ch < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); ch++ ) + for ( slot_idx = 0; slot_idx < MAX_PARAM_SPATIAL_SUBFRAMES; slot_idx++ ) { - mvr2r( Cldfb_RealBuffer[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer[ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); - mvr2r( Cldfb_ImagBuffer[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer[ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); + for ( ch = 0; ch < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ); ch++ ) + { + mvr2r( Cldfb_RealBuffer[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_RealBuffer[ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); + mvr2r( Cldfb_ImagBuffer[ch][slot_idx], st_ivas->hSplitBinRend->hCldfbDataOut->Cldfb_ImagBuffer[ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); + } } + st_ivas->hSplitBinRend->hCldfbDataOut->config = st_ivas->hIntSetup.output_config; } - st_ivas->hSplitBinRend->hCldfbDataOut->config = st_ivas->hIntSetup.output_config; } - } - ivas_binRenderer( st_ivas->hBinRenderer, - ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, + ivas_binRenderer( st_ivas->hBinRenderer, + ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, #ifdef SPLIT_REND_WITH_HEAD_ROT_DEBUG - NULL, + NULL, #endif - st_ivas->hCombinedOrientationData, - hParamMC->subframe_nbslots[subframe_idx], - Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); + st_ivas->hCombinedOrientationData, + hParamMC->subframe_nbslots[subframe_idx], + Cldfb_RealBuffer_Binaural, Cldfb_ImagBuffer_Binaural, Cldfb_RealBuffer, Cldfb_ImagBuffer ); - if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - int16_t pos_idx; - for ( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) + if ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++ ) + int16_t pos_idx; + for ( pos_idx = 0; pos_idx < st_ivas->hBinRenderer->numPoses; pos_idx++ ) { - for ( ch = 0; ch < nchan_out_cldfb; ch++ ) + for ( slot_idx = 0; slot_idx < hParamMC->subframe_nbslots[subframe_idx]; slot_idx++ ) { - mvr2r( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); - mvr2r( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); + for ( ch = 0; ch < nchan_out_cldfb; ch++ ) + { + mvr2r( Cldfb_RealBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_RealBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); + mvr2r( Cldfb_ImagBuffer_Binaural[pos_idx][ch][slot_idx], st_ivas->hSplitBinRend->hMultiBinCldfbData->Cldfb_ImagBuffer_Binaural[( pos_idx * BINAURAL_CHANNELS ) + ch][slot_idx_start + slot_idx], hParamMC->num_freq_bands ); + } } } } - } - - /* update combined orientation access index */ - ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); - } - else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) - { - /* format conversion*/ - ivas_lssetupconversion_process_param_mc( st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer, Cldfb_ImagBuffer, channel_active ); - } - /* CLDFB synthesis */ - for ( ch = 0; ch < nchan_out_cldfb; ch++ ) - { - float *RealBuffer[16]; - float *ImagBuffer[16]; + /* update combined orientation access index */ + ivas_combined_orientation_update_index( st_ivas->hCombinedOrientationData, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + } + else if ( hParamMC->synthesis_conf == PARAM_MC_SYNTH_LS_CONV_CLDFB ) + { + /* format conversion*/ + ivas_lssetupconversion_process_param_mc( st_ivas, hParamMC->subframe_nbslots[subframe_idx], Cldfb_RealBuffer, Cldfb_ImagBuffer, channel_active ); + } - if ( channel_active[ch] ) + /* CLDFB synthesis */ + for ( ch = 0; ch < nchan_out_cldfb; ch++ ) { - /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ - for ( i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++ ) + float *RealBuffer[16]; + float *ImagBuffer[16]; + + if ( channel_active[ch] ) { - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + /* open CLDFB buffer up to CLDFB_NO_CHANNELS_MAX bands for 48kHz */ + for ( i = 0; i < hParamMC->subframe_nbslots[subframe_idx]; i++ ) { - RealBuffer[i] = Cldfb_RealBuffer_Binaural[0][ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[0][ch][i]; - } - else - { - RealBuffer[i] = Cldfb_RealBuffer[ch][i]; - ImagBuffer[i] = Cldfb_ImagBuffer[ch][i]; + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) + { + RealBuffer[i] = Cldfb_RealBuffer_Binaural[0][ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer_Binaural[0][ch][i]; + } + else + { + RealBuffer[i] = Cldfb_RealBuffer[ch][i]; + ImagBuffer[i] = Cldfb_ImagBuffer[ch][i]; + } } - } - cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), - hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); - } - else - { - set_f( &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), 0.0f, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + cldfbSynthesis( RealBuffer, ImagBuffer, &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), + hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx], st_ivas->cldfbSynDec[ch] ); + } + else + { + set_f( &( output_f[ch][slot_idx_start_cldfb_synth * hParamMC->num_freq_bands] ), 0.0f, hParamMC->num_freq_bands * hParamMC->subframe_nbslots[subframe_idx] ); + } } + slot_idx_start += hParamMC->subframe_nbslots[subframe_idx]; + slot_idx_start_cldfb_synth += hParamMC->subframe_nbslots[subframe_idx]; } - slot_idx_start += hParamMC->subframe_nbslots[subframe_idx]; - slot_idx_start_cldfb_synth += hParamMC->subframe_nbslots[subframe_idx]; - } - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - ivas_mc2sba( st_ivas->hIntSetup, output_f, output_f, hParamMC->num_freq_bands * slots_to_render, st_ivas->hOutSetup.ambisonics_order, 0.f ); - } + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_mc2sba( st_ivas->hIntSetup, output_f, output_f, hParamMC->num_freq_bands * slots_to_render, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } - /* update */ - if ( hParamMC->slots_rendered == hParamMC->num_slots ) - { - hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; - param_mc_update_mixing_matrices( hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_transport, nchan_out_cov ); - } - hParamMC->subframes_rendered = last_sf; - *nSamplesAvailableNext = ( hParamMC->num_slots - hParamMC->slots_rendered ) * NS2SA( output_Fs, CLDFB_SLOT_NS ); - pop_wmops(); + /* update */ + if ( hParamMC->slots_rendered == hParamMC->num_slots ) + { + hParamMC->hMetadataPMC->last_coded_bwidth = hParamMC->hMetadataPMC->coded_bwidth; + param_mc_update_mixing_matrices( hParamMC, hParamMC->h_output_synthesis_cov_state.mixing_matrix, hParamMC->h_output_synthesis_cov_state.mixing_matrix_res, nchan_transport, nchan_out_cov ); + } + hParamMC->subframes_rendered = last_sf; + *nSamplesAvailableNext = ( hParamMC->num_slots - hParamMC->slots_rendered ) * NS2SA( output_Fs, CLDFB_SLOT_NS ); + pop_wmops(); - return; -} + return; + } -/*------------------------------------------------------------------------- - * param_mc_dec_init() - * - * Parametric MC decoding initialization - *------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------- + * param_mc_dec_init() + * + * Parametric MC decoding initialization + *------------------------------------------------------------------------*/ -static void ivas_param_mc_dec_init( - PARAM_MC_DEC_HANDLE hParamMC, /* i/o: decoder DirAC handle */ - const int16_t nchan_transport, /* i : number of input (transport) channels */ - const int16_t nchan_cov ) /* i : number of cov synthesis channels */ -{ - int16_t k; - uint16_t max_param_band_residual; - int16_t len; + static void ivas_param_mc_dec_init( + PARAM_MC_DEC_HANDLE hParamMC, /* i/o: decoder DirAC handle */ + const int16_t nchan_transport, /* i : number of input (transport) channels */ + const int16_t nchan_cov ) /* i : number of cov synthesis channels */ + { + int16_t k; + uint16_t max_param_band_residual; + int16_t len; - /*-----------------------------------------------------------------* - * init sub-modules - *-----------------------------------------------------------------*/ + /*-----------------------------------------------------------------* + * init sub-modules + *-----------------------------------------------------------------*/ - /* decorrelation */ - if ( hParamMC->max_band_decorr > 0 ) - { - len = hParamMC->diff_proto_info->num_protos_diff * hParamMC->h_freq_domain_decorr_ap_params->h_onset_detection_power_params.max_band_decorr; + /* decorrelation */ + if ( hParamMC->max_band_decorr > 0 ) + { + len = hParamMC->diff_proto_info->num_protos_diff * hParamMC->h_freq_domain_decorr_ap_params->h_onset_detection_power_params.max_band_decorr; - /* init onsetDetectionPower */ - set_zero( hParamMC->h_freq_domain_decorr_ap_state->h_onset_detection_power_state.onset_detector_1, len ); - set_zero( hParamMC->h_freq_domain_decorr_ap_state->h_onset_detection_power_state.onset_detector_2, len ); - } + /* init onsetDetectionPower */ + set_zero( hParamMC->h_freq_domain_decorr_ap_state->h_onset_detection_power_state.onset_detector_1, len ); + set_zero( hParamMC->h_freq_domain_decorr_ap_state->h_onset_detection_power_state.onset_detector_2, len ); + } - max_param_band_residual = 0; + max_param_band_residual = 0; - /* output synthesis */ - for ( k = hParamMC->hMetadataPMC->num_parameter_bands; k >= 0; k-- ) - { - if ( hParamMC->band_grouping[k] <= hParamMC->max_band_decorr ) + /* output synthesis */ + for ( k = hParamMC->hMetadataPMC->num_parameter_bands; k >= 0; k-- ) { - max_param_band_residual = k; + if ( hParamMC->band_grouping[k] <= hParamMC->max_band_decorr ) + { + max_param_band_residual = k; #ifdef DEBUGGING - assert( hParamMC->band_grouping[k] == hParamMC->max_band_decorr ); + assert( hParamMC->band_grouping[k] == hParamMC->max_band_decorr ); #endif - break; + break; + } } - } - - ivas_dirac_dec_output_synthesis_cov_init( &( hParamMC->h_output_synthesis_cov_state ), nchan_transport, nchan_cov, hParamMC->hMetadataPMC->num_parameter_bands, max_param_band_residual ); - - /*-----------------------------------------------------------------* - * init proto frames - *-----------------------------------------------------------------*/ - if ( hParamMC->max_band_decorr > 0 ) - { - set_zero( hParamMC->proto_frame_f, 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands ); - set_zero( hParamMC->proto_frame_dec_f, 2 * nchan_cov * hParamMC->num_freq_bands ); - } + ivas_dirac_dec_output_synthesis_cov_init( &( hParamMC->h_output_synthesis_cov_state ), nchan_transport, nchan_cov, hParamMC->hMetadataPMC->num_parameter_bands, max_param_band_residual ); - return; -} + /*-----------------------------------------------------------------* + * init proto frames + *-----------------------------------------------------------------*/ + if ( hParamMC->max_band_decorr > 0 ) + { + set_zero( hParamMC->proto_frame_f, 2 * hParamMC->diff_proto_info->num_protos_diff * hParamMC->num_freq_bands ); + set_zero( hParamMC->proto_frame_dec_f, 2 * nchan_cov * hParamMC->num_freq_bands ); + } -/*------------------------------------------------------------------------- - * Local functions - *-------------------------------------------------------------------------*/ + return; + } -/*------------------------------------------------------------------------- - * ivas_param_mc_dec_compute_diffuse_proto() - * - * Compute prototypes for decorrelation - *------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------- + * Local functions + *-------------------------------------------------------------------------*/ -static void param_mc_protoSignalComputation( - float *RealBuffer, /* i : CLDFB samples of the transport channels (real part) */ - float *ImagBuffer, /* i : CLDFB samples of the transport channels (imaginary part) */ - float *proto_frame_f, /* o : interleaved complex prototype CLDFB samples */ - const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, /* i : prototype generation information */ - const int16_t num_freq_bands /* i : number of frequency bands for the prototypes */ -) -{ - int16_t band; - int16_t proto_ch_idx, source_ch_cnt; - float *p_proto_frame; - float *p_real_buffer; - float *p_imag_buffer; - set_zero( proto_frame_f, 2 * num_freq_bands * diff_proto_info->num_protos_diff ); + /*------------------------------------------------------------------------- + * ivas_param_mc_dec_compute_diffuse_proto() + * + * Compute prototypes for decorrelation + *------------------------------------------------------------------------*/ - for ( proto_ch_idx = 0; proto_ch_idx < diff_proto_info->num_protos_diff; proto_ch_idx++ ) + static void param_mc_protoSignalComputation( + float *RealBuffer, /* i : CLDFB samples of the transport channels (real part) */ + float *ImagBuffer, /* i : CLDFB samples of the transport channels (imaginary part) */ + float *proto_frame_f, /* o : interleaved complex prototype CLDFB samples */ + const PARAM_MC_DIFF_PROTO_INFO *diff_proto_info, /* i : prototype generation information */ + const int16_t num_freq_bands /* i : number of frequency bands for the prototypes */ + ) { - int16_t num_source_ch = diff_proto_info->num_source_chan_diff[proto_ch_idx]; + int16_t band; + int16_t proto_ch_idx, source_ch_cnt; + float *p_proto_frame; + float *p_real_buffer; + float *p_imag_buffer; - for ( source_ch_cnt = 0; source_ch_cnt < num_source_ch; source_ch_cnt++ ) - { - float fac = diff_proto_info->proto_fac[proto_ch_idx][source_ch_cnt]; - int16_t source_ch_idx = diff_proto_info->source_chan_idx[proto_ch_idx][source_ch_cnt]; + set_zero( proto_frame_f, 2 * num_freq_bands * diff_proto_info->num_protos_diff ); - p_proto_frame = &proto_frame_f[proto_ch_idx * num_freq_bands * 2]; - p_real_buffer = &RealBuffer[source_ch_idx * num_freq_bands]; - p_imag_buffer = &ImagBuffer[source_ch_idx * num_freq_bands]; + for ( proto_ch_idx = 0; proto_ch_idx < diff_proto_info->num_protos_diff; proto_ch_idx++ ) + { + int16_t num_source_ch = diff_proto_info->num_source_chan_diff[proto_ch_idx]; - for ( band = 0; band < num_freq_bands; band++ ) + for ( source_ch_cnt = 0; source_ch_cnt < num_source_ch; source_ch_cnt++ ) { - *( p_proto_frame++ ) += fac * ( *( p_real_buffer++ ) ); - *( p_proto_frame++ ) += fac * ( *( p_imag_buffer++ ) ); + float fac = diff_proto_info->proto_fac[proto_ch_idx][source_ch_cnt]; + int16_t source_ch_idx = diff_proto_info->source_chan_idx[proto_ch_idx][source_ch_cnt]; + + p_proto_frame = &proto_frame_f[proto_ch_idx * num_freq_bands * 2]; + p_real_buffer = &RealBuffer[source_ch_idx * num_freq_bands]; + p_imag_buffer = &ImagBuffer[source_ch_idx * num_freq_bands]; + + for ( band = 0; band < num_freq_bands; band++ ) + { + *( p_proto_frame++ ) += fac * ( *( p_real_buffer++ ) ); + *( p_proto_frame++ ) += fac * ( *( p_imag_buffer++ ) ); + } } } - } - return; -} + return; + } -/*------------------------------------------------------------------------- - * ivas_param_mc_dec_compute_diffuse_proto() - * - * Transfer decorrelated signals back from the decorrelator buffer to - * the buffers used in the final synthesis - *------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------- + * ivas_param_mc_dec_compute_diffuse_proto() + * + * Transfer decorrelated signals back from the decorrelator buffer to + * the buffers used in the final synthesis + *------------------------------------------------------------------------*/ -static void ivas_param_mc_dec_copy_diffuse_proto( - PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ - float Cldfb_buffer_real[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : CLDFB buffer used in the final synthesis (real part) */ - float Cldfb_buffer_imag[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : CLDFB buffer used in the final synthesis (imaginary part) */ - const int16_t nY, /* i : number of decorrelated channels */ - const int16_t slot_idx /* i : current time slot index */ -) -{ - int16_t k, l; - int16_t num_freq_bands, num_freq_bands_diff; - float *p_proto_diff; + static void ivas_param_mc_dec_copy_diffuse_proto( + PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ + float Cldfb_buffer_real[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : CLDFB buffer used in the final synthesis (real part) */ + float Cldfb_buffer_imag[MAX_CICP_CHANNELS][PARAM_MC_MAX_NSLOTS_IN_SUBFRAME][CLDFB_NO_CHANNELS_MAX], /* o : CLDFB buffer used in the final synthesis (imaginary part) */ + const int16_t nY, /* i : number of decorrelated channels */ + const int16_t slot_idx /* i : current time slot index */ + ) + { + int16_t k, l; + int16_t num_freq_bands, num_freq_bands_diff; + float *p_proto_diff; - num_freq_bands = hParamMC->num_freq_bands; - num_freq_bands_diff = hParamMC->h_output_synthesis_params.max_band_decorr; + num_freq_bands = hParamMC->num_freq_bands; + num_freq_bands_diff = hParamMC->h_output_synthesis_params.max_band_decorr; - for ( k = 0; k < nY; k++ ) - { - p_proto_diff = hParamMC->proto_frame_dec_f + k * 2 * num_freq_bands; - for ( l = 0; l < num_freq_bands_diff; l++ ) + for ( k = 0; k < nY; k++ ) { - Cldfb_buffer_real[k][slot_idx][l] = *( p_proto_diff++ ); - Cldfb_buffer_imag[k][slot_idx][l] = *( p_proto_diff++ ); + p_proto_diff = hParamMC->proto_frame_dec_f + k * 2 * num_freq_bands; + for ( l = 0; l < num_freq_bands_diff; l++ ) + { + Cldfb_buffer_real[k][slot_idx][l] = *( p_proto_diff++ ); + Cldfb_buffer_imag[k][slot_idx][l] = *( p_proto_diff++ ); + } } + + return; } - return; -} + /*------------------------------------------------------------------------- + * ivas_param_mc_bin2dec() + * + * decode a number of bits to an integer + *------------------------------------------------------------------------*/ + /* r : decoded integer */ + static int16_t ivas_param_mc_bin2dec( + uint16_t bits[PARAM_MC_MAX_BITS], /* i : bit buffer */ + const int16_t N /* i : number of bits to decode */ + ) + { + int16_t i; + int16_t out; -/*------------------------------------------------------------------------- - * ivas_param_mc_bin2dec() - * - * decode a number of bits to an integer - *------------------------------------------------------------------------*/ -/* r : decoded integer */ -static int16_t ivas_param_mc_bin2dec( - uint16_t bits[PARAM_MC_MAX_BITS], /* i : bit buffer */ - const int16_t N /* i : number of bits to decode */ -) -{ - int16_t i; - int16_t out; + assert( N <= 16 ); + out = 0; + for ( i = 0; i < N; i++ ) + { + out += ( bits[i] << ( N - 1 - i ) ); + } - assert( N <= 16 ); - out = 0; - for ( i = 0; i < N; i++ ) - { - out += ( bits[i] << ( N - 1 - i ) ); + return out; } - return out; -} + /*------------------------------------------------------------------------- + * ivas_param_mc_uniform_decoder() + * + * decode a uniformily coded sequence of float values + *------------------------------------------------------------------------*/ -/*------------------------------------------------------------------------- - * ivas_param_mc_uniform_decoder() - * - * decode a uniformily coded sequence of float values - *------------------------------------------------------------------------*/ + static int16_t ivas_param_mc_uniform_decoder( + float *seq, /* o : decoded sequence of float values */ + const int16_t sz_seq, /* i : number of values to decode */ + const float *alphabet, /* i : codebook */ + const int16_t N, /* i : number of bits per coded index */ + uint16_t bit_buffer[PARAM_MC_MAX_BITS] /* i : bit buffer to decode */ + ) + { + int16_t i; + int16_t idx; + int16_t n_bits; -static int16_t ivas_param_mc_uniform_decoder( - float *seq, /* o : decoded sequence of float values */ - const int16_t sz_seq, /* i : number of values to decode */ - const float *alphabet, /* i : codebook */ - const int16_t N, /* i : number of bits per coded index */ - uint16_t bit_buffer[PARAM_MC_MAX_BITS] /* i : bit buffer to decode */ -) -{ - int16_t i; - int16_t idx; - int16_t n_bits; + n_bits = 0; + assert( N * sz_seq < PARAM_MC_MAX_BITS ); + + for ( i = 0; i < sz_seq; ++i ) + { + idx = ivas_param_mc_bin2dec( &bit_buffer[i * N], N ); + seq[i] = alphabet[idx]; + } - n_bits = 0; - assert( N * sz_seq < PARAM_MC_MAX_BITS ); + n_bits = N * sz_seq; - for ( i = 0; i < sz_seq; ++i ) - { - idx = ivas_param_mc_bin2dec( &bit_buffer[i * N], N ); - seq[i] = alphabet[idx]; + return n_bits; } - n_bits = N * sz_seq; - return n_bits; -} + /*------------------------------------------------------------------------- + * ivas_param_mc_range_decoder_LC() + * + * decode a sequency of inidices coded with a range coder + *------------------------------------------------------------------------*/ + static int16_t ivas_param_mc_range_decoder_LC( + uint16_t * bit_buffer, /* i : bit buffer to read from */ + int16_t * x, /* o : decoded indices */ + int16_t * BER_detect, /* o : flag for indicating a bit error */ + const int16_t sz_seq, /* i : size of the sequence to be decoded */ + const int16_t sz_alphabet, /* i : size of the alphabet */ + const uint16_t *cft, /* i : cumulative frequency table */ + const uint16_t *sft, /* i : symbol frequency table */ + const int16_t tot_shift, /* i : total frequency as a power of 2 */ + const int16_t nbbits /* i : maximum bit budget */ + ) + { + RangeUniDecState rc_st_dec; /* State of the range decoder */ + int16_t cur_bit_pos; + int16_t k; + int16_t r; -/*------------------------------------------------------------------------- - * ivas_param_mc_range_decoder_LC() - * - * decode a sequency of inidices coded with a range coder - *------------------------------------------------------------------------*/ + /* Start Decoding */ + /* Initialize range decoder */ + cur_bit_pos = 0; + rc_uni_dec_init( &rc_st_dec, bit_buffer, nbbits - 32 ); /* (nbbits + 30) entries are read by the decoder */ -static int16_t ivas_param_mc_range_decoder_LC( - uint16_t *bit_buffer, /* i : bit buffer to read from */ - int16_t *x, /* o : decoded indices */ - int16_t *BER_detect, /* o : flag for indicating a bit error */ - const int16_t sz_seq, /* i : size of the sequence to be decoded */ - const int16_t sz_alphabet, /* i : size of the alphabet */ - const uint16_t *cft, /* i : cumulative frequency table */ - const uint16_t *sft, /* i : symbol frequency table */ - const int16_t tot_shift, /* i : total frequency as a power of 2 */ - const int16_t nbbits /* i : maximum bit budget */ -) -{ - RangeUniDecState rc_st_dec; /* State of the range decoder */ - int16_t cur_bit_pos; - int16_t k; - int16_t r; + /* Main Loop through the indices */ + for ( k = 0; k < sz_seq; k++ ) + { + r = rc_uni_dec_read_symbol_fastS( &rc_st_dec, cft, sft, sz_alphabet, tot_shift ); /*Alphabet size = 17 (2^4 = 16 MSB symbols + 1 ESC symbol) */ + /* r is the symbol read, the possible values are {0,1,....alphabet_size - 1} */ - /* Start Decoding */ - /* Initialize range decoder */ - cur_bit_pos = 0; - rc_uni_dec_init( &rc_st_dec, bit_buffer, nbbits - 32 ); /* (nbbits + 30) entries are read by the decoder */ + /* Update bitstream pointer */ + cur_bit_pos = rc_uni_dec_virtual_finish( &rc_st_dec ); - /* Main Loop through the indices */ - for ( k = 0; k < sz_seq; k++ ) - { - r = rc_uni_dec_read_symbol_fastS( &rc_st_dec, cft, sft, sz_alphabet, tot_shift ); /*Alphabet size = 17 (2^4 = 16 MSB symbols + 1 ESC symbol) */ - /* r is the symbol read, the possible values are {0,1,....alphabet_size - 1} */ + /* Confirm that there is no overflow */ + if ( cur_bit_pos > nbbits ) + { + *BER_detect |= 1; + } + + x[k] = r; + } - /* Update bitstream pointer */ - cur_bit_pos = rc_uni_dec_virtual_finish( &rc_st_dec ); + /* We don't need to finish because virtual_finish() already does the same */ + /*st->next_bit_pos = rc_uni_dec_finish(&rc_st_dec);*/ - /* Confirm that there is no overflow */ - if ( cur_bit_pos > nbbits ) + /* Check for bitstream errors */ + if ( rc_st_dec.bit_error_detected != 0 ) { *BER_detect |= 1; } - x[k] = r; - } - - /* We don't need to finish because virtual_finish() already does the same */ - /*st->next_bit_pos = rc_uni_dec_finish(&rc_st_dec);*/ - - /* Check for bitstream errors */ - if ( rc_st_dec.bit_error_detected != 0 ) - { - *BER_detect |= 1; + return cur_bit_pos; } - return cur_bit_pos; -} - - -/*------------------------------------------------------------------------- - * param_mc_compute_interpolator() - * - * compute the interpolator used in the final synthesis - *------------------------------------------------------------------------*/ -static void ivas_param_mc_dec_compute_interpolator( - const uint16_t bAttackPresent, /* i : flag indicating if we have a transient in the current frame */ - const uint16_t attackPos, /* i : position of the transient */ - const uint16_t interp_length, /* i : number of interpolation values to be calculated */ - float *interpolator /* o : interpolator */ -) -{ - int16_t idx; + /*------------------------------------------------------------------------- + * param_mc_compute_interpolator() + * + * compute the interpolator used in the final synthesis + *------------------------------------------------------------------------*/ - if ( bAttackPresent ) + static void ivas_param_mc_dec_compute_interpolator( + const uint16_t bAttackPresent, /* i : flag indicating if we have a transient in the current frame */ + const uint16_t attackPos, /* i : position of the transient */ + const uint16_t interp_length, /* i : number of interpolation values to be calculated */ + float *interpolator /* o : interpolator */ + ) { - for ( idx = 0; idx < 2 * attackPos; idx++ ) + int16_t idx; + + if ( bAttackPresent ) { - interpolator[idx] = 0.0f; + for ( idx = 0; idx < 2 * attackPos; idx++ ) + { + interpolator[idx] = 0.0f; + } + for ( ; idx < interp_length; idx++ ) + { + interpolator[idx] = 1.0f; + } } - for ( ; idx < interp_length; idx++ ) + else { - interpolator[idx] = 1.0f; + ivas_jbm_dec_get_adapted_linear_interpolator( DEFAULT_JBM_CLDFB_TIMESLOTS, interp_length, interpolator ); } - } - else - { - ivas_jbm_dec_get_adapted_linear_interpolator( DEFAULT_JBM_CLDFB_TIMESLOTS, interp_length, interpolator ); - } - return; -} + return; + } -/*------------------------------------------------------------------------- - * remove_lfe_from_cy() - * - * remove all LFE related values from a covariance matrix - *------------------------------------------------------------------------*/ + /*------------------------------------------------------------------------- + * remove_lfe_from_cy() + * + * remove all LFE related values from a covariance matrix + *------------------------------------------------------------------------*/ -static void remove_lfe_from_cy( - const int16_t nY, /* i : dimension of the covariance matrix */ - int16_t lfe_indices[PARAM_MC_LOCAL_SZ_LFE_MAP], /* i : LFE index */ - int16_t num_lfe, /* i : number of LFEs */ - float *cy, /* i : covariance matrix */ - float *cy_woLFE ) /* o : covariance matrix with LFE removed */ -{ - int16_t ch_idx1, ch_idx2; - int16_t lfe_idx1, lfe_idx2; - float *ptrCy; - float *ptrCy_out; + static void remove_lfe_from_cy( + const int16_t nY, /* i : dimension of the covariance matrix */ + int16_t lfe_indices[PARAM_MC_LOCAL_SZ_LFE_MAP], /* i : LFE index */ + int16_t num_lfe, /* i : number of LFEs */ + float *cy, /* i : covariance matrix */ + float *cy_woLFE ) /* o : covariance matrix with LFE removed */ + { + int16_t ch_idx1, ch_idx2; + int16_t lfe_idx1, lfe_idx2; + float *ptrCy; + float *ptrCy_out; - ptrCy = cy; - ptrCy_out = cy_woLFE; + ptrCy = cy; + ptrCy_out = cy_woLFE; - for ( lfe_idx1 = 0; lfe_idx1 < num_lfe + 1; lfe_idx1++ ) - { - for ( ch_idx1 = lfe_indices[lfe_idx1] + 1; ch_idx1 < lfe_indices[lfe_idx1 + 1]; ch_idx1++ ) + for ( lfe_idx1 = 0; lfe_idx1 < num_lfe + 1; lfe_idx1++ ) { - for ( lfe_idx2 = 0; lfe_idx2 < num_lfe + 1; lfe_idx2++ ) + for ( ch_idx1 = lfe_indices[lfe_idx1] + 1; ch_idx1 < lfe_indices[lfe_idx1 + 1]; ch_idx1++ ) { - for ( ch_idx2 = lfe_indices[lfe_idx2] + 1; ch_idx2 < lfe_indices[lfe_idx2 + 1]; ch_idx2++ ) + for ( lfe_idx2 = 0; lfe_idx2 < num_lfe + 1; lfe_idx2++ ) { - *( ptrCy_out++ ) = *( ptrCy++ ); - } - ptrCy++; + for ( ch_idx2 = lfe_indices[lfe_idx2] + 1; ch_idx2 < lfe_indices[lfe_idx2 + 1]; ch_idx2++ ) + { + *( ptrCy_out++ ) = *( ptrCy++ ); + } + ptrCy++; + } + ptrCy--; } - ptrCy--; + ptrCy += nY; } - ptrCy += nY; + + return; } - return; -} + /*------------------------------------------------------------------------- + * ivas_param_mc_get_mixing_matrices() + * + * calculate the direct and residual mixing matrices + * using the covariance method + *------------------------------------------------------------------------*/ + + static void ivas_param_mc_get_mixing_matrices( + PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ + IVAS_OUTPUT_SETUP * hSynthesisOutputSetup, + float Cx_in[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : input covariance for all parameter bands */ + const int16_t param_band_idx, /* i : parameter band index */ + float *mixing_matrix[], /* o : direct mixing matrices for all parameter bands */ + float *mixing_matrix_res[], /* o : residual mixing matrices for all parameter bands */ + const int16_t nY_intern, /* i : number of channels in the transported format */ + const PARAM_MC_SYNTHESIS_CONF synth_config, /* i : Parametric MC synthesis config */ + const int16_t nX, /* i : number of transport channels */ + const int16_t nY_cov /* i : number of covariance synthesis output channels */ + ) + { + float Cx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float Cy[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float Cy_diag[MAX_CICP_CHANNELS]; + float Cr[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float Cproto_diag[MAX_CICP_CHANNELS]; + float Cproto[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float mat_mult_buffer1[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float *Cx_state; + float *Cx_old_state; + float Cy_state[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float *Cy_old_state; + int16_t nY_band; + float proto_matrix_noLFE[PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS]; + float *proto_matrix_ptr; + int16_t num_lfe_bands; + int16_t brange[2]; + uint16_t i; + int16_t ch_idx1, ch_idx2, lfe_idx1, lfe_idx2; + float *ptrMM; + float *ptrMM_out; + float Cy_full[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float mixing_matrix_local[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS]; + float mixing_matrix_res_local[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + int16_t remove_lfe; + int16_t lfe_indices[PARAM_MC_LOCAL_SZ_LFE_MAP]; + + set_zero( Cproto, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); + set_zero( mat_mult_buffer1, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); + set_zero( proto_matrix_noLFE, PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS ); -/*------------------------------------------------------------------------- - * ivas_param_mc_get_mixing_matrices() - * - * calculate the direct and residual mixing matrices - * using the covariance method - *------------------------------------------------------------------------*/ + nY_band = nY_cov; + num_lfe_bands = 0; + remove_lfe = 0; -static void ivas_param_mc_get_mixing_matrices( - PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ - IVAS_OUTPUT_SETUP *hSynthesisOutputSetup, - float Cx_in[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS], /* i : input covariance for all parameter bands */ - const int16_t param_band_idx, /* i : parameter band index */ - float *mixing_matrix[], /* o : direct mixing matrices for all parameter bands */ - float *mixing_matrix_res[], /* o : residual mixing matrices for all parameter bands */ - const int16_t nY_intern, /* i : number of channels in the transported format */ - const PARAM_MC_SYNTHESIS_CONF synth_config, /* i : Parametric MC synthesis config */ - const int16_t nX, /* i : number of transport channels */ - const int16_t nY_cov /* i : number of covariance synthesis output channels */ -) -{ - float Cx[PARAM_MC_MAX_TRANSPORT_CHANS * PARAM_MC_MAX_TRANSPORT_CHANS]; - float Cy[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float Cy_diag[MAX_CICP_CHANNELS]; - float Cr[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float Cproto_diag[MAX_CICP_CHANNELS]; - float Cproto[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float mat_mult_buffer1[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float *Cx_state; - float *Cx_old_state; - float Cy_state[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float *Cy_old_state; - int16_t nY_band; - float proto_matrix_noLFE[PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS]; - float *proto_matrix_ptr; - int16_t num_lfe_bands; - int16_t brange[2]; - uint16_t i; - int16_t ch_idx1, ch_idx2, lfe_idx1, lfe_idx2; - float *ptrMM; - float *ptrMM_out; - float Cy_full[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float mixing_matrix_local[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS]; - float mixing_matrix_res_local[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - int16_t remove_lfe; - int16_t lfe_indices[PARAM_MC_LOCAL_SZ_LFE_MAP]; - - set_zero( Cproto, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); - set_zero( mat_mult_buffer1, MAX_CICP_CHANNELS * MAX_CICP_CHANNELS ); - set_zero( proto_matrix_noLFE, PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS ); - - nY_band = nY_cov; - num_lfe_bands = 0; - remove_lfe = 0; - - set_s( lfe_indices, -1, PARAM_MC_LOCAL_SZ_LFE_MAP ); - if ( hSynthesisOutputSetup->num_lfe ) - { - float *proto_matrix_ptr_in; + set_s( lfe_indices, -1, PARAM_MC_LOCAL_SZ_LFE_MAP ); + if ( hSynthesisOutputSetup->num_lfe ) + { + float *proto_matrix_ptr_in; #ifdef DEBUGGING - assert( ( nY_cov == ( hSynthesisOutputSetup->nchan_out_woLFE + hSynthesisOutputSetup->num_lfe ) ) && "Number of channels do not match!" ); + assert( ( nY_cov == ( hSynthesisOutputSetup->nchan_out_woLFE + hSynthesisOutputSetup->num_lfe ) ) && "Number of channels do not match!" ); #endif - for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe; lfe_idx1++ ) - { - lfe_indices[lfe_idx1 + 1] = hSynthesisOutputSetup->index_lfe[lfe_idx1]; - } - lfe_indices[hSynthesisOutputSetup->num_lfe + 1] = nY_cov; - proto_matrix_ptr = &proto_matrix_noLFE[0]; - proto_matrix_ptr_in = &hParamMC->h_output_synthesis_params.proto_matrix[0]; - set_zero( proto_matrix_noLFE, PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS ); + for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe; lfe_idx1++ ) + { + lfe_indices[lfe_idx1 + 1] = hSynthesisOutputSetup->index_lfe[lfe_idx1]; + } + lfe_indices[hSynthesisOutputSetup->num_lfe + 1] = nY_cov; + proto_matrix_ptr = &proto_matrix_noLFE[0]; + proto_matrix_ptr_in = &hParamMC->h_output_synthesis_params.proto_matrix[0]; + set_zero( proto_matrix_noLFE, PARAM_MC_MAX_TRANSPORT_CHANS * MAX_CICP_CHANNELS ); - for ( ch_idx1 = 0; ch_idx1 < nX; ch_idx1++ ) - { - for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx1++ ) + for ( ch_idx1 = 0; ch_idx1 < nX; ch_idx1++ ) { - for ( ch_idx2 = lfe_indices[lfe_idx1] + 1; ch_idx2 < lfe_indices[lfe_idx1 + 1]; ch_idx2++ ) + for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx1++ ) { - *( proto_matrix_ptr++ ) = *( proto_matrix_ptr_in++ ); + for ( ch_idx2 = lfe_indices[lfe_idx1] + 1; ch_idx2 < lfe_indices[lfe_idx1 + 1]; ch_idx2++ ) + { + *( proto_matrix_ptr++ ) = *( proto_matrix_ptr_in++ ); + } + proto_matrix_ptr_in++; } - proto_matrix_ptr_in++; + proto_matrix_ptr_in--; } - proto_matrix_ptr_in--; } - } - if ( hParamMC->hMetadataPMC->lfe_on ) - { - num_lfe_bands = PARAM_MC_MAX_BAND_LFE; - } + if ( hParamMC->hMetadataPMC->lfe_on ) + { + num_lfe_bands = PARAM_MC_MAX_BAND_LFE; + } - if ( hSynthesisOutputSetup->num_lfe > 0 && param_band_idx >= num_lfe_bands ) - { - remove_lfe = 1; - nY_band = nY_cov - hSynthesisOutputSetup->num_lfe; - proto_matrix_ptr = proto_matrix_noLFE; - } - else - { - proto_matrix_ptr = hParamMC->h_output_synthesis_params.proto_matrix; - } + if ( hSynthesisOutputSetup->num_lfe > 0 && param_band_idx >= num_lfe_bands ) + { + remove_lfe = 1; + nY_band = nY_cov - hSynthesisOutputSetup->num_lfe; + proto_matrix_ptr = proto_matrix_noLFE; + } + else + { + proto_matrix_ptr = hParamMC->h_output_synthesis_params.proto_matrix; + } - brange[0] = hParamMC->band_grouping[param_band_idx]; - brange[1] = hParamMC->band_grouping[param_band_idx + 1]; + brange[0] = hParamMC->band_grouping[param_band_idx]; + brange[1] = hParamMC->band_grouping[param_band_idx + 1]; - Cx_state = Cx_in; - Cx_old_state = hParamMC->h_output_synthesis_cov_state.cx_old[param_band_idx]; - Cy_old_state = hParamMC->h_output_synthesis_cov_state.cy_old[param_band_idx]; + Cx_state = Cx_in; + Cx_old_state = hParamMC->h_output_synthesis_cov_state.cx_old[param_band_idx]; + Cy_old_state = hParamMC->h_output_synthesis_cov_state.cy_old[param_band_idx]; - /* Getting mixing mtx */ - /* estimate target cov from input cov and proto_matrix */ - matrix_product( hParamMC->proto_matrix_int, nY_intern, nX, 0, Cx_state, nX, nX, 0, mat_mult_buffer1 ); + /* Getting mixing mtx */ + /* estimate target cov from input cov and proto_matrix */ + matrix_product( hParamMC->proto_matrix_int, nY_intern, nX, 0, Cx_state, nX, nX, 0, mat_mult_buffer1 ); - matrix_product( mat_mult_buffer1, nY_intern, nX, 0, hParamMC->proto_matrix_int, nY_intern, nX, 1, Cproto ); + matrix_product( mat_mult_buffer1, nY_intern, nX, 0, hParamMC->proto_matrix_int, nY_intern, nX, 1, Cproto ); - for ( ch_idx1 = 0; ch_idx1 < nY_intern; ch_idx1++ ) - { - if ( Cproto[ch_idx1 + ch_idx1 * nY_intern] < 0.0f ) + for ( ch_idx1 = 0; ch_idx1 < nY_intern; ch_idx1++ ) { - Cproto[ch_idx1 + ch_idx1 * nY_intern] = 0.0f; + if ( Cproto[ch_idx1 + ch_idx1 * nY_intern] < 0.0f ) + { + Cproto[ch_idx1 + ch_idx1 * nY_intern] = 0.0f; + } } - } - ivas_param_mc_dequantize_cov( hParamMC, - hParamMC->icld_q + param_band_idx * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe, - hParamMC->icc_q + param_band_idx * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe, - param_band_idx, nY_cov, - synth_config, - nY_intern, - nX, Cx_state, Cproto, Cy_state ); + ivas_param_mc_dequantize_cov( hParamMC, + hParamMC->icld_q + param_band_idx * hParamMC->hMetadataPMC->ild_mapping_conf->ild_map_size_lfe, + hParamMC->icc_q + param_band_idx * hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe, + param_band_idx, nY_cov, + synth_config, + nY_intern, + nX, Cx_state, Cproto, Cy_state ); - /* Smoothing: Sum over two buffers */ - if ( hParamMC->hMetadataPMC->bAttackPresent ) - { - /* no smoothing on attacks */ - mvr2r( Cx_state, Cx, nX * nX ); - mvr2r( Cy_state, Cy_full, nY_cov * nY_cov ); - } - else - { - /* smoothing gains are now identical to one, simply add up */ - v_add( Cx_state, Cx_old_state, Cx, nX * nX ); - v_add( Cy_state, Cy_old_state, Cy_full, nY_cov * nY_cov ); - } + /* Smoothing: Sum over two buffers */ + if ( hParamMC->hMetadataPMC->bAttackPresent ) + { + /* no smoothing on attacks */ + mvr2r( Cx_state, Cx, nX * nX ); + mvr2r( Cy_state, Cy_full, nY_cov * nY_cov ); + } + else + { + /* smoothing gains are now identical to one, simply add up */ + v_add( Cx_state, Cx_old_state, Cx, nX * nX ); + v_add( Cy_state, Cy_old_state, Cy_full, nY_cov * nY_cov ); + } - /* cov buffer update */ - mvr2r( Cx_state, Cx_old_state, nX * nX ); - mvr2r( Cy_state, Cy_old_state, nY_cov * nY_cov ); + /* cov buffer update */ + mvr2r( Cx_state, Cx_old_state, nX * nX ); + mvr2r( Cy_state, Cy_old_state, nY_cov * nY_cov ); - /* remove LFE if necessary */ - if ( remove_lfe ) - { - remove_lfe_from_cy( nY_cov, lfe_indices, hSynthesisOutputSetup->num_lfe, Cy_full, Cy ); - } - else - { - mvr2r( Cy_full, Cy, nY_band * nY_band ); - } + /* remove LFE if necessary */ + if ( remove_lfe ) + { + remove_lfe_from_cy( nY_cov, lfe_indices, hSynthesisOutputSetup->num_lfe, Cy_full, Cy ); + } + else + { + mvr2r( Cy_full, Cy, nY_band * nY_band ); + } - matrix_product( proto_matrix_ptr, nY_band, nX, 0, Cx, nX, nX, 0, mat_mult_buffer1 ); + matrix_product( proto_matrix_ptr, nY_band, nX, 0, Cx, nX, nX, 0, mat_mult_buffer1 ); - matrix_product_diag( mat_mult_buffer1, nY_band, nX, 0, proto_matrix_ptr, nY_band, nX, 1, Cproto_diag ); + matrix_product_diag( mat_mult_buffer1, nY_band, nX, 0, proto_matrix_ptr, nY_band, nX, 1, Cproto_diag ); - /* make sure we have no negative entries in Cproto_diag due to rounding errors */ - for ( ch_idx1 = 0; ch_idx1 < nY_band; ch_idx1++ ) - { - if ( Cproto_diag[ch_idx1] < 0.0f ) + /* make sure we have no negative entries in Cproto_diag due to rounding errors */ + for ( ch_idx1 = 0; ch_idx1 < nY_band; ch_idx1++ ) { - Cproto_diag[ch_idx1] = 0.0f; + if ( Cproto_diag[ch_idx1] < 0.0f ) + { + Cproto_diag[ch_idx1] = 0.0f; + } } - } - - /* Computing the mixing matrices */ - - /* bands with decorr */ - if ( brange[0] < hParamMC->h_output_synthesis_params.max_band_decorr ) - { - computeMixingMatrices( nX, nY_band, Cx, Cy, proto_matrix_ptr, 0, PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix_local, Cr ); - /* Compute mixing matrix for residual */ - computeMixingMatricesResidual( nY_band, Cproto_diag, Cr, PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix_res_local ); + /* Computing the mixing matrices */ - if ( remove_lfe ) + /* bands with decorr */ + if ( brange[0] < hParamMC->h_output_synthesis_params.max_band_decorr ) { - set_zero( mixing_matrix_res[param_band_idx], nY_cov * nY_cov ); + computeMixingMatrices( nX, nY_band, Cx, Cy, proto_matrix_ptr, 0, PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix_local, Cr ); + + /* Compute mixing matrix for residual */ + computeMixingMatricesResidual( nY_band, Cproto_diag, Cr, PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix_res_local ); - ptrMM = mixing_matrix_res_local; - ptrMM_out = mixing_matrix_res[param_band_idx]; - for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx1++ ) + if ( remove_lfe ) { - for ( ch_idx1 = lfe_indices[lfe_idx1] + 1; ch_idx1 < lfe_indices[lfe_idx1 + 1]; ch_idx1++ ) + set_zero( mixing_matrix_res[param_band_idx], nY_cov * nY_cov ); + + ptrMM = mixing_matrix_res_local; + ptrMM_out = mixing_matrix_res[param_band_idx]; + for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx1++ ) { - for ( lfe_idx2 = 0; lfe_idx2 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx2++ ) + for ( ch_idx1 = lfe_indices[lfe_idx1] + 1; ch_idx1 < lfe_indices[lfe_idx1 + 1]; ch_idx1++ ) { - for ( ch_idx2 = lfe_indices[lfe_idx2] + 1; ch_idx2 < lfe_indices[lfe_idx2 + 1]; ch_idx2++ ) + for ( lfe_idx2 = 0; lfe_idx2 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx2++ ) { - *( ptrMM_out++ ) = *( ptrMM++ ); + for ( ch_idx2 = lfe_indices[lfe_idx2] + 1; ch_idx2 < lfe_indices[lfe_idx2 + 1]; ch_idx2++ ) + { + *( ptrMM_out++ ) = *( ptrMM++ ); + } + ptrMM_out++; } - ptrMM_out++; + ptrMM_out--; } - ptrMM_out--; + ptrMM_out += nY_cov; } - ptrMM_out += nY_cov; + } + else + { + mvr2r( mixing_matrix_res_local, mixing_matrix_res[param_band_idx], nY_cov * nY_cov ); } } - else + else if ( brange[0] < hParamMC->max_band_energy_compensation ) { - mvr2r( mixing_matrix_res_local, mixing_matrix_res[param_band_idx], nY_cov * nY_cov ); + /* Compute mixing matrices (energy compensation only) */ + computeMixingMatrices( nX, nY_band, Cx, Cy, proto_matrix_ptr, 1, PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix_local, Cr ); } - } - else if ( brange[0] < hParamMC->max_band_energy_compensation ) - { - /* Compute mixing matrices (energy compensation only) */ - computeMixingMatrices( nX, nY_band, Cx, Cy, proto_matrix_ptr, 1, PARAM_MC_REG_SX, PARAM_MC_REG_GHAT, mixing_matrix_local, Cr ); - } - else - { - /*if neither decorrelation nor energy compensation is applied*/ - for ( i = 0; i < nY_band; i++ ) + else { - Cy_diag[i] = Cy[i + nY_band * i]; - Cy_diag[i] = sqrtf( Cy_diag[i] / ( Cproto_diag[i] + EPSILON ) ); - } - - diag_matrix_product( Cy_diag, nY_band, proto_matrix_ptr, nY_band, nX, 0, mixing_matrix_local ); - } - if ( remove_lfe ) - { - set_zero( mixing_matrix[param_band_idx], nX * nY_cov ); + /*if neither decorrelation nor energy compensation is applied*/ + for ( i = 0; i < nY_band; i++ ) + { + Cy_diag[i] = Cy[i + nY_band * i]; + Cy_diag[i] = sqrtf( Cy_diag[i] / ( Cproto_diag[i] + EPSILON ) ); + } - ptrMM = mixing_matrix_local; - ptrMM_out = mixing_matrix[param_band_idx]; - for ( ch_idx1 = 0; ch_idx1 < nX; ch_idx1++ ) + diag_matrix_product( Cy_diag, nY_band, proto_matrix_ptr, nY_band, nX, 0, mixing_matrix_local ); + } + if ( remove_lfe ) { - for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx1++ ) + set_zero( mixing_matrix[param_band_idx], nX * nY_cov ); + + ptrMM = mixing_matrix_local; + ptrMM_out = mixing_matrix[param_band_idx]; + for ( ch_idx1 = 0; ch_idx1 < nX; ch_idx1++ ) { - for ( ch_idx2 = lfe_indices[lfe_idx1] + 1; ch_idx2 < lfe_indices[lfe_idx1 + 1]; ch_idx2++ ) + for ( lfe_idx1 = 0; lfe_idx1 < hSynthesisOutputSetup->num_lfe + 1; lfe_idx1++ ) { - *( ptrMM_out++ ) = *( ptrMM++ ); + for ( ch_idx2 = lfe_indices[lfe_idx1] + 1; ch_idx2 < lfe_indices[lfe_idx1 + 1]; ch_idx2++ ) + { + *( ptrMM_out++ ) = *( ptrMM++ ); + } + ptrMM_out++; } - ptrMM_out++; + ptrMM_out--; } - ptrMM_out--; } - } - else - { - mvr2r( mixing_matrix_local, mixing_matrix[param_band_idx], nY_cov * nX ); - } - - return; -} - - -/*------------------------------------------------------------------------- - * param_mc_update_mixing_matrices() - * - * update mixing matrix buffers - *------------------------------------------------------------------------*/ - -static void param_mc_update_mixing_matrices( - PARAM_MC_DEC_HANDLE hParamMC, /* i/o: Parametric MC handle */ - float *mixing_matrix[], /* i : direct mixing matrices for the frame just processed */ - float *mixing_matrix_res[], /* i : residual mixing matrices for the frame just processed */ - const uint16_t nX, /* i : number of transport channels */ - const uint16_t nY ) /* i : number of synthesis channels */ -{ - uint16_t param_band_idx; - - for ( param_band_idx = 0; param_band_idx < hParamMC->hMetadataPMC->nbands_coded; param_band_idx++ ) - { - int16_t brange[2]; - - brange[0] = hParamMC->band_grouping[param_band_idx]; - brange[1] = hParamMC->band_grouping[param_band_idx + 1]; - - mvr2r( mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[param_band_idx], nX * nY ); - - if ( brange[0] < hParamMC->h_output_synthesis_params.max_band_decorr ) + else { - mvr2r( mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], nY * nY ); + mvr2r( mixing_matrix_local, mixing_matrix[param_band_idx], nY_cov * nX ); } - } - - return; -} + return; + } -/*------------------------------------------------------------------------- - * ivas_param_mc_dequantize_cov() - * - * generate the target covariance matrix - *------------------------------------------------------------------------*/ -static void ivas_param_mc_dequantize_cov( - PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ - float *ild_q, /* i : sequence of dequantized ILD values */ - float *icc_q, /* i : sequence of dequantized ICC values */ - const int16_t param_band_index, /* i : current parameter band */ - const int16_t nY_cov, /* i : number of output channels in the covariance synthesis */ - const PARAM_MC_SYNTHESIS_CONF synth_conf, /* i : Parametric MC synthesis configuration */ - const int16_t nY_int, /* i : number of channels in the transported format */ - const int16_t nX, /* i : number of transport channels */ - float *Cx_state, /* i : transport channel covariance matrix */ - float *Cproto, /* i : prototype matrix */ - float *Cy_state /* o : target covariance matrix */ -) -{ - float Nrqq[MAX_OUTPUT_CHANNELS]; - float a[MAX_OUTPUT_CHANNELS]; - int16_t k; - int16_t l; - float *Cyp; - float ap; - const PARAM_MC_ILD_MAPPING *h_ild_mapping; - float Cy_state_int[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; - - set_zero( Nrqq, MAX_OUTPUT_CHANNELS ); - h_ild_mapping = hParamMC->hMetadataPMC->ild_mapping_conf; + /*------------------------------------------------------------------------- + * param_mc_update_mixing_matrices() + * + * update mixing matrix buffers + *------------------------------------------------------------------------*/ - /*get back Nrg*/ - for ( k = 0; k < nY_int; k++ ) + static void param_mc_update_mixing_matrices( + PARAM_MC_DEC_HANDLE hParamMC, /* i/o: Parametric MC handle */ + float *mixing_matrix[], /* i : direct mixing matrices for the frame just processed */ + float *mixing_matrix_res[], /* i : residual mixing matrices for the frame just processed */ + const uint16_t nX, /* i : number of transport channels */ + const uint16_t nY ) /* i : number of synthesis channels */ { - float ref_ener = 0.0f; - int16_t ref_channel_cnt; - int16_t ref_channel_idx; + uint16_t param_band_idx; - for ( ref_channel_cnt = 0; ref_channel_cnt < h_ild_mapping->num_ref_channels[k]; ref_channel_cnt++ ) + for ( param_band_idx = 0; param_band_idx < hParamMC->hMetadataPMC->nbands_coded; param_band_idx++ ) { - ref_channel_idx = h_ild_mapping->ref_channel_idx[k][ref_channel_cnt]; - ref_ener += Cx_state[ref_channel_idx + ref_channel_idx * nX]; - } - Nrqq[h_ild_mapping->ild_index[k]] = powf( 10.0f, ild_q[k] / 10.0f ) * hParamMC->hMetadataPMC->ild_factors[k] * ref_ener; - } + int16_t brange[2]; - /* estimate ICCs from estimated Cproto */ - for ( k = 0; k < nY_int; k++ ) - { - a[k] = 1.f / ( sqrtf( Cproto[k + nY_int * k] ) + EPSILON ); + brange[0] = hParamMC->band_grouping[param_band_idx]; + brange[1] = hParamMC->band_grouping[param_band_idx + 1]; - v_multc( Cproto + k * nY_int, a[k], Cy_state_int + k * nY_int, nY_int ); - } + mvr2r( mixing_matrix[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_old[param_band_idx], nX * nY ); - for ( k = 0; k < nY_int; k++ ) - { - Cyp = Cy_state_int + k; - ap = a[k]; - for ( l = 0; l < nY_int; l++ ) - { - ( *Cyp ) *= ap; - Cyp += nY_int; + if ( brange[0] < hParamMC->h_output_synthesis_params.max_band_decorr ) + { + mvr2r( mixing_matrix_res[param_band_idx], hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old[param_band_idx], nY * nY ); + } } - } - /* replace some estimated ICCs with transmitted values */ - for ( k = 0; k < hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe; k++ ) - { - Cy_state_int[hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][0] + nY_int * hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][1]] = icc_q[k]; - Cy_state_int[hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][1] + nY_int * hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][0]] = icc_q[k]; + return; } - if ( param_band_index >= PARAM_MC_MAX_BAND_LFE || !hParamMC->hMetadataPMC->lfe_on ) - { + + /*------------------------------------------------------------------------- + * ivas_param_mc_dequantize_cov() + * + * generate the target covariance matrix + *------------------------------------------------------------------------*/ + + static void ivas_param_mc_dequantize_cov( + PARAM_MC_DEC_HANDLE hParamMC, /* i : Parametric MC handle */ + float *ild_q, /* i : sequence of dequantized ILD values */ + float *icc_q, /* i : sequence of dequantized ICC values */ + const int16_t param_band_index, /* i : current parameter band */ + const int16_t nY_cov, /* i : number of output channels in the covariance synthesis */ + const PARAM_MC_SYNTHESIS_CONF synth_conf, /* i : Parametric MC synthesis configuration */ + const int16_t nY_int, /* i : number of channels in the transported format */ + const int16_t nX, /* i : number of transport channels */ + float *Cx_state, /* i : transport channel covariance matrix */ + float *Cproto, /* i : prototype matrix */ + float *Cy_state /* o : target covariance matrix */ + ) + { + float Nrqq[MAX_OUTPUT_CHANNELS]; + float a[MAX_OUTPUT_CHANNELS]; + int16_t k; + int16_t l; + float *Cyp; + float ap; + const PARAM_MC_ILD_MAPPING *h_ild_mapping; + float Cy_state_int[MAX_OUTPUT_CHANNELS * MAX_OUTPUT_CHANNELS]; + + set_zero( Nrqq, MAX_OUTPUT_CHANNELS ); + h_ild_mapping = hParamMC->hMetadataPMC->ild_mapping_conf; + + /*get back Nrg*/ for ( k = 0; k < nY_int; k++ ) { - Cy_state_int[k + 3 * nY_int] = 1.0f; - Cy_state_int[3 + k * nY_int] = 1.0f; - } - Nrqq[3] = 0.0f; - } - - /* Generate back Covariance Mtx */ - for ( k = 0; k < nY_int; k++ ) - { - a[k] = sqrtf( Nrqq[k] ); - v_multc( Cy_state_int + k * nY_int, a[k], Cy_state_int + k * nY_int, nY_int ); - } - - for ( k = 0; k < nY_int; k++ ) - { - Cyp = Cy_state_int + k; - ap = a[k]; + float ref_ener = 0.0f; + int16_t ref_channel_cnt; + int16_t ref_channel_idx; - for ( l = 0; l < nY_int; l++ ) - { - ( *Cyp ) *= ap; - Cyp += nY_int; + for ( ref_channel_cnt = 0; ref_channel_cnt < h_ild_mapping->num_ref_channels[k]; ref_channel_cnt++ ) + { + ref_channel_idx = h_ild_mapping->ref_channel_idx[k][ref_channel_cnt]; + ref_ener += Cx_state[ref_channel_idx + ref_channel_idx * nX]; + } + Nrqq[h_ild_mapping->ild_index[k]] = powf( 10.0f, ild_q[k] / 10.0f ) * hParamMC->hMetadataPMC->ild_factors[k] * ref_ener; } - } - if ( synth_conf == PARAM_MC_SYNTH_LS_CONV_COV ) - { - /* Cy = dmx*Cy*dmx' */ - float mat_mult_buffer1[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; - float target_ch_ener[MAX_CICP_CHANNELS]; - float dmx_ch_ener[MAX_CICP_CHANNELS]; - - set_zero( target_ch_ener, MAX_CICP_CHANNELS ); - set_zero( dmx_ch_ener, MAX_CICP_CHANNELS ); - - matrix_product( hParamMC->ls_conv_dmx_matrix, nY_cov, nY_int, 0, - Cy_state_int, nY_int, nY_int, 0, - mat_mult_buffer1 ); + /* estimate ICCs from estimated Cproto */ + for ( k = 0; k < nY_int; k++ ) + { + a[k] = 1.f / ( sqrtf( Cproto[k + nY_int * k] ) + EPSILON ); - matrix_product( mat_mult_buffer1, nY_cov, nY_int, 0, - hParamMC->ls_conv_dmx_matrix, nY_cov, nY_int, 1, - Cy_state ); + v_multc( Cproto + k * nY_int, a[k], Cy_state_int + k * nY_int, nY_int ); + } - for ( k = 0; k < nY_cov; k++ ) + for ( k = 0; k < nY_int; k++ ) { + Cyp = Cy_state_int + k; + ap = a[k]; for ( l = 0; l < nY_int; l++ ) { - target_ch_ener[k] += hParamMC->ls_conv_dmx_matrix[k + l * nY_cov] * Nrqq[l]; + ( *Cyp ) *= ap; + Cyp += nY_int; } + } - dmx_ch_ener[k] = Cy_state[k + nY_cov * k]; + /* replace some estimated ICCs with transmitted values */ + for ( k = 0; k < hParamMC->hMetadataPMC->icc_mapping_conf->icc_map_size_lfe; k++ ) + { + Cy_state_int[hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][0] + nY_int * hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][1]] = icc_q[k]; + Cy_state_int[hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][1] + nY_int * hParamMC->hMetadataPMC->icc_mapping_conf->icc_mapping[k][0]] = icc_q[k]; + } - if ( dmx_ch_ener[k] < 0.0f ) + if ( param_band_index >= PARAM_MC_MAX_BAND_LFE || !hParamMC->hMetadataPMC->lfe_on ) + { + for ( k = 0; k < nY_int; k++ ) { - Cy_state[k + nY_cov * k] *= -1.0f; - dmx_ch_ener[k] *= -1.0f; + Cy_state_int[k + 3 * nY_int] = 1.0f; + Cy_state_int[3 + k * nY_int] = 1.0f; } + Nrqq[3] = 0.0f; + } - target_ch_ener[k] = sqrtf( target_ch_ener[k] / ( dmx_ch_ener[k] + EPSILON ) ); + /* Generate back Covariance Mtx */ + for ( k = 0; k < nY_int; k++ ) + { + a[k] = sqrtf( Nrqq[k] ); + v_multc( Cy_state_int + k * nY_int, a[k], Cy_state_int + k * nY_int, nY_int ); + } - v_multc( Cy_state + k * nY_cov, target_ch_ener[k], Cy_state + k * nY_cov, nY_cov ); + for ( k = 0; k < nY_int; k++ ) + { + Cyp = Cy_state_int + k; + ap = a[k]; - Cyp = Cy_state + k; - ap = target_ch_ener[k]; - for ( l = 0; l < nY_cov; l++ ) + for ( l = 0; l < nY_int; l++ ) { ( *Cyp ) *= ap; - Cyp += nY_cov; + Cyp += nY_int; } } - } - else - { - mvr2r( Cy_state_int, Cy_state, nY_int * nY_int ); - } - return; -} + if ( synth_conf == PARAM_MC_SYNTH_LS_CONV_COV ) + { + /* Cy = dmx*Cy*dmx' */ + float mat_mult_buffer1[MAX_CICP_CHANNELS * MAX_CICP_CHANNELS]; + float target_ch_ener[MAX_CICP_CHANNELS]; + float dmx_ch_ener[MAX_CICP_CHANNELS]; + set_zero( target_ch_ener, MAX_CICP_CHANNELS ); + set_zero( dmx_ch_ener, MAX_CICP_CHANNELS ); -/*-------------------------------------------------------------------------* - * param_mc_set_num_synth_bands() - * - * set the number of frequency bands to be synthesized - *-------------------------------------------------------------------------*/ + matrix_product( hParamMC->ls_conv_dmx_matrix, nY_cov, nY_int, 0, + Cy_state_int, nY_int, nY_int, 0, + mat_mult_buffer1 ); -static void param_mc_set_num_synth_bands( - const int32_t output_Fs, /* i : output sampling frequency */ - PARAM_MC_DEC_HANDLE hParamMC /* i/o: Parametric MC handle */ -) -{ - uint16_t max_param_band_synth; - const int16_t *param_mc_bands_coded; - - switch ( hParamMC->hMetadataPMC->num_parameter_bands ) - { - case 20: - param_mc_bands_coded = param_mc_bands_coded_20; - break; - case 10: - param_mc_bands_coded = param_mc_bands_coded_10; - break; - case 14: - default: - param_mc_bands_coded = param_mc_bands_coded_14; - break; - } + matrix_product( mat_mult_buffer1, nY_cov, nY_int, 0, + hParamMC->ls_conv_dmx_matrix, nY_cov, nY_int, 1, + Cy_state ); - switch ( output_Fs ) - { - case 8000: - max_param_band_synth = param_mc_bands_coded[NB]; - break; - case 16000: - max_param_band_synth = param_mc_bands_coded[WB]; - break; - case 32000: - max_param_band_synth = param_mc_bands_coded[SWB]; - break; - case 48000: - default: - max_param_band_synth = param_mc_bands_coded[FB]; - break; - } + for ( k = 0; k < nY_cov; k++ ) + { + for ( l = 0; l < nY_int; l++ ) + { + target_ch_ener[k] += hParamMC->ls_conv_dmx_matrix[k + l * nY_cov] * Nrqq[l]; + } - hParamMC->num_param_bands_synth = min( hParamMC->hMetadataPMC->nbands_coded, max_param_band_synth ); + dmx_ch_ener[k] = Cy_state[k + nY_cov * k]; - return; -} + if ( dmx_ch_ener[k] < 0.0f ) + { + Cy_state[k + nY_cov * k] *= -1.0f; + dmx_ch_ener[k] *= -1.0f; + } + target_ch_ener[k] = sqrtf( target_ch_ener[k] / ( dmx_ch_ener[k] + EPSILON ) ); -/*-------------------------------------------------------------------------* - * param_mc_get_diff_proto_info() - * - * calculated the diffuse prototype information - *-------------------------------------------------------------------------*/ + v_multc( Cy_state + k * nY_cov, target_ch_ener[k], Cy_state + k * nY_cov, nY_cov ); -static ivas_error param_mc_get_diff_proto_info( - const float *proto_mtx, /* i : protoype matrix for the synthesis */ - const uint16_t nchan_transport, /* i : number of transport channels */ - const uint16_t nchan_out_cov, /* i : number if output channels of the covariance synthesis */ - PARAM_MC_DIFF_PROTO_INFO *p_diff_proto_info /* o : generated diffuse prototype info */ -) -{ - float proto_fac[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS]; - uint16_t cur_out_ch; - uint16_t cur_diff_proto; - uint16_t cur_transport_ch; - uint16_t max_num_src_chan; + Cyp = Cy_state + k; + ap = target_ch_ener[k]; + for ( l = 0; l < nY_cov; l++ ) + { + ( *Cyp ) *= ap; + Cyp += nY_cov; + } + } + } + else + { + mvr2r( Cy_state_int, Cy_state, nY_int * nY_int ); + } - /* Initializations */ - max_num_src_chan = 0; - set_zero( proto_fac, MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS ); - if ( ( p_diff_proto_info->proto_index_diff = (int16_t *) malloc( nchan_out_cov * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + return; } - set_s( p_diff_proto_info->proto_index_diff, 0, nchan_out_cov ); - if ( ( p_diff_proto_info->num_source_chan_diff = (int16_t *) malloc( nchan_out_cov * sizeof( int16_t ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); - } - set_s( p_diff_proto_info->num_source_chan_diff, 0, nchan_out_cov ); - /* we have at least one prototype, copy the first one */ - p_diff_proto_info->num_protos_diff = 1; - mvr2r_inc( proto_mtx, nchan_out_cov, proto_fac, nchan_out_cov, nchan_transport ); - p_diff_proto_info->proto_index_diff[0] = 0; + /*-------------------------------------------------------------------------* + * param_mc_set_num_synth_bands() + * + * set the number of frequency bands to be synthesized + *-------------------------------------------------------------------------*/ - /* search for distinct prototypes */ - for ( cur_out_ch = 1; cur_out_ch < nchan_out_cov; cur_out_ch++ ) + static void param_mc_set_num_synth_bands( + const int32_t output_Fs, /* i : output sampling frequency */ + PARAM_MC_DEC_HANDLE hParamMC /* i/o: Parametric MC handle */ + ) { - uint16_t found = 0; + uint16_t max_param_band_synth; + const int16_t *param_mc_bands_coded; - for ( cur_diff_proto = 0; cur_diff_proto < p_diff_proto_info->num_protos_diff; cur_diff_proto++ ) + switch ( hParamMC->hMetadataPMC->num_parameter_bands ) { - float diff = 0; - float *proto_fac_ptr = proto_fac + cur_diff_proto; - const float *proto_mtx_ptr = proto_mtx + cur_out_ch; - - for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) - { - diff += fabsf( *proto_fac_ptr - *proto_mtx_ptr ); - proto_fac_ptr += nchan_out_cov; - proto_mtx_ptr += nchan_out_cov; - } - - /* we already have this prototype, save the index */ - if ( diff < 0.1f ) - { - found = 1; - p_diff_proto_info->proto_index_diff[cur_out_ch] = cur_diff_proto; + case 20: + param_mc_bands_coded = param_mc_bands_coded_20; + break; + case 10: + param_mc_bands_coded = param_mc_bands_coded_10; + break; + case 14: + default: + param_mc_bands_coded = param_mc_bands_coded_14; break; - } } - /* new distinct prototype, add it */ - if ( found == 0 ) + switch ( output_Fs ) { - const float *proto_mtx_ptr = proto_mtx + cur_out_ch; - int16_t cur_num_src_chan; - - cur_num_src_chan = 0; - for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) - { - if ( *proto_mtx_ptr > EPSILON ) - { - cur_num_src_chan++; - } - proto_mtx_ptr += nchan_out_cov; - } + case 8000: + max_param_band_synth = param_mc_bands_coded[NB]; + break; + case 16000: + max_param_band_synth = param_mc_bands_coded[WB]; + break; + case 32000: + max_param_band_synth = param_mc_bands_coded[SWB]; + break; + case 48000: + default: + max_param_band_synth = param_mc_bands_coded[FB]; + break; + } - mvr2r_inc( proto_mtx + cur_out_ch, nchan_out_cov, proto_fac + p_diff_proto_info->num_protos_diff, nchan_out_cov, nchan_transport ); + hParamMC->num_param_bands_synth = min( hParamMC->hMetadataPMC->nbands_coded, max_param_band_synth ); - p_diff_proto_info->proto_index_diff[cur_out_ch] = p_diff_proto_info->num_protos_diff; - p_diff_proto_info->num_protos_diff++; - max_num_src_chan = max( max_num_src_chan, cur_num_src_chan ); - } + return; } - /* set up the prototype info struct */ - if ( ( p_diff_proto_info->source_chan_idx = (int16_t **) malloc( p_diff_proto_info->num_protos_diff * sizeof( int16_t * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); - } - if ( ( p_diff_proto_info->proto_fac = (float **) malloc( p_diff_proto_info->num_protos_diff * sizeof( float * ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); - } - for ( cur_diff_proto = 0; cur_diff_proto < p_diff_proto_info->num_protos_diff; cur_diff_proto++ ) + /*-------------------------------------------------------------------------* + * param_mc_get_diff_proto_info() + * + * calculated the diffuse prototype information + *-------------------------------------------------------------------------*/ + + static ivas_error param_mc_get_diff_proto_info( + const float *proto_mtx, /* i : protoype matrix for the synthesis */ + const uint16_t nchan_transport, /* i : number of transport channels */ + const uint16_t nchan_out_cov, /* i : number if output channels of the covariance synthesis */ + PARAM_MC_DIFF_PROTO_INFO *p_diff_proto_info /* o : generated diffuse prototype info */ + ) { - float *proto_fac_ptr; + float proto_fac[MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS]; + uint16_t cur_out_ch; + uint16_t cur_diff_proto; + uint16_t cur_transport_ch; + uint16_t max_num_src_chan; - if ( ( p_diff_proto_info->source_chan_idx[cur_diff_proto] = (int16_t *) malloc( max_num_src_chan * sizeof( int16_t ) ) ) == NULL ) + /* Initializations */ + max_num_src_chan = 0; + set_zero( proto_fac, MAX_CICP_CHANNELS * PARAM_MC_MAX_TRANSPORT_CHANS ); + if ( ( p_diff_proto_info->proto_index_diff = (int16_t *) malloc( nchan_out_cov * sizeof( int16_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); } - if ( ( p_diff_proto_info->proto_fac[cur_diff_proto] = (float *) malloc( max_num_src_chan * sizeof( float ) ) ) == NULL ) + set_s( p_diff_proto_info->proto_index_diff, 0, nchan_out_cov ); + + if ( ( p_diff_proto_info->num_source_chan_diff = (int16_t *) malloc( nchan_out_cov * sizeof( int16_t ) ) ) == NULL ) { return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); } + set_s( p_diff_proto_info->num_source_chan_diff, 0, nchan_out_cov ); + + /* we have at least one prototype, copy the first one */ + p_diff_proto_info->num_protos_diff = 1; + mvr2r_inc( proto_mtx, nchan_out_cov, proto_fac, nchan_out_cov, nchan_transport ); + p_diff_proto_info->proto_index_diff[0] = 0; - proto_fac_ptr = proto_fac + cur_diff_proto; - for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) + /* search for distinct prototypes */ + for ( cur_out_ch = 1; cur_out_ch < nchan_out_cov; cur_out_ch++ ) { - if ( *proto_fac_ptr > EPSILON ) + uint16_t found = 0; + + for ( cur_diff_proto = 0; cur_diff_proto < p_diff_proto_info->num_protos_diff; cur_diff_proto++ ) { - p_diff_proto_info->source_chan_idx[cur_diff_proto][p_diff_proto_info->num_source_chan_diff[cur_diff_proto]] = cur_transport_ch; - p_diff_proto_info->proto_fac[cur_diff_proto][p_diff_proto_info->num_source_chan_diff[cur_diff_proto]] = *proto_fac_ptr; - p_diff_proto_info->num_source_chan_diff[cur_diff_proto]++; + float diff = 0; + float *proto_fac_ptr = proto_fac + cur_diff_proto; + const float *proto_mtx_ptr = proto_mtx + cur_out_ch; + + for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) + { + diff += fabsf( *proto_fac_ptr - *proto_mtx_ptr ); + proto_fac_ptr += nchan_out_cov; + proto_mtx_ptr += nchan_out_cov; + } + + /* we already have this prototype, save the index */ + if ( diff < 0.1f ) + { + found = 1; + p_diff_proto_info->proto_index_diff[cur_out_ch] = cur_diff_proto; + break; + } } - proto_fac_ptr += nchan_out_cov; - } - } - return IVAS_ERR_OK; -} + /* new distinct prototype, add it */ + if ( found == 0 ) + { + const float *proto_mtx_ptr = proto_mtx + cur_out_ch; + int16_t cur_num_src_chan; + cur_num_src_chan = 0; + for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) + { + if ( *proto_mtx_ptr > EPSILON ) + { + cur_num_src_chan++; + } + proto_mtx_ptr += nchan_out_cov; + } -/*-------------------------------------------------------------------------* - * ivas_param_mc_bs_decode_parameter_values() - * - * reads and decodes a sequence of Parametric MC parameters from the bitstream - *-------------------------------------------------------------------------*/ + mvr2r_inc( proto_mtx + cur_out_ch, nchan_out_cov, proto_fac + p_diff_proto_info->num_protos_diff, nchan_out_cov, nchan_transport ); -static void ivas_param_mc_bs_decode_parameter_values( - uint16_t bit_buffer[], /* i : bitstream buffer */ - int16_t *bit_pos, /* i/o: current bitstream buffer position */ - const int16_t max_bits, /* i : maximum available bits in the buffer */ - int16_t *BER_detect, /* i/o: bit error detection flag */ - HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC, /* i : Parametric MC metadata information */ - HANDLE_PARAM_MC_PARAMETER_CODING_INFO hParamCodingInfo, /* i : Parametric MC parameter quantization and coding tables */ - const int16_t map_size_wo_lfe, /* i : number of parameters per band (w/o LFEs) */ - const int16_t map_size, /* i : number of parameters per band (total) */ - const int16_t num_lfe_bands, /* i : number of parameter bands with coded LFE */ - const int16_t band_step, /* i : parameter band step */ - const int16_t num_param_bands, /* i : number of parameter bands to decode */ - float *value_buffer /* o : output buffer for decoded parameter values */ -) -{ - int16_t range_coding; - int16_t sz_seq; - int16_t delta_coding; - int16_t delta_idx[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; - int16_t idx[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; - int16_t idx_prev; - int16_t idx_offset; - int16_t sz_alphabet; - int16_t i, j, k; - float dequant_seq[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; - float dequant_ordered[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; - int16_t n_lfe_idx; + p_diff_proto_info->proto_index_diff[cur_out_ch] = p_diff_proto_info->num_protos_diff; + p_diff_proto_info->num_protos_diff++; + max_num_src_chan = max( max_num_src_chan, cur_num_src_chan ); + } + } - range_coding = bit_buffer[( *bit_pos )++]; + /* set up the prototype info struct */ + if ( ( p_diff_proto_info->source_chan_idx = (int16_t **) malloc( p_diff_proto_info->num_protos_diff * sizeof( int16_t * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + if ( ( p_diff_proto_info->proto_fac = (float **) malloc( p_diff_proto_info->num_protos_diff * sizeof( float * ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } - /* Decoding the sequence */ - n_lfe_idx = map_size - map_size_wo_lfe; - sz_seq = num_param_bands * ( map_size_wo_lfe ) + num_lfe_bands * n_lfe_idx; + for ( cur_diff_proto = 0; cur_diff_proto < p_diff_proto_info->num_protos_diff; cur_diff_proto++ ) + { + float *proto_fac_ptr; - set_s( idx, 0, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); - set_zero( dequant_ordered, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); - set_zero( dequant_seq, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); + if ( ( p_diff_proto_info->source_chan_idx[cur_diff_proto] = (int16_t *) malloc( max_num_src_chan * sizeof( int16_t ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } + if ( ( p_diff_proto_info->proto_fac[cur_diff_proto] = (float *) malloc( max_num_src_chan * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Parametric MC\n" ) ); + } - if ( range_coding ) - { - delta_coding = bit_buffer[( *bit_pos )++]; + proto_fac_ptr = proto_fac + cur_diff_proto; + for ( cur_transport_ch = 0; cur_transport_ch < nchan_transport; cur_transport_ch++ ) + { + if ( *proto_fac_ptr > EPSILON ) + { + p_diff_proto_info->source_chan_idx[cur_diff_proto][p_diff_proto_info->num_source_chan_diff[cur_diff_proto]] = cur_transport_ch; + p_diff_proto_info->proto_fac[cur_diff_proto][p_diff_proto_info->num_source_chan_diff[cur_diff_proto]] = *proto_fac_ptr; + p_diff_proto_info->num_source_chan_diff[cur_diff_proto]++; + } + proto_fac_ptr += nchan_out_cov; + } + } - if ( delta_coding ) + return IVAS_ERR_OK; + } + + + /*-------------------------------------------------------------------------* + * ivas_param_mc_bs_decode_parameter_values() + * + * reads and decodes a sequence of Parametric MC parameters from the bitstream + *-------------------------------------------------------------------------*/ + + static void ivas_param_mc_bs_decode_parameter_values( + uint16_t bit_buffer[], /* i : bitstream buffer */ + int16_t * bit_pos, /* i/o: current bitstream buffer position */ + const int16_t max_bits, /* i : maximum available bits in the buffer */ + int16_t *BER_detect, /* i/o: bit error detection flag */ + HANDLE_IVAS_PARAM_MC_METADATA hMetadataPMC, /* i : Parametric MC metadata information */ + HANDLE_PARAM_MC_PARAMETER_CODING_INFO hParamCodingInfo, /* i : Parametric MC parameter quantization and coding tables */ + const int16_t map_size_wo_lfe, /* i : number of parameters per band (w/o LFEs) */ + const int16_t map_size, /* i : number of parameters per band (total) */ + const int16_t num_lfe_bands, /* i : number of parameter bands with coded LFE */ + const int16_t band_step, /* i : parameter band step */ + const int16_t num_param_bands, /* i : number of parameter bands to decode */ + float *value_buffer /* o : output buffer for decoded parameter values */ + ) + { + int16_t range_coding; + int16_t sz_seq; + int16_t delta_coding; + int16_t delta_idx[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; + int16_t idx[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; + int16_t idx_prev; + int16_t idx_offset; + int16_t sz_alphabet; + int16_t i, j, k; + float dequant_seq[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; + float dequant_ordered[PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE]; + int16_t n_lfe_idx; + + range_coding = bit_buffer[( *bit_pos )++]; + + /* Decoding the sequence */ + n_lfe_idx = map_size - map_size_wo_lfe; + sz_seq = num_param_bands * ( map_size_wo_lfe ) + num_lfe_bands * n_lfe_idx; + + set_s( idx, 0, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); + set_zero( dequant_ordered, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); + set_zero( dequant_seq, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); + + if ( range_coding ) { - idx_prev = hParamCodingInfo->quantizer_size / 2 + hParamCodingInfo->quantizer_size % 2 - 1; - sz_alphabet = 2 * hParamCodingInfo->quantizer_size - 1; - idx_offset = hParamCodingInfo->quantizer_size - 1; + delta_coding = bit_buffer[( *bit_pos )++]; - /* read range coded delta ICC indices */ - *bit_pos += ivas_param_mc_range_decoder_LC( &bit_buffer[*bit_pos], delta_idx, BER_detect, sz_seq, sz_alphabet, - hParamCodingInfo->cum_freq_delta, hParamCodingInfo->sym_freq_delta, PARAM_MC_RANGE_CODER_TOT_SHIFT, max_bits - *bit_pos ); + if ( delta_coding ) + { + idx_prev = hParamCodingInfo->quantizer_size / 2 + hParamCodingInfo->quantizer_size % 2 - 1; + sz_alphabet = 2 * hParamCodingInfo->quantizer_size - 1; + idx_offset = hParamCodingInfo->quantizer_size - 1; + + /* read range coded delta ICC indices */ + *bit_pos += ivas_param_mc_range_decoder_LC( &bit_buffer[*bit_pos], delta_idx, BER_detect, sz_seq, sz_alphabet, + hParamCodingInfo->cum_freq_delta, hParamCodingInfo->sym_freq_delta, PARAM_MC_RANGE_CODER_TOT_SHIFT, max_bits - *bit_pos ); + + /* delta index to absolute index */ + for ( j = 0; j < sz_seq; j++ ) + { + idx[j] = idx_prev + delta_idx[j] - idx_offset; + idx_prev = idx[j]; + } + } + else + { + /* read range coded absolute ICC indices */ + sz_alphabet = hParamCodingInfo->quantizer_size; + *bit_pos += ivas_param_mc_range_decoder_LC( &bit_buffer[*bit_pos], idx, BER_detect, sz_seq, sz_alphabet, + hParamCodingInfo->cum_freq, hParamCodingInfo->sym_freq, PARAM_MC_RANGE_CODER_TOT_SHIFT, max_bits - *bit_pos ); + } - /* delta index to absolute index */ + /* dequantize */ for ( j = 0; j < sz_seq; j++ ) { - idx[j] = idx_prev + delta_idx[j] - idx_offset; - idx_prev = idx[j]; + dequant_seq[j] = hParamCodingInfo->quantizer[idx[j]]; } } else { - /* read range coded absolute ICC indices */ - sz_alphabet = hParamCodingInfo->quantizer_size; - *bit_pos += ivas_param_mc_range_decoder_LC( &bit_buffer[*bit_pos], idx, BER_detect, sz_seq, sz_alphabet, - hParamCodingInfo->cum_freq, hParamCodingInfo->sym_freq, PARAM_MC_RANGE_CODER_TOT_SHIFT, max_bits - *bit_pos ); - } + set_zero( dequant_seq, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); - /* dequantize */ - for ( j = 0; j < sz_seq; j++ ) - { - dequant_seq[j] = hParamCodingInfo->quantizer[idx[j]]; + /* read uniformly coded ICCs */ + *bit_pos += ivas_param_mc_uniform_decoder( dequant_seq, sz_seq, hParamCodingInfo->quantizer, hParamCodingInfo->uni_bits, &bit_buffer[*bit_pos] ); } - } - else - { - set_zero( dequant_seq, PARAM_MC_MAX_PARAMETER_BANDS * PARAM_MC_MAX_VAL_MAP_SIZE ); - - /* read uniformly coded ICCs */ - *bit_pos += ivas_param_mc_uniform_decoder( dequant_seq, sz_seq, hParamCodingInfo->quantizer, hParamCodingInfo->uni_bits, &bit_buffer[*bit_pos] ); - } - /* reorder from sequential to parameter-band-wise */ - k = 0; - for ( j = 0; j < map_size_wo_lfe; ++j ) - { - for ( i = 0; i < num_param_bands; ++i ) + /* reorder from sequential to parameter-band-wise */ + k = 0; + for ( j = 0; j < map_size_wo_lfe; ++j ) { - dequant_ordered[j + i * map_size] = dequant_seq[k++]; + for ( i = 0; i < num_param_bands; ++i ) + { + dequant_ordered[j + i * map_size] = dequant_seq[k++]; + } } - } - for ( i = 0; i < num_lfe_bands; i++ ) - { - for ( j = 0; j < n_lfe_idx; j++ ) + for ( i = 0; i < num_lfe_bands; i++ ) { - dequant_ordered[map_size - n_lfe_idx + j + i * map_size] = dequant_seq[k++]; + for ( j = 0; j < n_lfe_idx; j++ ) + { + dequant_ordered[map_size - n_lfe_idx + j + i * map_size] = dequant_seq[k++]; + } } - } - if ( !( *BER_detect ) ) - { - j = 0; - for ( k = 0; k < hMetadataPMC->nbands_coded; k += band_step ) + if ( !( *BER_detect ) ) { - if ( hMetadataPMC->bAttackPresent || hMetadataPMC->param_frame_idx == hMetadataPMC->coding_band_mapping[k] ) + j = 0; + for ( k = 0; k < hMetadataPMC->nbands_coded; k += band_step ) { - mvr2r( dequant_ordered + j * map_size, value_buffer + k * map_size, map_size ); - j++; - } - if ( hMetadataPMC->bAttackPresent && k + 1 < hMetadataPMC->nbands_coded ) - { - mvr2r( value_buffer + k * map_size, value_buffer + ( k + 1 ) * map_size, map_size ); + if ( hMetadataPMC->bAttackPresent || hMetadataPMC->param_frame_idx == hMetadataPMC->coding_band_mapping[k] ) + { + mvr2r( dequant_ordered + j * map_size, value_buffer + k * map_size, map_size ); + j++; + } + if ( hMetadataPMC->bAttackPresent && k + 1 < hMetadataPMC->nbands_coded ) + { + mvr2r( value_buffer + k * map_size, value_buffer + ( k + 1 ) * map_size, map_size ); + } } } - } - return; -} + return; + } diff --git a/lib_dec/ivas_osba_dec.c b/lib_dec/ivas_osba_dec.c index 485dbfb1b..64e582d0a 100644 --- a/lib_dec/ivas_osba_dec.c +++ b/lib_dec/ivas_osba_dec.c @@ -134,7 +134,7 @@ ivas_error ivas_osba_dirac_td_binaural_jbm( { int16_t n; ivas_error error; - float output_separated_objects[BINAURAL_CHANNELS][L_FRAME48k]; // VE2SB: TBV + float output_separated_objects[BINAURAL_CHANNELS][L_FRAME48k]; float *p_sepobj[BINAURAL_CHANNELS]; int16_t channel_offset; int16_t slot_idx_start; diff --git a/lib_dec/ivas_sba_rendering_internal.c b/lib_dec/ivas_sba_rendering_internal.c index 06410aa54..1aece93bb 100644 --- a/lib_dec/ivas_sba_rendering_internal.c +++ b/lib_dec/ivas_sba_rendering_internal.c @@ -358,7 +358,7 @@ void ivas_ism2sba_sf( { int16_t i, j, k; float g1, *g2, *tc, *out, gain, prev_gain; - float buffer_tmp[HOA3_CHANNELS][L_FRAME48k]; // VE2SB: TBV + float buffer_tmp[HOA3_CHANNELS][L_FRAME48k]; int16_t sba_num_chans; assert( ( sba_order <= 3 ) && "Only order up to 3 is supported!" ); @@ -376,7 +376,11 @@ void ivas_ism2sba_sf( for ( j = 0; j < sba_num_chans; j++ ) { g2 = hIsmRendererData->interpolator + offset; +#ifdef UNIFIED_DECODING_PATHS_LEFTOVERS + tc = buffer_in[i]; +#else tc = buffer_in[i] + offset; +#endif out = buffer_tmp[j]; gain = hIsmRendererData->gains[i][j]; prev_gain = hIsmRendererData->prev_gains[i][j]; diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index c5958d8a9..4409cc0c9 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -965,16 +965,16 @@ typedef struct ivas_masa_ism_data_structure typedef struct decoder_tc_buffer_structure { - float *tc_buffer; /* the buffer itself */ - float *tc[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc */ // VE2SB: TBV - TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ - int16_t nchan_transport_jbm; /* number of TCs after TC decoding */ - int16_t nchan_transport_internal; /* total number of TC buffer channels, can include e.g. TD decorr data */ - int16_t nchan_buffer_full; /* number of channels to be fully buffered */ - int16_t n_samples_available; /* samples still available for rendering in the current frame */ - int16_t n_samples_buffered; /* full number of samples in the buffer (including spill to next frame) */ - int16_t n_samples_rendered; /* samples already rendered in the current frame */ - int16_t n_samples_granularity; /* render granularity */ + float *tc_buffer; /* the buffer itself */ + float *tc[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; /* pointers into the buffer to the beginning of each tc */ + TC_BUFFER_MODE tc_buffer_mode; /* mode of the buffer (no buffering, render buffering, out buffering) */ + int16_t nchan_transport_jbm; /* number of TCs after TC decoding */ + int16_t nchan_transport_internal; /* total number of TC buffer channels, can include e.g. TD decorr data */ + int16_t nchan_buffer_full; /* number of channels to be fully buffered */ + int16_t n_samples_available; /* samples still available for rendering in the current frame */ + int16_t n_samples_buffered; /* full number of samples in the buffer (including spill to next frame) */ + int16_t n_samples_rendered; /* samples already rendered in the current frame */ + int16_t n_samples_granularity; /* render granularity */ int16_t n_samples_flushed; int16_t subframe_nbslots[MAX_JBM_SUBFRAMES_5MS]; int16_t nb_subframes; diff --git a/lib_dec/lib_dec.c b/lib_dec/lib_dec.c index 7d1b9e455..5296daf5c 100644 --- a/lib_dec/lib_dec.c +++ b/lib_dec/lib_dec.c @@ -4945,10 +4945,12 @@ static ivas_error evs_dec_main( mvs2r( pcm_buf_local, p_output[ch], nOutSamples ); } } +#ifndef UNIFIED_DECODING_PATHS_LEFTOVERS else // ToDo: the 'else' branch can be removed once UNIFIED_DECODING_PATHS_LEFTOVERS is merged { ivas_jbm_dec_copy_tc_no_tsm( st_ivas, p_output, nOutSamples ); } +#endif #else if ( !st_ivas->hDecoderConfig->Opt_tsm ) { -- GitLab From de7ed670b9809f800115eccf4411e4d0ab90cb35 Mon Sep 17 00:00:00 2001 From: vaclav Date: Tue, 21 Oct 2025 14:09:59 +0200 Subject: [PATCH 2/3] fix --- lib_dec/ivas_ism_param_dec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib_dec/ivas_ism_param_dec.c b/lib_dec/ivas_ism_param_dec.c index 2239c602d..7ca049322 100644 --- a/lib_dec/ivas_ism_param_dec.c +++ b/lib_dec/ivas_ism_param_dec.c @@ -1194,10 +1194,10 @@ static void ivas_ism_param_dec_tc_gain_adjust( #else void ivas_ism_param_dec_tc_gain_ajust( #endif - Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ - const uint16_t nSamples, /* i : number of samples to be compensate */ - const uint16_t nFadeLength, /* i : length of the crossfade in samples */ - float *p_data_f[] /* i : synthesized core-coder transport channels/DirAC output*/ + Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ + const int16_t nSamples, /* i : number of samples to be compensate */ + const int16_t nFadeLength, /* i : length of the crossfade in samples */ + float *p_data_f[] /* i : synthesized core-coder transport channels/DirAC output*/ ) { -- GitLab From ff747703c9b84689fb25658c9a52d871b4f63dc9 Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 22 Oct 2025 17:47:18 +0200 Subject: [PATCH 3/3] fix comment --- lib_com/ivas_prot.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 583100d14..c25b82849 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -1141,7 +1141,7 @@ void ivas_ism_dec_digest_tc( void ivas_param_ism_dec_digest_tc( Decoder_Struct *st_ivas, /* i/o: IVAS decoder handle */ const uint16_t nCldfbSlots, /* i : number of CLDFB slots in transport channels */ - float *p_data_f[] /* i : synthesized core-coder transport channels/DirAC output */ + float *p_data_f[] /* i/o: synthesized core-coder transport channels/DirAC output */ ); void ivas_param_ism_dec_dequant_md( -- GitLab