From eba73d93e577e0cee6f2159e05d67921907532ad Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 28 Jan 2026 15:43:40 +0100 Subject: [PATCH] move functions --- Workspace_msvc/lib_dec.vcxproj | 3 +- Workspace_msvc/lib_dec.vcxproj.filters | 12 +- lib_dec/ivas_dec_fx.c | 1565 +++++++ ...ivas_jbm_dec_fx.c => ivas_dec_render_fx.c} | 3883 +++++------------ 4 files changed, 2755 insertions(+), 2708 deletions(-) create mode 100644 lib_dec/ivas_dec_fx.c rename lib_dec/{ivas_jbm_dec_fx.c => ivas_dec_render_fx.c} (64%) diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 81461f72d..ef31eea68 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -213,6 +213,8 @@ + + @@ -222,7 +224,6 @@ - diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index 170eada9a..59e2aa52d 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -326,9 +326,6 @@ decoder_all_c - - decoder_ivas_c - decoder_ivas_c @@ -362,9 +359,6 @@ decoder_ivas_c - - decoder_ivas_c - decoder_ivas_c @@ -509,6 +503,12 @@ decoder_all_c + + decoder_ivas_c + + + decoder_ivas_c + diff --git a/lib_dec/ivas_dec_fx.c b/lib_dec/ivas_dec_fx.c new file mode 100644 index 000000000..bd3eab3e4 --- /dev/null +++ b/lib_dec/ivas_dec_fx.c @@ -0,0 +1,1565 @@ +/****************************************************************************************************** + + (C) 2022-2026 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include "options.h" +#include "ivas_cnst.h" +#include "prot_fx.h" +#include "ivas_prot_fx.h" +#include "ivas_prot_rend_fx.h" +#include "ivas_rom_com.h" +#include "wmc_auto.h" +#ifdef DEBUGGING +#include "debug.h" +#endif + + +/*--------------------------------------------------------------------------* + * ivas_dec() + * + * Principal IVAS decoder routine, decoding of metadata and transport channels + *--------------------------------------------------------------------------*/ + +ivas_error ivas_dec_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + Word16 ch, n, output_frame, nchan_out, i, s; + Decoder_State *st; /* used for bitstream handling */ + Word32 *p_output_fx[MAX_TRANSPORT_CHANNELS]; /* buffer for output synthesis */ + Word16 nchan_remapped; + Word16 nb_bits_metadata[MAX_SCE + 1]; + Word32 output_Fs, ivas_total_brate; + AUDIO_CONFIG output_config; + ivas_error error; + Word16 num_md_sub_frames; + Word32 ism_total_brate; + + push_wmops( "ivas_dec" ); + /*----------------------------------------------------------------* + * Initialization of local vars after struct has been set + *----------------------------------------------------------------*/ + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + move32(); + nchan_out = st_ivas->hTcBuffer->nchan_transport_rend; + move16(); + output_config = st_ivas->hDecoderConfig->output_config; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + move32(); + + output_frame = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) ) /* output_Fs / FRAMES_PER_SEC */; + + /* set pointers to transport channels audio */ + FOR( n = 0; n < MAX_TRANSPORT_CHANNELS; n++ ) + { + p_output_fx[n] = st_ivas->p_output_fx[n]; + IF( p_output_fx[n] != NULL ) + { + set32_fx( p_output_fx[n], 0, L_FRAME48k ); + } + } + + /*----------------------------------------------------------------* + * Decoding + pre-rendering + *----------------------------------------------------------------*/ + + test(); + IF( EQ_32( st_ivas->ivas_format, STEREO_FORMAT ) ) + + { + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + move32(); + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* HP filtering */ + FOR( n = 0; n < s_min( nchan_out, st_ivas->nchan_transport ); n++ ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + } + ELSE IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) ) + { + /* Metadata decoding and configuration */ + test(); + IF( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) || EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) + { + ivas_ism_dtx_dec_fx( st_ivas, nb_bits_metadata ); + + IF( ( error = ivas_sce_dec_fx( st_ivas, st_ivas->hISMDTX.sce_id_dtx, &p_output_fx[st_ivas->hISMDTX.sce_id_dtx], output_frame, nb_bits_metadata[st_ivas->hISMDTX.sce_id_dtx] ) ) != IVAS_ERR_OK ) + { + return error; + } + + ivas_ism_dtx_limit_noise_energy_for_near_silence_fx( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport ); + + ivas_param_ism_dec_dequant_md_fx( st_ivas ); + } + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) + { + IF( NE_32( ( error = ivas_ism_metadata_dec_fx( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hParamIsmDec->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt, st_ivas->hSCE[0]->hCoreCoder[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + ivas_param_ism_dec_dequant_md_fx( st_ivas ); + } + ELSE /* ISM_MODE_DISC */ + { + IF( NE_32( ( error = ivas_ism_metadata_dec_fx( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt, st_ivas->hSCE[0]->hCoreCoder[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + FOR( n = 0; n < st_ivas->nchan_transport; n++ ) + { + /* for DTX frames, dominant object has already been decoded before */ + test(); + test(); + IF( !( ( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) || EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) && EQ_16( n, st_ivas->hISMDTX.sce_id_dtx ) ) ) + { + IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, n, &p_output_fx[n], output_frame, nb_bits_metadata[n] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* HP filtering */ + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + test(); + test(); + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) + { + ivas_ism_mono_dmx_fx( st_ivas, p_output_fx, output_frame ); + + Scale_sig32( p_output_fx[0], output_frame, Q11 - Q8 ); + } + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) && ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) ) + { + /* loudness correction */ + ivas_dirac_dec_binaural_sba_gain_fx( p_output_fx, st_ivas->nchan_transport, output_frame ); /*returns Q-1*/ + + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, 1 ); // Q-1 -> Q + } + } + } + ELSE IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) + { + set16_fx( nb_bits_metadata, 0, MAX_SCE ); + + /* read parameters from the bitstream */ + test(); + IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->hQMetaData != NULL ) + { + // st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; + IF( st_ivas->nSCE > 0 ) + { + st = st_ivas->hSCE[0]->hCoreCoder[0]; + } + ELSE + { + st = st_ivas->hCPE[0]->hCoreCoder[0]; + } + + IF( NE_32( ( error = ivas_masa_decode_fx( st_ivas, st, &nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) ) + { + IF( NE_32( ( error = ivas_spar_dec_fx( st_ivas, nb_bits_metadata ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + test(); + IF( EQ_16( st_ivas->nchan_transport, CPE_CHANNELS ) && GE_16( st_ivas->nCPE, 1 ) ) + { + st_ivas->hCPE[0]->brate_surplus = 0; + move32(); + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + move32(); + } + + /* core-decoding of transport channels */ + IF( EQ_16( st_ivas->nSCE, 1 ) ) + { + IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( GT_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* TCs remapping */ + nchan_remapped = st_ivas->nchan_transport; + move16(); + + test(); + test(); + test(); + test(); + test(); + IF( st_ivas->sba_dirac_stereo_flag ) + { + nchan_remapped = nchan_out; + move16(); + + IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) ) + { + FOR( i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, Q14 - Q11 ); // Q14 + } + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; + Word16 nchan_transport; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + move16(); + nchan_out = nchan_transport; + move16(); + + ivas_agc_dec_process_fx( st_ivas->hSpar->hAgcDec, ( p_output_fx ), ( p_output_fx ), st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + IF( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec_fx( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, p_output_fx ); + } + + ivas_spar_dec_gen_umx_mat_fx( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, ivas_total_brate, st_ivas->last_active_ivas_total_brate ) ); + } + + ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fx, output_frame ); + } + ELSE IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && ( GT_32( ivas_total_brate, IVAS_SID_5k2 ) || ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) && st_ivas->nCPE > 0 && EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) ) ) + { + nchan_remapped = 1; /* Only one channel transported */ + move16(); + } + + /* HP filtering */ + FOR( n = 0; n < nchan_remapped; n++ ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) ) + { + nchan_remapped = ivas_sba_remapTCs_fx( p_output_fx, st_ivas, output_frame ); + + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, ivas_total_brate, st_ivas->last_active_ivas_total_brate ); + + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; + Word16 Q_p_output = MAX_16, temp_min; + move16(); + Word16 nchan_transport; + + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + move16(); + nchan_out = nchan_transport; + move16(); + FOR( ch = 0; ch < nchan_transport; ch++ ) + { + temp_min = L_norm_arr( p_output_fx[ch], output_frame ); + Q_p_output = s_min( Q_p_output, temp_min ); + } + Q_p_output = sub( Q_p_output, 2 ); + if ( GT_16( Q_p_output, 20 ) ) + { + Q_p_output = 20; + move16(); + } + FOR( ch = 0; ch < nchan_transport; ch++ ) + { + Scale_sig32( p_output_fx[ch], output_frame, Q_p_output ); // Q(11+Q_p_output) + } + + ivas_sba_mix_matrix_determiner_fx( st_ivas->hSpar, p_output_fx, st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames, Q_p_output ); + FOR( Word16 c = 0; c < nchan_transport; c++ ) + { + Scale_sig32( p_output_fx[c], output_frame, 11 ); // Q11 + } + } + ELSE IF( NE_32( st_ivas->renderer_type, RENDERER_DISABLE ) ) + { + Word16 size = st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; + move16(); + if ( EQ_16( st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, 3 ) ) + size = add( size, 1 ); + + FOR( i = 0; i < size; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, Q14 - Q11 ); // Q14 + } + + ivas_spar_dec_agc_pca_fx( st_ivas, p_output_fx, output_frame ); + } + } + + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) + { + Word16 q_shift = 0; + move16(); + + ivas_masa_prerender_fx( st_ivas, p_output_fx, &q_shift, output_frame, nchan_remapped ); + + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, negate( q_shift ) ); + } + + test(); + /* external output */ + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && EQ_32( st_ivas->hMasa->config.input_ivas_format, MASA_ISM_FORMAT ) ) + { + FOR( n = 0; n < st_ivas->nchan_ism; n++ ) + { + set_zero_fx( p_output_fx[add( st_ivas->nchan_transport, n )], output_frame ); + } + + ivas_omasa_rearrange_channels_fx( p_output_fx, st_ivas->nchan_ism, output_frame ); + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) && ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) + { + /* loudness correction */ + ivas_dirac_dec_binaural_sba_gain_fx( p_output_fx, nchan_remapped, output_frame ); + + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, 1 ); // Q-1 -> Q + } + } + } + ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + Word16 nchan_ism, nchan_transport_ism; + Word16 dirac_bs_md_write_idx; + + set16_fx( nb_bits_metadata, 0, MAX_SCE + 1 ); + + /* Set the number of objects for the parametric rendering */ + dirac_bs_md_write_idx = 0; + move16(); + IF( st_ivas->hSpatParamRendCom != NULL ) + { + st_ivas->hSpatParamRendCom->numIsmDirections = 0; + move16(); + test(); + if ( NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + st_ivas->hSpatParamRendCom->numIsmDirections = st_ivas->nchan_ism; + move16(); + } + + dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */ + move16(); + } + + /* MASA metadata decoding */ + IF( NE_32( ( error = ivas_masa_decode_fx( st_ivas, st_ivas->hCPE[0]->hCoreCoder[0], &nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* Configuration of combined-format bit-budget distribution */ + ivas_set_surplus_brate_dec( st_ivas, &ism_total_brate ); + + st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream = &( st_ivas->bit_stream[( ism_total_brate / FRAMES_PER_SEC )] ); + + IF( NE_32( ( error = ivas_omasa_ism_metadata_dec_fx( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + FOR( n = 0; n < nchan_transport_ism; n++ ) + { + IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, n, &p_output_fx[st_ivas->nchan_transport + n], output_frame, nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* decode MASA channels */ + IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + IF( EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) + { + Copy32( p_output_fx[0], p_output_fx[1], output_frame ); /* Copy mono signal to stereo output channels */ + } + + FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + Word16 output_q = Q11; + move16(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) + { + ivas_ism_mono_dmx_fx( st_ivas, p_output_fx, output_frame ); + + output_q = Q8; + move16(); + } + ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + { + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + ivas_omasa_rearrange_channels_fx( p_output_fx, nchan_transport_ism, output_frame ); + } + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + /* Convert separate object to MASA, combine with the original MASA, and output combined MASA + empty objects. */ + ivas_omasa_combine_separate_ism_with_masa_fx( st_ivas, p_output_fx, &output_q, st_ivas->nchan_ism, output_frame ); + } + ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + /* Extract objects from MASA, output MASA + all objects (i.e., extracted and separated objects) */ + ivas_omasa_render_objects_from_mix_fx( st_ivas, p_output_fx, st_ivas->nchan_ism, output_frame, &output_q ); + } + } + + IF( NE_16( output_q, Q11 ) ) + { + FOR( n = 0; n < s_max( getNumChanSynthesis( st_ivas ), nchan_transport_ism + st_ivas->nchan_transport ); n++ ) + { + Scale_sig32( p_output_fx[n], output_frame, sub( Q11, output_q ) ); // Q11 + } + st_ivas->hCPE[0]->q_output_mem_fx[0] = output_q; + st_ivas->hCPE[0]->q_output_mem_fx[1] = output_q; + } + } + ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) + { + Word16 nchan_ism, sba_ch_idx; + + set16_fx( nb_bits_metadata, 0, MAX_SCE + 1 ); + nchan_ism = st_ivas->nchan_ism; + move16(); + IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + /* set ISM parameters and decode ISM metadata in OSBA format */ + IF( NE_32( ( error = ivas_osba_ism_metadata_dec_fx( st_ivas, ivas_total_brate, &nchan_ism, &nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + { + return error; + } + sba_ch_idx = st_ivas->nchan_ism; + move16(); + } + ELSE + { + nb_bits_metadata[1] = add( nb_bits_metadata[1], NO_BITS_MASA_ISM_NO_OBJ ); + sba_ch_idx = 0; + move16(); + move16(); + } + + /* SBA metadata decoding */ + IF( NE_32( ( error = ivas_spar_dec_fx( st_ivas, nb_bits_metadata ) ), IVAS_ERR_OK ) ) + { + return error; + } + + test(); + IF( EQ_16( st_ivas->nchan_transport, CPE_CHANNELS ) && GE_16( st_ivas->nCPE, 1 ) ) + { + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + move32(); + } + + /* core-decoding of transport channels */ + IF( EQ_16( st_ivas->nSCE, 1 ) ) + { + IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, add( nb_bits_metadata[0], nb_bits_metadata[1] ) ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( GT_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + IF( st_ivas->sba_dirac_stereo_flag ) + { + FOR( i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) + { + Scale_sig32( p_output_fx[i + sba_ch_idx], output_frame, Q14 - Q11 ); // Q14 + } + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; + Word16 nchan_transport; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + move16(); + nchan_out = nchan_transport; + move16(); + ivas_agc_dec_process_fx( st_ivas->hSpar->hAgcDec, ( p_output_fx + sba_ch_idx ), ( p_output_fx + sba_ch_idx ), st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + IF( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec_fx( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, &p_output_fx[sba_ch_idx] ); + } + + ivas_spar_dec_gen_umx_mat_fx( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ) ); + + ivas_sba_dirac_stereo_dec_fx( st_ivas, &p_output_fx[sba_ch_idx], output_frame ); + } + + /* HP filtering */ + FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + nchan_remapped = ivas_sba_remapTCs_fx( &p_output_fx[sba_ch_idx], st_ivas, output_frame ); + + test(); + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ); + SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; + Word16 nchan_transport; + // num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; + nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; + move16(); + nchan_out = nchan_transport; + move16(); + Word16 Q_p_output; + Word16 min_norm = 31; + move16(); + + FOR( ch = 0; ch < nchan_transport; ++ch ) + { + Word16 norm = L_norm_arr( p_output_fx[sba_ch_idx + ch], output_frame ); // Normalize per channel + min_norm = s_min( norm, min_norm ); + } + + Q_p_output = s_max( 3, sub( min_norm, 1 ) ); + + Q_p_output = s_min( Q_p_output, 19 ); // to restrict Q-factor of p_ouptut to Q30 + FOR( ch = 0; ch < nchan_transport; ch++ ) + { + Scale_sig32( p_output_fx[sba_ch_idx + ch], output_frame, Q_p_output ); // Q_p_output + Q11 + } + Q_p_output = add( Q11, Q_p_output ); + hSpar->hMdDec->Q_mixer_mat = 31; + move16(); + + ivas_sba_mix_matrix_determiner_fx( st_ivas->hSpar, &p_output_fx[sba_ch_idx], st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames, sub( Q_p_output, Q11 ) ); + FOR( Word16 c = 0; c < nchan_transport; c++ ) + { + Scale_sig32( p_output_fx[sba_ch_idx + c], output_frame, Q11 ); // Q11 + } + } + ELSE IF( NE_32( st_ivas->renderer_type, RENDERER_DISABLE ) && st_ivas->sba_dirac_stereo_flag == 0 ) + { + Word16 size = add( st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, sba_ch_idx ); + if ( EQ_16( size, 3 ) ) + { + size = add( size, 1 ); + } + + FOR( i = sba_ch_idx; i < size; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, ( Q14 - Q11 ) ); // Q14 + } + + ivas_spar_dec_agc_pca_fx( st_ivas, &p_output_fx[sba_ch_idx], output_frame ); + } + + test(); + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + /* loudness correction */ + ivas_dirac_dec_binaural_sba_gain_fx( &p_output_fx[sba_ch_idx], nchan_remapped, output_frame ); /*returns Q-1*/ + + FOR( i = 0; i < nchan_remapped; i++ ) + { + Scale_sig32( p_output_fx[i], output_frame, 1 ); // Q-1 -> Q + } + } + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + ivas_ism_mono_dmx_fx( st_ivas, p_output_fx, output_frame ); + + Scale_sig32( p_output_fx[0], output_frame, Q11 - Q8 ); // Q11 + + /* add W */ + FOR( n = 0; n < nchan_out; n++ ) + { + v_add_32( p_output_fx[n], p_output_fx[n + s_max( nchan_out, nchan_ism )], p_output_fx[n], output_frame ); + } + } + } + ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) ) + { + IF( st_ivas->nSCE > 0 ) + { + st = st_ivas->hSCE[0]->hCoreCoder[0]; + } + ELSE + { + st = st_ivas->hCPE[0]->hCoreCoder[0]; + } + + IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) ) + { + /* LFE channel decoder */ + ivas_lfe_dec_fx( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output_fx[LFE_CHANNEL] ); + + Scale_sig32( p_output_fx[LFE_CHANNEL], output_frame, Q11 - Q9 ); // Q11 + + IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* HP filtering */ + FOR( n = 0; n < st_ivas->nchan_transport; n++ ) + { + IF( NE_16( n, LFE_CHANNEL ) ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + } + + test(); + test(); + test(); + IF( NE_32( st_ivas->transport_config, st_ivas->intern_config ) && ( NE_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || NE_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || NE_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) + { + IF( GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) + { + ivas_mc2sba_fx( st_ivas->hTransSetup, p_output_fx, p_output_fx, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE_FX ); + } + } + + test(); + test(); + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_MC ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ) ) + { + IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) + { + s = Q16 - Q11; + move16(); + s = sub( s, find_guarded_bits_fx( st_ivas->nchan_transport ) ); + FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, st_ivas->nchan_transport ); ++i ) + { + Scale_sig32( p_output_fx[i], output_frame, s ); // Q(11+s) + } + ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, output_frame, p_output_fx, p_output_fx ); + FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, st_ivas->nchan_transport ); ++i ) + { + Scale_sig32( p_output_fx[i], output_frame, negate( s ) ); // Q11 + } + } + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) + { + ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, output_frame, st_ivas->hOutSetup.ambisonics_order, 0 ); + } + } + } + ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + { + /* LFE channel decoder */ + ivas_lfe_dec_fx( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output_fx[LFE_CHANNEL] ); + + Scale_sig32( p_output_fx[LFE_CHANNEL], output_frame, Q11 - Q9 ); // Q11 + + ivas_mc_paramupmix_dec_read_BS( st_ivas, st, st_ivas->hMCParamUpmix, &nb_bits_metadata[0] ); + + IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* HP filtering */ + FOR( n = 0; n < st_ivas->nchan_transport; n++ ) + { + IF( NE_16( n, LFE_CHANNEL ) ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + } + + /* Rendering */ + test(); + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) && ( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) ) + { + /* Compensate loudness for not doing full upmix */ + FOR( n = 4; n < 8; n++ ) + { + Scale_sig32( p_output_fx[n], output_frame, 1 ); + } + + test(); + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) + { + s = Q16 - Q11; + move16(); + Word16 nchan_transport; + nchan_transport = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 ); + s = sub( s, find_guarded_bits_fx( nchan_transport ) ); + FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, nchan_transport ); ++i ) + { + Scale_sig32( p_output_fx[i], output_frame, s ); + } + + ivas_ls_setup_conversion_fx( st_ivas, nchan_transport, output_frame, p_output_fx, p_output_fx ); + + FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, nchan_transport ); ++i ) + { + Scale_sig32( p_output_fx[i], output_frame, negate( s ) ); + } + } + } + } + ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMMC ) ) + { + /* read Parametric MC parameters from the bitstream */ + ivas_param_mc_dec_read_BS_fx( ivas_total_brate, st, st_ivas->hParamMC, &nb_bits_metadata[0] ); + + IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( GT_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + + /* HP filtering */ + FOR( n = 0; n < st_ivas->nchan_transport; n++ ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + /* Rendering */ + test(); + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) + { + ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, output_frame, p_output_fx, p_output_fx ); + } + } + ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + IF( st_ivas->hOutSetup.separateChannelEnabled ) + { + st = st_ivas->hCPE[0]->hCoreCoder[0]; /* Metadata is always with CPE in the case of separated channel */ + } + + /* read McMASA parameters from the bitstream */ + IF( NE_32( ( error = ivas_masa_decode_fx( st_ivas, st, &nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + IF( st_ivas->hOutSetup.separateChannelEnabled ) + { + /* Decode the transport audio signals */ + IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* Identify the index of the separated channel, always LFE_CHANNEL-1 here */ + n = LFE_CHANNEL - 1; + move16(); + + /* Decode the separated channel to output[n] to be combined with the synthesized channels */ + IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[n], output_frame, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + /* Delay the separated channel to sync with CLDFB delay of the DirAC synthesis, and synthesize the LFE signal. */ + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1 ) || + EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe > 0 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + { + ivas_lfe_synth_with_filters_fx( st_ivas->hMasa->hMasaLfeSynth, p_output_fx, output_frame, n, LFE_CHANNEL ); + } + ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe == 0 ) + { + /* Delay the separated channel to sync with the DirAC rendering */ + delay_signal32_fx( p_output_fx[n], output_frame, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size ); + } + } + ELSE + { + IF( EQ_16( st_ivas->nSCE, 1 ) ) + { + IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } + + IF( st_ivas->sba_dirac_stereo_flag != 0 ) /* use the flag to trigger the DFT upmix */ + { + ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fx, output_frame ); + } + + /* HP filtering */ + FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + } + + IF( EQ_32( st_ivas->renderer_type, RENDERER_MCMASA_MONO_STEREO ) ) + { + ivas_mono_stereo_downmix_mcmasa_fx( st_ivas, p_output_fx, output_frame ); + } + } + } + + /*----------------------------------------------------------------* + * Common updates + *----------------------------------------------------------------*/ + + IF( !st_ivas->bfi ) /* do not update if first frame(s) are lost or NO_DATA */ + { + st_ivas->hDecoderConfig->last_ivas_total_brate = ivas_total_brate; + move32(); + IF( LE_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + st_ivas->last_active_ivas_total_brate = st_ivas->last_active_ivas_total_brate; + move32(); + } + ELSE + { + st_ivas->last_active_ivas_total_brate = ivas_total_brate; + move32(); + } + } + + test(); + test(); + if ( LT_16( st_ivas->ini_frame, MAX_FRAME_COUNTER ) && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) ) /* keep "st_ivas->ini_frame = 0" until first good received frame */ + { + st_ivas->ini_frame = add( st_ivas->ini_frame, 1 ); + move16(); + } + + test(); + test(); + if ( LT_16( st_ivas->ini_active_frame, MAX_FRAME_COUNTER ) && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && GT_32( ivas_total_brate, IVAS_SID_5k2 ) ) /* needed in MASA decoder in case the first active frame is BFI, and there were SID-frames decoded before */ + { + st_ivas->ini_active_frame = add( st_ivas->ini_active_frame, 1 ); + move16(); + } + + st_ivas->last_ivas_format = st_ivas->ivas_format; + move32(); + pop_wmops(); + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_get_num_tc_channels() + * + * Get the number of transport channels provided to the renderer + *--------------------------------------------------------------------------*/ + +Word16 ivas_dec_get_num_tc_channels_fx( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +) +{ + Word16 num_tc; + Word32 ivas_total_brate; + AUDIO_CONFIG output_config; + + IF( EQ_16( st_ivas->renderer_type, RENDERER_DISABLE ) ) + { + num_tc = st_ivas->hDecoderConfig->nchan_out; + move16(); + } + ELSE + { + num_tc = st_ivas->nchan_transport; + move16(); + } + output_config = st_ivas->hDecoderConfig->output_config; + move16(); + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + move32(); + + test(); + test(); + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, MONO_FORMAT ) ) + { + num_tc = 1; + move16(); + } + ELSE IF( EQ_32( st_ivas->ivas_format, STEREO_FORMAT ) && EQ_16( st_ivas->hDecoderConfig->nchan_out, 1 ) ) + { + num_tc = 1; + move16(); + } + ELSE IF( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) ) + { + if ( EQ_16( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) + { + num_tc = 1; + move16(); + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) || EQ_16( st_ivas->ivas_format, MASA_FORMAT ) ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + move16(); + } + ELSE IF( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && ( GT_32( ivas_total_brate, IVAS_SID_5k2 ) || ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) && GT_16( st_ivas->nCPE, 0 ) && st_ivas->hCPE[0] != NULL && EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) ) ) + { + num_tc = 1; /* Only one channel transported */ + move16(); + } + + test(); + test(); + test(); + test(); + IF( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) && EQ_16( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && EQ_16( st_ivas->nchan_transport, 2 ) && LT_32( st_ivas->hDecoderConfig->ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && GT_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_SID_5k2 ) ) + { + num_tc = CPE_CHANNELS; + move16(); + } + IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) ) + { + if ( EQ_16( num_tc, 3 ) ) + { + num_tc = add( num_tc, 1 ); + } + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + IF( NE_16( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + { + test(); + IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + { + num_tc = add( num_tc, 1 ); + } + ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + num_tc = add( num_tc, st_ivas->nchan_ism ); + } + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) + { + if ( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + move16(); + } + + if ( EQ_16( num_tc, 3 ) ) + { + num_tc = add( num_tc, 1 ); + } + if ( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + num_tc = add( num_tc, st_ivas->nchan_ism ); + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) + { + IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_MONO ) ) + { + num_tc = 1; + move16(); + } + ELSE IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) + { + num_tc = 2; + move16(); + } + ELSE IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCT ) ) + { + /* do all static dmx already in the TC decoder if less channels than transported... */ + test(); + test(); + test(); + test(); + test(); + IF( NE_16( st_ivas->transport_config, st_ivas->intern_config ) && ( EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) + { + if ( GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) + { + num_tc = add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ); + } + } + ELSE IF( ( EQ_16( st_ivas->renderer_type, RENDERER_MC ) || EQ_16( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ) ) + { + num_tc = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); + } + } + ELSE IF( EQ_16( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + { + num_tc = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; + move16(); + } + ELSE IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) + { + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + num_tc = add( num_tc, 1 ); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + if ( st_ivas->hOutSetup.separateChannelEnabled && ( EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || + EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe > 0 ) ) ) + { + /* LFE is synthesized in TD with the TCs*/ + num_tc = add( num_tc, 1 ); + } + } + } + + return num_tc; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_get_tc_buffer_mode() + * + * + *--------------------------------------------------------------------------*/ + +TC_BUFFER_MODE ivas_dec_get_tc_buffer_mode_fx( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + TC_BUFFER_MODE buffer_mode; + + buffer_mode = TC_BUFFER_MODE_BUFFER; + move16(); + + SWITCH( st_ivas->renderer_type ) + { + /* all renderers where we are done after TC decoding (might include DMX to mono/stereo */ + case RENDERER_DISABLE: + case RENDERER_MCMASA_MONO_STEREO: + case RENDERER_OSBA_STEREO: + case RENDERER_MONO_DOWNMIX: + buffer_mode = TC_BUFFER_MODE_BUFFER; + move16(); + BREAK; + case RENDERER_NON_DIEGETIC_DOWNMIX: + case RENDERER_TD_PANNING: + case RENDERER_BINAURAL_OBJECTS_TD: + case RENDERER_BINAURAL_FASTCONV: + case RENDERER_BINAURAL_FASTCONV_ROOM: + case RENDERER_BINAURAL_PARAMETRIC: + case RENDERER_BINAURAL_PARAMETRIC_ROOM: + case RENDERER_STEREO_PARAMETRIC: + case RENDERER_DIRAC: + case RENDERER_PARAM_ISM: + case RENDERER_BINAURAL_MIXER_CONV: + case RENDERER_BINAURAL_MIXER_CONV_ROOM: + case RENDERER_OMASA_OBJECT_EXT: + case RENDERER_OMASA_MIX_EXT: + case RENDERER_OSBA_AMBI: + case RENDERER_OSBA_LS: + buffer_mode = TC_BUFFER_MODE_RENDERER; + move16(); + BREAK; + case RENDERER_MC_PARAMMC: + IF( EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_MONO_STEREO ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; /* TCs are already the DMX to mono or stereo */ + move16(); + } + ELSE + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + move16(); + } + BREAK; + case RENDERER_MC: + if ( NE_16( ivas_dec_get_num_tc_channels_fx( st_ivas ), st_ivas->hDecoderConfig->nchan_out ) ) + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + move16(); + } + BREAK; + case RENDERER_SBA_LINEAR_ENC: + test(); + test(); + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) && ( EQ_32( st_ivas->renderer_type, RENDERER_MC ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( ( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ) ), ( add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ) ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + move16(); + } + ELSE + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + move16(); + } + BREAK; + case RENDERER_SBA_LINEAR_DEC: + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) && ( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + move16(); + } + ELSE + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + move16(); + } + BREAK; + } + + return buffer_mode; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_audio_allocate() + * + * allocate and initialize TC audio buffer + *--------------------------------------------------------------------------*/ + +static ivas_error ivas_dec_tc_audio_allocate_fx( + DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: TC buffer handle */ + const Word32 output_Fs, /* i : output sampling rate */ + const Word16 Opt_tsm /* i : TSM option flag */ +) +{ + Word16 nsamp_to_allocate; + Word16 ch_idx, n_samp_full, n_samp_residual, offset; + + IF( Opt_tsm ) + { + n_samp_full = NS2SA_FX2( output_Fs, MAX_JBM_L_FRAME_NS ); + n_samp_full = s_max( n_samp_full, L_FRAME48k ); /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': ensure minimal length */ + n_samp_residual = sub( hTcBuffer->n_samples_granularity, 1 ); + } + ELSE + { + n_samp_full = extract_l( Mpy_32_32( output_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ); + n_samp_residual = 0; + move16(); + } + + nsamp_to_allocate = imult1616( s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ), n_samp_full ); + + IF( Opt_tsm ) + { + /* note: this is stack memory buffer for TC decoded and also time-scale modified audio signals */ + IF( ( hTcBuffer->tc_buffer_fx = (Word32 *) malloc( nsamp_to_allocate * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + } + set_zero_fx( hTcBuffer->tc_buffer_fx, nsamp_to_allocate ); + + offset = 0; + move16(); + FOR( ch_idx = 0; ch_idx < s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; + offset = add( offset, n_samp_full ); + } + FOR( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + + /* memory buffer for TC audio samples not rendered in the previous frame */ + FOR( ch_idx = 0; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) + { + IF( ( hTcBuffer->tc_buffer_old_fx[ch_idx] = (Word32 *) malloc( n_samp_residual * sizeof( Word32 ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + } + set_zero_fx( hTcBuffer->tc_buffer_old_fx[ch_idx], n_samp_residual ); + } + FOR( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + } + } + else + { + hTcBuffer->tc_buffer_fx = NULL; + + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + } + } + + hTcBuffer->tc_buffer2_fx = NULL; + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_buffer_open() + * + * Open and initialize transport channel buffer handle + *--------------------------------------------------------------------------*/ + +ivas_error ivas_dec_tc_buffer_open_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const Word16 nchan_transport_rend, /* i : number of TCs for rendering */ + const Word16 nchan_transport_internal, /* i : number of totally buffered channels */ + const Word16 nchan_full, /* i : number of channels to fully store */ + const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ +) +{ + DECODER_TC_BUFFER_HANDLE hTcBuffer; + Word16 nMaxSlotsPerSubframe; + ivas_error error; + Word16 tmp, tmp_e; + + /*-----------------------------------------------------------------* + * prepare library opening + *-----------------------------------------------------------------*/ + + IF( ( hTcBuffer = (DECODER_TC_BUFFER_HANDLE) malloc( sizeof( DECODER_TC_BUFFER ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + } + + hTcBuffer->tc_buffer_mode = tc_buffer_mode; + move16(); + hTcBuffer->nchan_transport_rend = nchan_transport_rend; + move16(); + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + move16(); + hTcBuffer->nchan_buffer_full = nchan_full; + move16(); + hTcBuffer->n_samples_granularity = n_samples_granularity; + move16(); + hTcBuffer->n_samples_available = 0; + move16(); + hTcBuffer->n_samples_buffered = 0; + move16(); + hTcBuffer->n_samples_rendered = 0; + move16(); + hTcBuffer->slots_rendered = 0; + move16(); + hTcBuffer->subframes_rendered = 0; + move16(); + hTcBuffer->n_samples_discard = 0; + move16(); + hTcBuffer->n_samples_flushed = 0; + move16(); + hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + move16(); + + /* nMaxSlotsPerSubframe = (Word16)(st_ivas->hDecoderConfig->output_Fs / (FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES)) / st_ivas->hTcBuffer->n_samples_granularity; */ + tmp = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, ONE_BY_SUBFR_PER_SEC_Q15 ) ); + tmp = BASOP_Util_Divide1616_Scale( tmp, hTcBuffer->n_samples_granularity, &tmp_e ); + nMaxSlotsPerSubframe = shr( tmp, sub( 15, tmp_e ) ); /* Q0 */ + + hTcBuffer->num_slots = mult0( nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + move16(); + + set16_fx( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set16_fx( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + + IF( ( error = ivas_dec_tc_audio_allocate_fx( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + { + return error; + } + + st_ivas->hTcBuffer = hTcBuffer; + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_jbm_dec_tc_audio_deallocate() + * + * deallocate TC audio buffer + *--------------------------------------------------------------------------*/ + +static void ivas_jbm_dec_tc_audio_deallocate_fx( + DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: JBM TSM buffer handle */ +) +{ + Word16 ch_idx; + + IF( hTcBuffer != NULL ) + { + IF( hTcBuffer->tc_buffer_fx != NULL ) + { + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_fx[ch_idx] = NULL; + } + + free( hTcBuffer->tc_buffer_fx ); + hTcBuffer->tc_buffer_fx = NULL; + } + + FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + IF( hTcBuffer->tc_buffer_old_fx[ch_idx] != NULL ) + { + free( hTcBuffer->tc_buffer_old_fx[ch_idx] ); + hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + } + } + + IF( hTcBuffer->tc_buffer2_fx != NULL ) + { + free( hTcBuffer->tc_buffer2_fx ); + hTcBuffer->tc_buffer2_fx = NULL; + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_buffer_close() + * + * Close transport channel buffer handle + *--------------------------------------------------------------------------*/ + +void ivas_dec_tc_buffer_close_fx( + DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ +) +{ + IF( *phTcBuffer != NULL ) + { + ivas_jbm_dec_tc_audio_deallocate_fx( *phTcBuffer ); + + free( *phTcBuffer ); + *phTcBuffer = NULL; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_buffer_reconfigure() + * + * Reconfigure transport channel buffer handle + *--------------------------------------------------------------------------*/ + +ivas_error ivas_dec_tc_buffer_reconfigure_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ + const Word16 nchan_transport_rend, /* i : new number of TCs for rendering */ + const Word16 nchan_transport_internal, /* i : new number of totally buffered channels */ + const Word16 nchan_full, /* i : new number of channels to fully store */ + const Word16 n_samples_granularity /* i : new granularity of the renderer/buffer */ +) +{ + Word16 ch_idx, num_tc_buffer_mem, n_samples_still_available; + Word32 tc_buffer_mem[MAX_INTERN_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES - 1]; + ivas_error error; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + hTcBuffer = st_ivas->hTcBuffer; + move16(); + + num_tc_buffer_mem = 0; + move16(); + n_samples_still_available = 0; + move16(); + + IF( st_ivas->hDecoderConfig->Opt_tsm ) + { + /* save samples of the TC buffer from the previous frame */ + num_tc_buffer_mem = s_min( hTcBuffer->nchan_transport_internal, nchan_transport_internal ); + n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); + + /* what is remaining from last frame needs always be smaller than the new granularity */ + assert( n_samples_still_available < n_samples_granularity ); + + FOR( ch_idx = 0; ch_idx < num_tc_buffer_mem; ch_idx++ ) + { + Copy32( hTcBuffer->tc_buffer_old_fx[ch_idx] + hTcBuffer->n_samples_flushed, tc_buffer_mem[ch_idx], n_samples_still_available ); + } + } + + /* if granularity changes, adapt subframe_nb_slots */ + IF( NE_16( n_samples_granularity, hTcBuffer->n_samples_granularity ) ) + { + Word16 nMaxSlotsPerSubframeNew; + Word16 tmp, tmp_e; + + /* nMaxSlotsPerSubframeNew = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / n_samples_granularity; */ + tmp = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, ONE_BY_SUBFR_PER_SEC_Q15 ) ); + tmp = BASOP_Util_Divide1616_Scale( tmp, n_samples_granularity, &tmp_e ); + nMaxSlotsPerSubframeNew = shr( tmp, sub( 15, tmp_e ) ); /* Q0 */ + + /* if samples were flushed, take that into account here */ + test(); + IF( LT_16( n_samples_granularity, hTcBuffer->n_samples_granularity ) && hTcBuffer->n_samples_flushed > 0 ) + { + hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = idiv1616( hTcBuffer->n_samples_flushed, n_samples_granularity ); + hTcBuffer->n_samples_flushed = 0; + move16(); + move16(); + } + ELSE + { + hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = nMaxSlotsPerSubframeNew; + move16(); + } + } + + hTcBuffer->tc_buffer_mode = tc_buffer_mode; + move16(); + hTcBuffer->nchan_transport_rend = nchan_transport_rend; + move16(); + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + move16(); + hTcBuffer->nchan_buffer_full = nchan_full; + move16(); + hTcBuffer->n_samples_granularity = n_samples_granularity; + move16(); + + /* reallocate TC audio buffers */ + + ivas_jbm_dec_tc_audio_deallocate_fx( hTcBuffer ); + + IF( ( error = ivas_dec_tc_audio_allocate_fx( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* propagate samples of the TC buffer from the previous frame */ + FOR( ch_idx = 0; ch_idx < num_tc_buffer_mem; ch_idx++ ) + { + Copy32( tc_buffer_mem[ch_idx], hTcBuffer->tc_buffer_old_fx[ch_idx], n_samples_still_available ); + } + + return IVAS_ERR_OK; +} diff --git a/lib_dec/ivas_jbm_dec_fx.c b/lib_dec/ivas_dec_render_fx.c similarity index 64% rename from lib_dec/ivas_jbm_dec_fx.c rename to lib_dec/ivas_dec_render_fx.c index 55788b01c..5b685edd4 100644 --- a/lib_dec/ivas_jbm_dec_fx.c +++ b/lib_dec/ivas_dec_render_fx.c @@ -67,814 +67,824 @@ static Word16 ceil_fx16( return ret; } + +/*--------------------------------------------------------------------------* + * ivas_dec_feed_tc_to_renderer() + * + * Feed decoded transport channels to the IVAS renderer routine + * + digest TC channels in ParamISM and ParamMC + *--------------------------------------------------------------------------*/ + +void ivas_dec_feed_tc_to_renderer_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 nSamplesForRendering, /* i : number of TC samples available for rendering */ + Word16 *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ +) +{ + Word32 tmp_buf_fx[MAX_JBM_L_FRAME48k]; + Word32 *p_data_fx[FOA_CHANNELS + MAX_NUM_OBJECTS]; + Word16 n, n_render_timeslots, n_ch_cldfb; + Word16 ch, offset, len_offset; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + hTcBuffer = st_ivas->hTcBuffer; + n_ch_cldfb = sub( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + move16(); + + hTcBuffer->q_tc_fx = Q11; + move16(); + + IF( st_ivas->hDecoderConfig->Opt_tsm ) + { + Word16 n_samples_still_available; + Word16 n_ch_full_copy, n_ch_res_copy; + + n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); + hTcBuffer->n_samples_buffered = add( add( n_samples_still_available, nSamplesForRendering ), hTcBuffer->n_samples_discard ); + hTcBuffer->n_samples_available = i_mult( hTcBuffer->n_samples_granularity, idiv1616( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_granularity ) ); + *nSamplesResidual = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_available ); + move16(); + move16(); + move16(); + n_ch_full_copy = s_min( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + n_ch_res_copy = sub( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + + /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': + in case of 'length(hTcBuffer->tc[]) < length(p_output_f[])', reset of TC buffer + pointers is needed after ivas_buffer_interleaved_to_deinterleaved() */ + len_offset = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ); + IF( LT_16( len_offset, L_FRAME48k ) ) + { + offset = 0; + move16(); + FOR( ch = 0; ch < s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch++ ) + { + hTcBuffer->tc_fx[ch] = &hTcBuffer->tc_buffer_fx[offset]; + st_ivas->p_output_fx[ch] = hTcBuffer->tc_fx[ch]; + offset = add( offset, len_offset ); + } + } + + FOR( ch = 0; ch < n_ch_full_copy; ch++ ) + { + Copy32( hTcBuffer->tc_fx[ch], tmp_buf_fx, nSamplesForRendering ); + set_zero_fx( hTcBuffer->tc_fx[ch], hTcBuffer->n_samples_discard ); + Copy32( hTcBuffer->tc_buffer_old_fx[ch], hTcBuffer->tc_fx[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); + Copy32( tmp_buf_fx, hTcBuffer->tc_fx[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); + Copy32( tmp_buf_fx + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old_fx[ch], *nSamplesResidual ); + } + + IF( n_ch_res_copy > 0 ) + { + FOR( ; ch < hTcBuffer->nchan_transport_rend; ch++ ) + { + p_data_fx[ch] = hTcBuffer->tc_fx[ch]; + Copy32( hTcBuffer->tc_fx[ch], tmp_buf_fx, nSamplesForRendering ); + Copy32( hTcBuffer->tc_buffer_old_fx[ch], p_data_fx[ch], n_samples_still_available ); + Copy32( tmp_buf_fx, p_data_fx[ch] + n_samples_still_available, sub( nSamplesForRendering, *nSamplesResidual ) ); + Copy32( tmp_buf_fx + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old_fx[ch], *nSamplesResidual ); + } + } + + n_render_timeslots = idiv1616( st_ivas->hTcBuffer->n_samples_available, st_ivas->hTcBuffer->n_samples_granularity ); + } + ELSE + { + FOR( n = 0; n < n_ch_cldfb; n++ ) + { + p_data_fx[n] = &st_ivas->p_output_fx[n][0]; + move16(); + } + + ch = s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + FOR( n = 0; n < ch; n++ ) + { + hTcBuffer->tc_fx[n] = st_ivas->p_output_fx[n]; /* note: buffers needed in the TD decorellator */ + move16(); + } + + hTcBuffer->n_samples_buffered = nSamplesForRendering; + hTcBuffer->n_samples_available = hTcBuffer->n_samples_buffered; + *nSamplesResidual = 0; + move16(); + move16(); + move16(); + + n_render_timeslots = DEFAULT_JBM_CLDFB_TIMESLOTS; + move16(); + } + + /* CLDFB analysis for ParamMC/ParamISM */ + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) && ( EQ_32( st_ivas->renderer_type, RENDERER_PARAM_ISM ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) ) + { + ivas_param_ism_dec_digest_tc_fx( st_ivas, n_render_timeslots, p_data_fx, Q11 ); + } + ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMMC ) && EQ_32( hTcBuffer->tc_buffer_mode, TC_BUFFER_MODE_RENDERER ) ) + { + ivas_param_mc_dec_digest_tc_fx( st_ivas, (UWord8) n_render_timeslots, p_data_fx, Q11 ); + } + + hTcBuffer->n_samples_rendered = 0; + move16(); + hTcBuffer->subframes_rendered = 0; + move16(); + + return; +} + + /*--------------------------------------------------------------------------* - * ivas_dec() + * ivas_dec_render() * - * Principal IVAS decoder routine, decoding of metadata and transport channels + * Principal IVAS internal rendering routine *--------------------------------------------------------------------------*/ -ivas_error ivas_dec_fx( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +ivas_error ivas_dec_render_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const UWord16 nSamplesAsked, /* i : number of samples wanted */ + UWord16 *nSamplesRendered, /* o : number of samples rendered */ + UWord16 *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ + Word16 *data /* o : output synthesis signal Q0*/ ) { - Word16 ch, n, output_frame, nchan_out, i, s; - Decoder_State *st; /* used for bitstream handling */ - Word32 *p_output_fx[MAX_TRANSPORT_CHANNELS]; /* buffer for output synthesis */ + Word16 n, nchan_out; + Word16 nchan_transport_rend; Word16 nchan_remapped; - Word16 nb_bits_metadata[MAX_SCE + 1]; - Word32 output_Fs, ivas_total_brate; + Word32 output_Fs; AUDIO_CONFIG output_config; + Word16 nSamplesAskedLocal; ivas_error error; - Word16 num_md_sub_frames; - Word32 ism_total_brate; + Word32 *p_output_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; + Word32 *p_tc_fx[MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS]; + Word16 subframe_len, gd_bits, exp, nchan_in, i, j, ch; + const Word16 output_q_factor = Q11; + move16(); + Word16 nchan_out_syn_output; - push_wmops( "ivas_dec" ); + push_wmops( "ivas_dec_render" ); /*----------------------------------------------------------------* * Initialization of local vars after struct has been set *----------------------------------------------------------------*/ output_Fs = st_ivas->hDecoderConfig->output_Fs; move32(); - nchan_out = st_ivas->hTcBuffer->nchan_transport_rend; + nchan_out = st_ivas->hDecoderConfig->nchan_out; + move16(); + nchan_transport_rend = st_ivas->hTcBuffer->nchan_transport_rend; move16(); output_config = st_ivas->hDecoderConfig->output_config; - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; move32(); + nSamplesAskedLocal = add( nSamplesAsked, st_ivas->hTcBuffer->n_samples_discard ); + move16(); - output_frame = extract_l( Mult_32_16( output_Fs, INV_FRAME_PER_SEC_Q15 ) ) /* output_Fs / FRAMES_PER_SEC */; - - /* set pointers to transport channels audio */ - FOR( n = 0; n < MAX_TRANSPORT_CHANNELS; n++ ) + FOR( n = 0; n < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; n++ ) { p_output_fx[n] = st_ivas->p_output_fx[n]; - IF( p_output_fx[n] != NULL ) + } + + IF( !st_ivas->hDecoderConfig->Opt_tsm ) + { + FOR( n = 0; n < MAX_INTERN_CHANNELS; n++ ) { - set32_fx( p_output_fx[n], 0, L_FRAME48k ); + st_ivas->hTcBuffer->tc_fx[n] = st_ivas->p_output_fx[n]; } } + FOR( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) + { + p_tc_fx[n] = &st_ivas->hTcBuffer->tc_fx[n][st_ivas->hTcBuffer->n_samples_rendered]; + } + /*----------------------------------------------------------------* - * Decoding + pre-rendering + * Update combined orientation access index *----------------------------------------------------------------*/ - test(); - IF( EQ_32( st_ivas->ivas_format, STEREO_FORMAT ) ) - + IF( st_ivas->hCombinedOrientationData != NULL ) { - st_ivas->hCPE[0]->element_brate = ivas_total_brate; - move32(); - IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } + /* take the discard samples into account here to make sure head rotation stays on the correct 5ms grid */ + st_ivas->hCombinedOrientationData->cur_subframe_samples_rendered_start = sub( st_ivas->hCombinedOrientationData->cur_subframe_samples_rendered_start, st_ivas->hTcBuffer->n_samples_discard ); + move16(); - /* HP filtering */ - FOR( n = 0; n < s_min( nchan_out, st_ivas->nchan_transport ); n++ ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } + ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); } - ELSE IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) ) - { - /* Metadata decoding and configuration */ - test(); - IF( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) || EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) - { - ivas_ism_dtx_dec_fx( st_ivas, nb_bits_metadata ); - IF( ( error = ivas_sce_dec_fx( st_ivas, st_ivas->hISMDTX.sce_id_dtx, &p_output_fx[st_ivas->hISMDTX.sce_id_dtx], output_frame, nb_bits_metadata[st_ivas->hISMDTX.sce_id_dtx] ) ) != IVAS_ERR_OK ) - { - return error; - } + /*----------------------------------------------------------------* + * Rendering + *----------------------------------------------------------------*/ - ivas_ism_dtx_limit_noise_energy_for_near_silence_fx( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport ); + *nSamplesRendered = s_min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); + move16(); - ivas_param_ism_dec_dequant_md_fx( st_ivas ); + test(); + test(); + IF( EQ_32( st_ivas->ivas_format, UNDEFINED_FORMAT ) ) + { + assert( 0 ); + } + ELSE IF( EQ_32( st_ivas->hTcBuffer->tc_buffer_mode, TC_BUFFER_MODE_BUFFER ) ) + { + ivas_dec_tc_buffer_playout_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output_fx ); + } + ELSE IF( EQ_32( st_ivas->ivas_format, MONO_FORMAT ) || EQ_32( st_ivas->ivas_format, STEREO_FORMAT ) ) + { + /* Rendering */ + IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) + { + ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc_fx, p_output_fx ); } - ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) ) { - IF( NE_32( ( error = ivas_ism_metadata_dec_fx( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, st_ivas->hParamIsmDec->hParamIsm, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt, st_ivas->hSCE[0]->hCoreCoder[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } - - ivas_param_ism_dec_dequant_md_fx( st_ivas ); + ivas_apply_non_diegetic_panning_fx( p_tc_fx[0], p_output_fx, st_ivas->hDecoderConfig->non_diegetic_pan_gain_fx, *nSamplesRendered ); } - ELSE /* ISM_MODE_DISC */ + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) { - IF( NE_32( ( error = ivas_ism_metadata_dec_fx( ivas_total_brate, st_ivas->nchan_ism, &( st_ivas->nchan_transport ), st_ivas->hIsmMetaData, st_ivas->hSCE, st_ivas->bfi, nb_bits_metadata, st_ivas->ism_mode, st_ivas->hISMDTX, NULL, &st_ivas->ism_extmeta_active, &st_ivas->ism_extmeta_cnt, st_ivas->hSCE[0]->hCoreCoder[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } + ivas_stereo2sba_fx( p_tc_fx, p_output_fx, *nSamplesRendered ); } - - FOR( n = 0; n < st_ivas->nchan_transport; n++ ) + } + ELSE IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) ) + { + /* Rendering */ + IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) { - /* for DTX frames, dominant object has already been decoded before */ test(); test(); - IF( !( ( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) || EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) && EQ_16( n, st_ivas->hISMDTX.sce_id_dtx ) ) ) + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) + { + ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, st_ivas->nchan_transport, p_output_fx ); + } + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_PARAM_ISM ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) { - IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, n, &p_output_fx[n], output_frame, nb_bits_metadata[n] ) ), IVAS_ERR_OK ) ) + ivas_param_ism_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ); + + IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) { - return error; + /* Convert CICP19 -> Ambisonics */ + ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); } } - - /* HP filtering */ - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } - - test(); - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) - { - ivas_ism_mono_dmx_fx( st_ivas, p_output_fx, output_frame ); - - Scale_sig32( p_output_fx[0], output_frame, Q11 - Q8 ); } - ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) && ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) ) + ELSE /* ISM_MODE_DISC */ { - /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain_fx( p_output_fx, st_ivas->nchan_transport, output_frame ); /*returns Q-1*/ - - FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + test(); + test(); + /* Loudspeaker or Ambisonics rendering */ + IF( EQ_32( st_ivas->renderer_type, RENDERER_TD_PANNING ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) { - Scale_sig32( p_output_fx[i], output_frame, 1 ); // Q-1 -> Q + /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ + ivas_ism_render_sf_fx( st_ivas, st_ivas->renderer_type, p_output_fx, *nSamplesRendered ); } - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) - { - set16_fx( nb_bits_metadata, 0, MAX_SCE ); - - /* read parameters from the bitstream */ - test(); - IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && st_ivas->hQMetaData != NULL ) - { - // st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; - IF( st_ivas->nSCE > 0 ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) ) { - st = st_ivas->hSCE[0]->hCoreCoder[0]; + ivas_apply_non_diegetic_panning_fx( p_tc_fx[0], p_output_fx, st_ivas->hDecoderConfig->non_diegetic_pan_gain_fx, *nSamplesRendered ); } - ELSE +#ifdef DEBUGGING + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) ) +#else + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) +#endif { - st = st_ivas->hCPE[0]->hCoreCoder[0]; + /* Convert to Ambisonics */ + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + FOR( j = 0; j < HOA3_CHANNELS; j++ ) + { + st_ivas->hIsmRendererData->gains_fx[i][j] = L_shr( st_ivas->hIsmRendererData->gains_fx[i][j], 1 ); // Q30 -> Q29 + move32(); + st_ivas->hIsmRendererData->prev_gains_fx[i][j] = L_shr( st_ivas->hIsmRendererData->prev_gains_fx[i][j], 1 ); // Q30 -> Q29 + move32(); + } + } + + ivas_ism2sba_sf_fx( p_tc_fx, p_output_fx, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); + + Word16 sba_num_chans = imult1616( add( st_ivas->hIntSetup.ambisonics_order, 1 ), add( st_ivas->hIntSetup.ambisonics_order, 1 ) ); + FOR( j = 0; j < sba_num_chans; j++ ) + { + scale_sig32( p_output_fx[j], *nSamplesRendered, sub( Q11, sub( add( output_q_factor, 29 ), 31 ) ) ); // Q11 + } + + FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + { + FOR( j = 0; j < 16; j++ ) + { + st_ivas->hIsmRendererData->gains_fx[i][j] = L_shl( st_ivas->hIsmRendererData->gains_fx[i][j], 1 ); // Q29 -> Q30 + move32(); + st_ivas->hIsmRendererData->prev_gains_fx[i][j] = L_shl( st_ivas->hIsmRendererData->prev_gains_fx[i][j], 1 ); // Q29 -> Q30 + move32(); + } + } } - IF( NE_32( ( error = ivas_masa_decode_fx( st_ivas, st, &nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + /* Binaural rendering */ + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) { - return error; + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output_fx, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } + } } - } - ELSE IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) ) - { - IF( NE_32( ( error = ivas_spar_dec_fx( st_ivas, nb_bits_metadata ) ), IVAS_ERR_OK ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) { - return error; + st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; + subframe_len = imult1616( st_ivas->hTcBuffer->subframe_nbslots[0], st_ivas->hTcBuffer->n_samples_granularity ); + gd_bits = find_guarded_bits_fx( subframe_len ); + exp = 13; + move16(); + nchan_in = 12; + move16(); + nchan_out = 2; + move16(); + exp = sub( exp, gd_bits ); + *st_ivas->hCrendWrapper->p_io_qfactor = exp; + move16(); + FOR( i = 0; i < nchan_in; i++ ) + { + scale_sig32( p_output_fx[i], *nSamplesRendered, negate( sub( 11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q11 + } + + IF( NE_32( ( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs, 0 ) ), IVAS_ERR_OK ) ) + { + return error; + } + + FOR( i = 0; i < nchan_out; i++ ) + { + scale_sig32( p_output_fx[i], *nSamplesRendered, sub( 11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 + } } } + } + ELSE IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) + { + nchan_remapped = nchan_transport_rend; + move16(); test(); - IF( EQ_16( st_ivas->nchan_transport, CPE_CHANNELS ) && GE_16( st_ivas->nCPE, 1 ) ) - { - st_ivas->hCPE[0]->brate_surplus = 0; - move32(); - st_ivas->hCPE[0]->element_brate = ivas_total_brate; - move32(); - } - - /* core-decoding of transport channels */ - IF( EQ_16( st_ivas->nSCE, 1 ) ) + test(); + /* Loudspeakers, Ambisonics or Binaural rendering */ + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) { - IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } + ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); } - ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + ELSE IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) { - IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) ) { - return error; + ivas_dirac_dec_render_fx( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ); } } - ELSE IF( GT_16( st_ivas->nCPE, 1 ) ) + ELSE { - IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) { return error; } } - - /* TCs remapping */ + } + ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { nchan_remapped = st_ivas->nchan_transport; move16(); - test(); test(); test(); - test(); - test(); - IF( st_ivas->sba_dirac_stereo_flag ) + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) { - nchan_remapped = nchan_out; - move16(); - - IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) ) + test(); + IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) { - FOR( i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) - { - Scale_sig32( p_output_fx[i], output_frame, Q14 - Q11 ); // Q14 - } - SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; - Word16 nchan_transport; - nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; - move16(); - nchan_out = nchan_transport; - move16(); - - ivas_agc_dec_process_fx( st_ivas->hSpar->hAgcDec, ( p_output_fx ), ( p_output_fx ), st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); - - IF( st_ivas->hSpar->hPCA != NULL ) + IF( NE_32( ( error = ivas_omasa_dirac_td_binaural_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ) ), IVAS_ERR_OK ) ) { - ivas_pca_dec_fx( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, p_output_fx ); + return error; } - - ivas_spar_dec_gen_umx_mat_fx( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, ivas_total_brate, st_ivas->last_active_ivas_total_brate ) ); } - - ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fx, output_frame ); + ELSE + { + ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); + } } - ELSE IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && ( GT_32( ivas_total_brate, IVAS_SID_5k2 ) || ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) && st_ivas->nCPE > 0 && EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) ) { - nchan_remapped = 1; /* Only one channel transported */ - move16(); + ivas_omasa_dirac_rend_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); } - - /* HP filtering */ - FOR( n = 0; n < nchan_remapped; n++ ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) ) { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); + ivas_dec_tc_buffer_playout_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output_fx ); + ivas_omasa_rearrange_channels_fx( p_output_fx, st_ivas->nchan_ism, *nSamplesRendered ); } + } + ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) + { + nchan_remapped = nchan_transport_rend; + move16(); - IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) ) + /* Loudspeakers, Ambisonics or Binaural rendering */ + IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) { - nchan_remapped = ivas_sba_remapTCs_fx( p_output_fx, st_ivas, output_frame ); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) ) { - num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, ivas_total_brate, st_ivas->last_active_ivas_total_brate ); - - SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; - Word16 Q_p_output = MAX_16, temp_min; + SPAR_DEC_HANDLE hSpar; + hSpar = st_ivas->hSpar; + hSpar->hMdDec->Q_mixer_mat = 30; move16(); - Word16 nchan_transport; - nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; - move16(); - nchan_out = nchan_transport; - move16(); - FOR( ch = 0; ch < nchan_transport; ch++ ) + IF( NE_32( ( error = ivas_osba_dirac_td_binaural_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) { - temp_min = L_norm_arr( p_output_fx[ch], output_frame ); - Q_p_output = s_min( Q_p_output, temp_min ); + return error; } - Q_p_output = sub( Q_p_output, 2 ); - if ( GT_16( Q_p_output, 20 ) ) + } + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OSBA_STEREO ) ) + { + test(); + /* shift SBA channels to avoid overwrite by ISM upmix in 1 object case and non-TSM unified channel memory*/ + IF( EQ_16( st_ivas->nchan_ism, 1 ) && EQ_16( st_ivas->hDecoderConfig->Opt_tsm, 0 ) ) { - Q_p_output = 20; - move16(); + Copy32( p_tc_fx[2], p_output_fx[3], *nSamplesRendered ); + Copy32( p_tc_fx[1], p_output_fx[2], *nSamplesRendered ); + p_tc_fx[1] = p_output_fx[2]; + p_tc_fx[2] = p_output_fx[3]; + } + + /* render objects */ + ivas_ism_render_sf_fx( st_ivas, st_ivas->renderer_type, p_output_fx, *nSamplesRendered ); + + /* add already rendered SBA part */ + ivas_osba_stereo_add_channels_fx( p_tc_fx, p_output_fx, st_ivas->hSbaIsmData->gain_bed_fx, nchan_out, st_ivas->nchan_ism, st_ivas->ism_mode, *nSamplesRendered ); + } + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OSBA_AMBI ) || EQ_32( st_ivas->renderer_type, RENDERER_OSBA_LS ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) + { + IF( NE_32( ( error = ivas_osba_render_sf_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) + { + return error; } - FOR( ch = 0; ch < nchan_transport; ch++ ) + } + ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) /*EXT output = individual objects + HOA3*/ + { + IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, &p_output_fx[st_ivas->nchan_ism] ) ), IVAS_ERR_OK ) ) { - Scale_sig32( p_output_fx[ch], output_frame, Q_p_output ); // Q(11+Q_p_output) + return error; } - ivas_sba_mix_matrix_determiner_fx( st_ivas->hSpar, p_output_fx, st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames, Q_p_output ); - FOR( Word16 c = 0; c < nchan_transport; c++ ) + FOR( n = 0; n < st_ivas->nchan_ism; n++ ) { - Scale_sig32( p_output_fx[c], output_frame, 11 ); // Q11 + Copy32( p_tc_fx[n], p_output_fx[n], *nSamplesRendered ); } } - ELSE IF( NE_32( st_ivas->renderer_type, RENDERER_DISABLE ) ) + ELSE { - Word16 size = st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; - move16(); - if ( EQ_16( st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, 3 ) ) - size = add( size, 1 ); - - FOR( i = 0; i < size; i++ ) + IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) { - Scale_sig32( p_output_fx[i], output_frame, Q14 - Q11 ); // Q14 + return error; } - - ivas_spar_dec_agc_pca_fx( st_ivas, p_output_fx, output_frame ); } } - - test(); - test(); - IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) { - Word16 q_shift = 0; - move16(); - - ivas_masa_prerender_fx( st_ivas, p_output_fx, &q_shift, output_frame, nchan_remapped ); + ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); - FOR( i = 0; i < CPE_CHANNELS; i++ ) + FOR( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) + { + scale_sig32( p_output_fx[n], *nSamplesRendered, 1 ); + } + } + ELSE + { + IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) { - Scale_sig32( p_output_fx[i], output_frame, negate( q_shift ) ); + return error; } - test(); - /* external output */ - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && EQ_32( st_ivas->hMasa->config.input_ivas_format, MASA_ISM_FORMAT ) ) + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) { + FOR( n = st_ivas->hIntSetup.nchan_out_woLFE - 1; n >= 0; n-- ) + { + Copy32( p_output_fx[n], p_output_fx[n + st_ivas->nchan_ism], *nSamplesRendered ); + } FOR( n = 0; n < st_ivas->nchan_ism; n++ ) { - set_zero_fx( p_output_fx[add( st_ivas->nchan_transport, n )], output_frame ); + set32_fx( p_output_fx[n], 0, *nSamplesRendered ); } - - ivas_omasa_rearrange_channels_fx( p_output_fx, st_ivas->nchan_ism, output_frame ); } - } - ELSE IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) && ( EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_16( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) ) - { - /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain_fx( p_output_fx, nchan_remapped, output_frame ); - - FOR( i = 0; i < st_ivas->nchan_transport; i++ ) + FOR( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) { - Scale_sig32( p_output_fx[i], output_frame, 1 ); // Q-1 -> Q + scale_sig32( p_output_fx[n], *nSamplesRendered, 1 ); } } } - ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) ) { - Word16 nchan_ism, nchan_transport_ism; - Word16 dirac_bs_md_write_idx; - - set16_fx( nb_bits_metadata, 0, MAX_SCE + 1 ); - - /* Set the number of objects for the parametric rendering */ - dirac_bs_md_write_idx = 0; - move16(); - IF( st_ivas->hSpatParamRendCom != NULL ) + IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) ) { - st_ivas->hSpatParamRendCom->numIsmDirections = 0; + Word16 crendInPlaceRotation = FALSE; move16(); + test(); - if ( NE_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && NE_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + test(); + test(); + IF( NE_32( st_ivas->transport_config, st_ivas->intern_config ) && ( EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) { - st_ivas->hSpatParamRendCom->numIsmDirections = st_ivas->nchan_ism; - move16(); - } + IF( LT_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) + { + crendInPlaceRotation = TRUE; + move16(); - dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */ - move16(); - } + ivas_mc2sba_fx( st_ivas->hTransSetup, p_tc_fx, p_output_fx, *nSamplesRendered, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE_FX ); + } + } - /* MASA metadata decoding */ - IF( NE_32( ( error = ivas_masa_decode_fx( st_ivas, st_ivas->hCPE[0]->hCoreCoder[0], &nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } - - /* Configuration of combined-format bit-budget distribution */ - ivas_set_surplus_brate_dec( st_ivas, &ism_total_brate ); - - st_ivas->hCPE[0]->hCoreCoder[0]->bit_stream = &( st_ivas->bit_stream[( ism_total_brate / FRAMES_PER_SEC )] ); - - IF( NE_32( ( error = ivas_omasa_ism_metadata_dec_fx( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) - { - return error; - } - - FOR( n = 0; n < nchan_transport_ism; n++ ) - { - IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, n, &p_output_fx[st_ivas->nchan_transport + n], output_frame, nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + /* Rendering */ + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) { - return error; - } - } + st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; + subframe_len = imult1616( st_ivas->hTcBuffer->subframe_nbslots[0], st_ivas->hTcBuffer->n_samples_granularity ); + gd_bits = find_guarded_bits_fx( subframe_len ); + exp = 13; + move16(); + IF( NE_32( ( error = getAudioConfigNumChannels( st_ivas->intern_config, &nchan_in ) ), IVAS_ERR_OK ) ) + { + return error; + } + IF( NE_32( ( error = getAudioConfigNumChannels( st_ivas->hOutSetup.output_config, &nchan_out ) ), IVAS_ERR_OK ) ) + { + return error; + } + exp = sub( exp, gd_bits ); + *st_ivas->hCrendWrapper->p_io_qfactor = exp; + move16(); - /* decode MASA channels */ - IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } + IF( crendInPlaceRotation ) + { + FOR( i = 0; i < nchan_in; i++ ) + { + scale_sig32( p_output_fx[i], *nSamplesRendered, negate( sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q = *st_ivas->hCrendWrapper->p_io_qfactor + } + } + ELSE + { + FOR( i = 0; i < nchan_in; i++ ) + { + scale_sig32( p_tc_fx[i], *nSamplesRendered, negate( sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q = *st_ivas->hCrendWrapper->p_io_qfactor + } + } - IF( EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) - { - Copy32( p_output_fx[0], p_output_fx[1], output_frame ); /* Copy mono signal to stereo output channels */ - } + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( ( error = ivas_rend_crendProcessSubframesSplitBin( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, + &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + IF( NE_32( ( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, + &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs, 0 ) ), + IVAS_ERR_OK ) ) + { + return error; + } - FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); + } - Word16 output_q = Q11; - move16(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) - { - ivas_ism_mono_dmx_fx( st_ivas, p_output_fx, output_frame ); + IF( crendInPlaceRotation ) + { + n = nchan_in; + } + ELSE + { + n = nchan_out; + } + move16(); - output_q = Q8; - move16(); - } - ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) - { - IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) - { - ivas_omasa_rearrange_channels_fx( p_output_fx, nchan_transport_ism, output_frame ); + FOR( i = 0; i < n; i++ ) + { + scale_sig32( p_output_fx[i], *nSamplesRendered, sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 + } + + FOR( i = n; i < nchan_in; i++ ) + { + scale_sig32( p_tc_fx[i], *nSamplesRendered, sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 + } } - ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) { - /* Convert separate object to MASA, combine with the original MASA, and output combined MASA + empty objects. */ - ivas_omasa_combine_separate_ism_with_masa_fx( st_ivas, p_output_fx, &output_q, st_ivas->nchan_ism, output_frame ); + ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc_fx, p_output_fx ); } - ELSE IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) { - /* Extract objects from MASA, output MASA + all objects (i.e., extracted and separated objects) */ - ivas_omasa_render_objects_from_mix_fx( st_ivas, p_output_fx, st_ivas->nchan_ism, output_frame, &output_q ); + ivas_mc2sba_fx( st_ivas->hIntSetup, p_tc_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); } - } - - IF( NE_16( output_q, Q11 ) ) - { - FOR( n = 0; n < s_max( getNumChanSynthesis( st_ivas ), nchan_transport_ism + st_ivas->nchan_transport ); n++ ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) { - Scale_sig32( p_output_fx[n], output_frame, sub( Q11, output_q ) ); // Q11 - } - st_ivas->hCPE[0]->q_output_mem_fx[0] = output_q; - st_ivas->hCPE[0]->q_output_mem_fx[1] = output_q; - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) - { - Word16 nchan_ism, sba_ch_idx; + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + else + { + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) + { + return error; + } - set16_fx( nb_bits_metadata, 0, MAX_SCE + 1 ); - nchan_ism = st_ivas->nchan_ism; - move16(); - IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) - { - /* set ISM parameters and decode ISM metadata in OSBA format */ - IF( NE_32( ( error = ivas_osba_ism_metadata_dec_fx( st_ivas, ivas_total_brate, &nchan_ism, &nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) - { - return error; + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); + } } - sba_ch_idx = st_ivas->nchan_ism; - move16(); - } - ELSE - { - nb_bits_metadata[1] = add( nb_bits_metadata[1], NO_BITS_MASA_ISM_NO_OBJ ); - sba_ch_idx = 0; - move16(); - move16(); - } - - /* SBA metadata decoding */ - IF( NE_32( ( error = ivas_spar_dec_fx( st_ivas, nb_bits_metadata ) ), IVAS_ERR_OK ) ) - { - return error; } - - test(); - IF( EQ_16( st_ivas->nchan_transport, CPE_CHANNELS ) && GE_16( st_ivas->nCPE, 1 ) ) + ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) { - st_ivas->hCPE[0]->element_brate = ivas_total_brate; - move32(); - } + ivas_mc_paramupmix_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_tc_fx, p_output_fx ); - /* core-decoding of transport channels */ - IF( EQ_16( st_ivas->nSCE, 1 ) ) - { - IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + /* Rendering */ + test(); + test(); + IF( ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) && !st_ivas->hDecoderConfig->Opt_Headrotation ) { - return error; + /* handled in CLDFB domain already */ + IF( NE_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_output_fx, p_output_fx ); + } } - } - ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) - { - IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, add( nb_bits_metadata[0], nb_bits_metadata[1] ) ) ), IVAS_ERR_OK ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) { - return error; + ivas_ls_setup_conversion_fx( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, *nSamplesRendered, p_output_fx, p_output_fx ); } - } - ELSE IF( GT_16( st_ivas->nCPE, 1 ) ) - { - IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ), IVAS_ERR_OK ) ) + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) { - return error; + ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); } } - - IF( st_ivas->sba_dirac_stereo_flag ) + ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMMC ) ) { - FOR( i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) - { - Scale_sig32( p_output_fx[i + sba_ch_idx], output_frame, Q14 - Q11 ); // Q14 - } - SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; - Word16 nchan_transport; - nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; - move16(); - nchan_out = nchan_transport; + Word16 channel_active_fx[MAX_OUTPUT_CHANNELS]; + Word16 nchan_out_cov; + Word16 nchan_out_cldfb = 0; move16(); - ivas_agc_dec_process_fx( st_ivas->hSpar->hAgcDec, ( p_output_fx + sba_ch_idx ), ( p_output_fx + sba_ch_idx ), st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); - IF( st_ivas->hSpar->hPCA != NULL ) + set16_fx( channel_active_fx, 0, MAX_LS_CHANNELS ); + Word16 nchan_transport_tmp = st_ivas->nchan_transport; + move16(); + output_Fs = st_ivas->hDecoderConfig->output_Fs; + move32(); + Word16 nchan_out_transport = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ); + test(); + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) { - ivas_pca_dec_fx( st_ivas->hSpar->hPCA, output_frame, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate, st_ivas->bfi, &p_output_fx[sba_ch_idx] ); + nchan_out_cldfb = BINAURAL_CHANNELS; + move16(); + set16_fx( channel_active_fx, 1, BINAURAL_CHANNELS ); + nchan_out_cov = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ); } - - ivas_spar_dec_gen_umx_mat_fx( st_ivas->hSpar->hMdDec, st_ivas->nchan_transport, IVAS_MAX_NUM_BANDS, st_ivas->bfi, ivas_get_spar_dec_md_num_subframes( st_ivas->sba_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ) ); - - ivas_sba_dirac_stereo_dec_fx( st_ivas, &p_output_fx[sba_ch_idx], output_frame ); - } - - /* HP filtering */ - FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } - - nchan_remapped = ivas_sba_remapTCs_fx( &p_output_fx[sba_ch_idx], st_ivas, output_frame ); - - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) - { - num_md_sub_frames = ivas_get_spar_dec_md_num_subframes( st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate, st_ivas->last_active_ivas_total_brate ); - SPAR_DEC_HANDLE hSpar = st_ivas->hSpar; - Word16 nchan_transport; - // num_bands_out = hSpar->hFbMixer->pFb->filterbank_num_bands; - nchan_transport = hSpar->hMdDec->spar_md_cfg.nchan_transport; - move16(); - nchan_out = nchan_transport; - move16(); - Word16 Q_p_output; - Word16 min_norm = 31; - move16(); - - FOR( ch = 0; ch < nchan_transport; ++ch ) + ELSE IF( EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_LS_CONV_CLDFB ) ) { - Word16 norm = L_norm_arr( p_output_fx[sba_ch_idx + ch], output_frame ); // Normalize per channel - min_norm = s_min( norm, min_norm ); + nchan_out_cov = nchan_out_transport; + move16(); + nchan_out_cldfb = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); } - - Q_p_output = s_max( 3, sub( min_norm, 1 ) ); - - Q_p_output = s_min( Q_p_output, 19 ); // to restrict Q-factor of p_ouptut to Q30 - FOR( ch = 0; ch < nchan_transport; ch++ ) + ELSE IF( EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_LS_CONV_COV ) || EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_MONO_STEREO ) ) { - Scale_sig32( p_output_fx[sba_ch_idx + ch], output_frame, Q_p_output ); // Q_p_output + Q11 + nchan_out_cov = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); + nchan_out_cldfb = nchan_out_cov; + move16(); + set16_fx( channel_active_fx, 1, nchan_out_cov ); } - Q_p_output = add( Q11, Q_p_output ); - hSpar->hMdDec->Q_mixer_mat = 31; - move16(); - - ivas_sba_mix_matrix_determiner_fx( st_ivas->hSpar, &p_output_fx[sba_ch_idx], st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames, sub( Q_p_output, Q11 ) ); - FOR( Word16 c = 0; c < nchan_transport; c++ ) + ELSE { - Scale_sig32( p_output_fx[sba_ch_idx + c], output_frame, Q11 ); // Q11 + nchan_out_cov = nchan_out_transport; + move16(); + nchan_out_cldfb = nchan_out_transport; + move16(); + set16_fx( channel_active_fx, 1, nchan_out_cov ); } - } - ELSE IF( NE_32( st_ivas->renderer_type, RENDERER_DISABLE ) && st_ivas->sba_dirac_stereo_flag == 0 ) - { - Word16 size = add( st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, sba_ch_idx ); - if ( EQ_16( size, 3 ) ) + IF( st_ivas->hParamMC->max_band_decorr > 0 ) { - size = add( size, 1 ); + Word16 tmp; + tmp = L_norm_arr( st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_fx, st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_len ); + scale_sig32( st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_fx, st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_len, tmp ); // Q(st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer+ tmp) + st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer = add( st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer, tmp ); + move16(); } - - FOR( i = sba_ch_idx; i < size; i++ ) + /* CLDFB synthesis */ + FOR( ch = 0; ch < nchan_out_cldfb; ch++ ) { - Scale_sig32( p_output_fx[i], output_frame, ( Q14 - Q11 ) ); // Q14 + IF( st_ivas->cldfbSynDec[ch] ) + { + scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, ( Q5 - Q11 ) ); // Q5 + st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q5; + move16(); + } } - - ivas_spar_dec_agc_pca_fx( st_ivas, &p_output_fx[sba_ch_idx], output_frame ); - } - - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) - { - /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain_fx( &p_output_fx[sba_ch_idx], nchan_remapped, output_frame ); /*returns Q-1*/ - - FOR( i = 0; i < nchan_remapped; i++ ) + Word16 tempp; + FOR( Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->num_param_bands_synth; param_band_idx++ ) { - Scale_sig32( p_output_fx[i], output_frame, 1 ); // Q-1 -> Q + tempp = getScaleFactor32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_len ); + scale_sig32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_len, tempp ); // Q(31-(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx]- tempp)) + st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx] = sub( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx], tempp ); + move16(); + + IF( LT_16( st_ivas->hParamMC->band_grouping[param_band_idx], st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr ) ) + { + tempp = getScaleFactor32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_len ); + scale_sig32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_len, tempp ); // Q(31- (st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx] - tempp)) + st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx] = sub( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx], tempp ); + move16(); + } } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) - { - ivas_ism_mono_dmx_fx( st_ivas, p_output_fx, output_frame ); - Scale_sig32( p_output_fx[0], output_frame, Q11 - Q8 ); // Q11 + ivas_param_mc_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx, channel_active_fx ); - /* add W */ - FOR( n = 0; n < nchan_out; n++ ) - { - v_add_32( p_output_fx[n], p_output_fx[n + s_max( nchan_out, nchan_ism )], p_output_fx[n], output_frame ); - } - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) ) - { - IF( st_ivas->nSCE > 0 ) - { - st = st_ivas->hSCE[0]->hCoreCoder[0]; - } - ELSE - { - st = st_ivas->hCPE[0]->hCoreCoder[0]; - } - - IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) ) - { - /* LFE channel decoder */ - ivas_lfe_dec_fx( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output_fx[LFE_CHANNEL] ); - - Scale_sig32( p_output_fx[LFE_CHANNEL], output_frame, Q11 - Q9 ); // Q11 - - IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, 0 ) ), IVAS_ERR_OK ) ) - { - return error; - } - - /* HP filtering */ - FOR( n = 0; n < st_ivas->nchan_transport; n++ ) - { - IF( NE_16( n, LFE_CHANNEL ) ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } - } - - test(); - test(); - test(); - IF( NE_32( st_ivas->transport_config, st_ivas->intern_config ) && ( NE_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || NE_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || NE_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) + FOR( ch = 0; ch < nchan_out_cldfb; ch++ ) { - IF( GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) + IF( st_ivas->cldfbSynDec[ch] ) { - ivas_mc2sba_fx( st_ivas->hTransSetup, p_output_fx, p_output_fx, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE_FX ); + scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, Q11 - Q5 ); // Q11 + st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11; + move16(); } } - - test(); - test(); - IF( ( EQ_32( st_ivas->renderer_type, RENDERER_MC ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ) ) + IF( EQ_16( st_ivas->hParamMC->slots_rendered, st_ivas->hParamMC->num_slots ) ) { - IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) + FOR( Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->hMetadataPMC->nbands_coded; param_band_idx++ ) { - s = Q16 - Q11; - move16(); - s = sub( s, find_guarded_bits_fx( st_ivas->nchan_transport ) ); - FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, st_ivas->nchan_transport ); ++i ) - { - Scale_sig32( p_output_fx[i], output_frame, s ); // Q(11+s) - } - ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, output_frame, p_output_fx, p_output_fx ); - FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, st_ivas->nchan_transport ); ++i ) + IF( LT_16( st_ivas->hParamMC->band_grouping[param_band_idx], st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr ) ) { - Scale_sig32( p_output_fx[i], output_frame, negate( s ) ); // Q11 + Copy32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_fx[param_band_idx], imult1616( nchan_transport_tmp, nchan_out_cov ) ); + st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_exp[param_band_idx] = st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx]; + move16(); } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, output_frame, st_ivas->hOutSetup.ambisonics_order, 0 ); + Copy32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_old_fx[param_band_idx], imult1616( nchan_transport_tmp, nchan_out_cov ) ); + st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_old_exp[param_band_idx] = st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx]; + move16(); } } } - ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCMASA ) ) { - /* LFE channel decoder */ - ivas_lfe_dec_fx( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output_fx[LFE_CHANNEL] ); - - Scale_sig32( p_output_fx[LFE_CHANNEL], output_frame, Q11 - Q9 ); // Q11 - - ivas_mc_paramupmix_dec_read_BS( st_ivas, st, st_ivas->hMCParamUpmix, &nb_bits_metadata[0] ); - - IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } - - /* HP filtering */ - FOR( n = 0; n < st_ivas->nchan_transport; n++ ) - { - IF( NE_16( n, LFE_CHANNEL ) ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } - } + nchan_remapped = st_ivas->nchan_transport; + move16(); - /* Rendering */ test(); test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) && ( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) ) + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) { - /* Compensate loudness for not doing full upmix */ - FOR( n = 4; n < 8; n++ ) - { - Scale_sig32( p_output_fx[n], output_frame, 1 ); - } + ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); + } + ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) /* rendering to CICPxx and Ambisonics */ + { + ivas_dirac_dec_render_fx( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ); test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) + test(); + test(); + IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) { - s = Q16 - Q11; - move16(); - Word16 nchan_transport; - nchan_transport = audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 ); - s = sub( s, find_guarded_bits_fx( nchan_transport ) ); - FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, nchan_transport ); ++i ) - { - Scale_sig32( p_output_fx[i], output_frame, s ); - } - - ivas_ls_setup_conversion_fx( st_ivas, nchan_transport, output_frame, p_output_fx, p_output_fx ); - - FOR( i = 0; i < s_max( st_ivas->hDecoderConfig->nchan_out, nchan_transport ); ++i ) + /* we still need to copy the separate channel if available */ + IF( st_ivas->hOutSetup.separateChannelEnabled ) { - Scale_sig32( p_output_fx[i], output_frame, negate( s ) ); + Copy32( p_tc_fx[LFE_CHANNEL - 1], p_output_fx[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); } - } - } - } - ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMMC ) ) - { - /* read Parametric MC parameters from the bitstream */ - ivas_param_mc_dec_read_BS_fx( ivas_total_brate, st, st_ivas->hParamMC, &nb_bits_metadata[0] ); - IF( EQ_16( st_ivas->nCPE, 1 ) ) - { - IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; + ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); } - } - ELSE IF( GT_16( st_ivas->nCPE, 1 ) ) - { - IF( NE_32( ( error = ivas_mct_dec_fx( st_ivas, p_output_fx, output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) + ELSE IF( EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_5_1 ) && ( EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1 ) ) ) { - return error; + FOR( n = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; n < ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ); n++ ) + { + set32_fx( p_output_fx[n], 0, *nSamplesRendered ); + } } } - /* HP filtering */ - FOR( n = 0; n < st_ivas->nchan_transport; n++ ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } - - /* Rendering */ - test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) - { - ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, output_frame, p_output_fx, p_output_fx ); - } - } - ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCMASA ) ) - { - IF( st_ivas->hOutSetup.separateChannelEnabled ) - { - st = st_ivas->hCPE[0]->hCoreCoder[0]; /* Metadata is always with CPE in the case of separated channel */ - } - - /* read McMASA parameters from the bitstream */ - IF( NE_32( ( error = ivas_masa_decode_fx( st_ivas, st, &nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } - + /* copy discrete C and TD LFE from internal TC to output */ IF( st_ivas->hOutSetup.separateChannelEnabled ) { - /* Decode the transport audio signals */ - IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } - - /* Identify the index of the separated channel, always LFE_CHANNEL-1 here */ - n = LFE_CHANNEL - 1; - move16(); - - /* Decode the separated channel to output[n] to be combined with the synthesized channels */ - IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[n], output_frame, 0 ) ), IVAS_ERR_OK ) ) - { - return error; - } - test(); test(); test(); @@ -882,2169 +892,761 @@ ivas_error ivas_dec_fx( test(); test(); test(); - /* Delay the separated channel to sync with CLDFB delay of the DirAC synthesis, and synthesize the LFE signal. */ IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1 ) || - EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe > 0 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) + EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || + EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && GT_16( st_ivas->hOutSetup.num_lfe, 0 ) ) ) { - ivas_lfe_synth_with_filters_fx( st_ivas->hMasa->hMasaLfeSynth, p_output_fx, output_frame, n, LFE_CHANNEL ); + Copy32( p_tc_fx[LFE_CHANNEL], p_output_fx[LFE_CHANNEL], *nSamplesRendered ); + Copy32( p_tc_fx[LFE_CHANNEL - 1], p_output_fx[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); } ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe == 0 ) { - /* Delay the separated channel to sync with the DirAC rendering */ - delay_signal32_fx( p_output_fx[n], output_frame, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_fx, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size ); - } - } - ELSE - { - IF( EQ_16( st_ivas->nSCE, 1 ) ) - { - IF( NE_32( ( error = ivas_sce_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) - { - IF( NE_32( ( error = ivas_cpe_dec_fx( st_ivas, 0, &p_output_fx[0], output_frame, nb_bits_metadata[0] ) ), IVAS_ERR_OK ) ) - { - return error; - } + Copy32( p_tc_fx[LFE_CHANNEL - 1], p_output_fx[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); } } - - IF( st_ivas->sba_dirac_stereo_flag != 0 ) /* use the flag to trigger the DFT upmix */ - { - ivas_sba_dirac_stereo_dec_fx( st_ivas, p_output_fx, output_frame ); - } - - /* HP filtering */ - FOR( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) - { - hp20_fx_32_opt( p_output_fx[n], output_frame, st_ivas->mem_hp20_out_fx[n], output_Fs ); - } - - IF( EQ_32( st_ivas->renderer_type, RENDERER_MCMASA_MONO_STEREO ) ) - { - ivas_mono_stereo_downmix_mcmasa_fx( st_ivas, p_output_fx, output_frame ); - } } } /*----------------------------------------------------------------* - * Common updates + * Write IVAS output channels + * - compensation for saturation + * - float to integer conversion *----------------------------------------------------------------*/ - IF( !st_ivas->bfi ) /* do not update if first frame(s) are lost or NO_DATA */ + st_ivas->hTcBuffer->n_samples_available = sub( st_ivas->hTcBuffer->n_samples_available, *nSamplesRendered ); + st_ivas->hTcBuffer->n_samples_rendered = add( st_ivas->hTcBuffer->n_samples_rendered, *nSamplesRendered ); + move16(); + move16(); + + /* update global combined orientation start index */ + ivas_combined_orientation_update_start_index( st_ivas->hCombinedOrientationData, *nSamplesRendered ); + + IF( st_ivas->hTcBuffer->n_samples_discard > 0 ) { - st_ivas->hDecoderConfig->last_ivas_total_brate = ivas_total_brate; - move32(); - IF( LE_32( ivas_total_brate, IVAS_SID_5k2 ) ) + FOR( n = 0; n < s_min( MAX_OUTPUT_CHANNELS, ivas_get_nchan_buffers_dec_fx( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ) ); n++ ) { - st_ivas->last_active_ivas_total_brate = st_ivas->last_active_ivas_total_brate; - move32(); + p_output_fx[n] += st_ivas->hTcBuffer->n_samples_discard; } - ELSE + *nSamplesRendered = sub( (Word16) *nSamplesRendered, st_ivas->hTcBuffer->n_samples_discard ); + move16(); + st_ivas->hTcBuffer->n_samples_discard = 0; + move16(); + } + + IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) + { + const Word32 *p_output_fx_const[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; + + nchan_out_syn_output = i_mult( BINAURAL_CHANNELS, st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); + + /* Save TD signals for pose correction if they are to be used. + * + * NOTE: Here BASOP differs from the float version. In float, we push samples to TD ring buffer in lib_dec.c function isar_render_poses. */ + IF( st_ivas->hSplitBinRend->hMultiBinTdData != NULL ) { - st_ivas->last_active_ivas_total_brate = ivas_total_brate; - move32(); + FOR( i = 0; i < nchan_out_syn_output; i++ ) + { + p_output_fx_const[i] = p_output_fx[i]; + } + ivas_TD_RINGBUF_PushChannels( st_ivas->hSplitBinRend->hMultiBinTdData, p_output_fx_const, *nSamplesRendered ); } - } - test(); - test(); - if ( LT_16( st_ivas->ini_frame, MAX_FRAME_COUNTER ) && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) ) /* keep "st_ivas->ini_frame = 0" until first good received frame */ +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + if ( st_ivas->flushing ) + { + nchan_out_syn_output = BINAURAL_CHANNELS; + move16(); + } +#endif + } + ELSE { - st_ivas->ini_frame = add( st_ivas->ini_frame, 1 ); + nchan_out_syn_output = nchan_out; move16(); } - test(); - test(); - if ( LT_16( st_ivas->ini_active_frame, MAX_FRAME_COUNTER ) && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && GT_32( ivas_total_brate, IVAS_SID_5k2 ) ) /* needed in MASA decoder in case the first active frame is BFI, and there were SID-frames decoded before */ + IF( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) { - st_ivas->ini_active_frame = add( st_ivas->ini_active_frame, 1 ); - move16(); + IF( NE_32( st_ivas->ivas_format, MONO_FORMAT ) ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec_fx( st_ivas->hLimiter, p_output_fx, nchan_out, *nSamplesRendered, st_ivas->BER_detect, output_q_factor ); +#endif + } } - st_ivas->last_ivas_format = st_ivas->ivas_format; - move32(); - pop_wmops(); + ivas_syn_output_fx( p_output_fx, output_q_factor, *nSamplesRendered, nchan_out_syn_output, data ); + *nSamplesAvailableNext = st_ivas->hTcBuffer->n_samples_available; + move16(); + + pop_wmops(); return IVAS_ERR_OK; } /*--------------------------------------------------------------------------* - * ivas_dec_feed_tc_to_renderer() + * ivas_jbm_dec_flush_renderer() * - * Feed decoded transport channels to the IVAS renderer routine - * + digest TC channels in ParamISM and ParamMC + * Flush samples if renderer granularity changes on a bitrate change in JBM *--------------------------------------------------------------------------*/ -void ivas_dec_feed_tc_to_renderer_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const Word16 nSamplesForRendering, /* i : number of TC samples available for rendering */ - Word16 *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ +ivas_error ivas_jbm_dec_flush_renderer_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 tc_granularity_new, /* i : new renderer granularity */ + const RENDERER_TYPE renderer_type_old, /* i : old renderer type */ + const AUDIO_CONFIG intern_config_old, /* i : old internal config */ + const IVAS_OUTPUT_SETUP_HANDLE hIntSetupOld, /* i : old internal output setup */ + const MC_MODE mc_mode_old, /* i : old MC mode */ + const ISM_MODE ism_mode_old, /* i : old ISM mode */ + UWord16 *nSamplesRendered, /* o : number of samples flushed */ + Word16 *data /* o : output synthesis signal Q0*/ ) { - Word32 tmp_buf_fx[MAX_JBM_L_FRAME48k]; - Word32 *p_data_fx[FOA_CHANNELS + MAX_NUM_OBJECTS]; - Word16 n, n_render_timeslots, n_ch_cldfb; - Word16 ch, offset, len_offset; + ivas_error error; + Word16 n_samples_still_available; + Word16 n_slots_still_available; + Word16 n_samples_to_render; + Word16 n_samples_granularity; DECODER_TC_BUFFER_HANDLE hTcBuffer; + Word32 *p_output_fx[MAX_LS_CHANNELS + MAX_NUM_OBJECTS]; + Word16 nchan_in, nchan_out; + Word16 ch_idx; + + + IF( !st_ivas->hDecoderConfig->Opt_tsm ) + { + return IVAS_ERR_OK; + } + + FOR( ch_idx = 0; ch_idx < ( MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS ); ch_idx++ ) + { + p_output_fx[ch_idx] = st_ivas->p_output_fx[ch_idx]; + } + *nSamplesRendered = 0; + move16(); hTcBuffer = st_ivas->hTcBuffer; - n_ch_cldfb = sub( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + n_samples_granularity = hTcBuffer->n_samples_granularity; move16(); - hTcBuffer->q_tc_fx = Q11; + /* get number of possible slots in new granularity */ + n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); + + // n_slots_still_available = n_samples_still_available / tc_granularity_new; + Word16 tmp, tmp_e; + tmp = BASOP_Util_Divide1616_Scale( n_samples_still_available, tc_granularity_new, &tmp_e ); + n_slots_still_available = shr( tmp, sub( 15, tmp_e ) ); + *nSamplesRendered = imult1616( n_slots_still_available, tc_granularity_new ); + n_samples_to_render = *nSamplesRendered; move16(); + move16(); + n_samples_still_available = sub( n_samples_still_available, n_samples_to_render ); + assert( n_samples_still_available < tc_granularity_new ); - IF( st_ivas->hDecoderConfig->Opt_tsm ) + /* update combined orientation access index */ + ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); + + IF( n_slots_still_available ) { - Word16 n_samples_still_available; - Word16 n_ch_full_copy, n_ch_res_copy; - n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); - hTcBuffer->n_samples_buffered = add( add( n_samples_still_available, nSamplesForRendering ), hTcBuffer->n_samples_discard ); - hTcBuffer->n_samples_available = i_mult( hTcBuffer->n_samples_granularity, idiv1616( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_granularity ) ); - *nSamplesResidual = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_available ); + /* render available full slots (with new lower granularity) */ + FOR( ch_idx = 0; ch_idx < s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) + { + /* move it at the beginning of the TC buffer with zero padding */ + Copy32( hTcBuffer->tc_buffer_old_fx[ch_idx], hTcBuffer->tc_fx[ch_idx], n_samples_to_render ); + set_zero_fx( hTcBuffer->tc_fx[ch_idx] + n_samples_to_render, sub( hTcBuffer->n_samples_granularity, n_samples_to_render ) ); + } + + /* simple change of the slot info */ + hTcBuffer->num_slots = 1; + hTcBuffer->nb_subframes = 1; + hTcBuffer->subframes_rendered = 0; + hTcBuffer->slots_rendered = 0; + hTcBuffer->subframe_nbslots[0] = 1; + hTcBuffer->n_samples_buffered = add( n_samples_granularity, n_samples_still_available ); + hTcBuffer->n_samples_available = 0; + hTcBuffer->n_samples_flushed = n_samples_to_render; + hTcBuffer->n_samples_rendered = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); move16(); move16(); move16(); - n_ch_full_copy = s_min( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); - n_ch_res_copy = sub( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); - /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': - in case of 'length(hTcBuffer->tc[]) < length(p_output_f[])', reset of TC buffer - pointers is needed after ivas_buffer_interleaved_to_deinterleaved() */ - len_offset = NS2SA_FX2( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ); - IF( LT_16( len_offset, L_FRAME48k ) ) + + test(); + IF( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) ) { - offset = 0; - move16(); - FOR( ch = 0; ch < s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch++ ) + IF( EQ_16( ism_mode_old, ISM_MODE_DISC ) ) { - hTcBuffer->tc_fx[ch] = &hTcBuffer->tc_buffer_fx[offset]; - st_ivas->p_output_fx[ch] = hTcBuffer->tc_fx[ch]; - offset = add( offset, len_offset ); - } - } + /* Binaural rendering */ + IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_OBJECTS_TD ) ) + { + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, n_samples_granularity ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + ELSE IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) + { + /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ + set16_fx( st_ivas->hIsmRendererData->interpolator_fx, 32767, n_samples_granularity ); // 32767=1.0f in Q15 - FOR( ch = 0; ch < n_ch_full_copy; ch++ ) - { - Copy32( hTcBuffer->tc_fx[ch], tmp_buf_fx, nSamplesForRendering ); - set_zero_fx( hTcBuffer->tc_fx[ch], hTcBuffer->n_samples_discard ); - Copy32( hTcBuffer->tc_buffer_old_fx[ch], hTcBuffer->tc_fx[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); - Copy32( tmp_buf_fx, hTcBuffer->tc_fx[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); - Copy32( tmp_buf_fx + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old_fx[ch], *nSamplesResidual ); - } + ivas_ism_render_sf_fx( st_ivas, renderer_type_old, p_output_fx, n_samples_granularity ); - IF( n_ch_res_copy > 0 ) - { - FOR( ; ch < hTcBuffer->nchan_transport_rend; ch++ ) + st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; + *st_ivas->hCrendWrapper->p_io_qfactor = 11; + + move16(); + IF( NE_32( ( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, + NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ), + IVAS_ERR_OK ) ) + { + return error; + } + } + } + ELSE { - p_data_fx[ch] = hTcBuffer->tc_fx[ch]; - Copy32( hTcBuffer->tc_fx[ch], tmp_buf_fx, nSamplesForRendering ); - Copy32( hTcBuffer->tc_buffer_old_fx[ch], p_data_fx[ch], n_samples_still_available ); - Copy32( tmp_buf_fx, p_data_fx[ch] + n_samples_still_available, sub( nSamplesForRendering, *nSamplesResidual ) ); - Copy32( tmp_buf_fx + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old_fx[ch], *nSamplesResidual ); + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong ISM_MODE in VoIP renderer flushing!" ); } } - - n_render_timeslots = idiv1616( st_ivas->hTcBuffer->n_samples_available, st_ivas->hTcBuffer->n_samples_granularity ); - } - ELSE - { - FOR( n = 0; n < n_ch_cldfb; n++ ) + ELSE IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) { - p_data_fx[n] = &st_ivas->p_output_fx[n][0]; - move16(); - } + IF( EQ_16( mc_mode_old, MC_MODE_MCT ) ) + { + Word16 crendInPlaceRotation = FALSE; - ch = s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); - FOR( n = 0; n < ch; n++ ) - { - hTcBuffer->tc_fx[n] = st_ivas->p_output_fx[n]; /* note: buffers needed in the TD decorellator */ - move16(); - } + test(); + test(); + test(); + IF( NE_16( st_ivas->transport_config, intern_config_old ) && ( EQ_16( intern_config_old, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( intern_config_old, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_16( intern_config_old, IVAS_AUDIO_CONFIG_HOA3 ) ) ) + { + IF( GT_16( sub( add( hIntSetupOld->nchan_out_woLFE, hIntSetupOld->num_lfe ), add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ) ), 0 ) ) + { + crendInPlaceRotation = TRUE; + move16(); + ivas_mc2sba_fx( st_ivas->hTransSetup, hTcBuffer->tc_fx, p_output_fx, hTcBuffer->n_samples_granularity, hIntSetupOld->ambisonics_order, GAIN_LFE_FX ); + } + } - hTcBuffer->n_samples_buffered = nSamplesForRendering; - hTcBuffer->n_samples_available = hTcBuffer->n_samples_buffered; - *nSamplesResidual = 0; - move16(); - move16(); - move16(); + test(); + IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_MIXER_CONV ) || EQ_16( renderer_type_old, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) + { + st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; + IF( NE_32( ( error = getAudioConfigNumChannels( intern_config_old, &nchan_in ) ), IVAS_ERR_OK ) ) + { + return error; + } - n_render_timeslots = DEFAULT_JBM_CLDFB_TIMESLOTS; - move16(); - } + IF( NE_32( ( error = getAudioConfigNumChannels( st_ivas->hOutSetup.output_config, &nchan_out ) ), IVAS_ERR_OK ) ) + { + return error; + } - /* CLDFB analysis for ParamMC/ParamISM */ - test(); - test(); - test(); - test(); - test(); - test(); - IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) && ( EQ_32( st_ivas->renderer_type, RENDERER_PARAM_ISM ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) ) - { - ivas_param_ism_dec_digest_tc_fx( st_ivas, n_render_timeslots, p_data_fx, Q11 ); - } - ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_PARAMMC ) && EQ_32( hTcBuffer->tc_buffer_mode, TC_BUFFER_MODE_RENDERER ) ) - { - ivas_param_mc_dec_digest_tc_fx( st_ivas, (UWord8) n_render_timeslots, p_data_fx, Q11 ); - } + Word16 subframe_len, gd_bits; + subframe_len = imult1616( st_ivas->hTcBuffer->subframe_nbslots[0], n_samples_granularity ); + gd_bits = find_guarded_bits_fx( subframe_len ); + *st_ivas->hCrendWrapper->p_io_qfactor = sub( 13, gd_bits ); + FOR( Word16 i = 0; i < nchan_in; i++ ) + { + scale_sig32( p_output_fx[i], *nSamplesRendered, sub( *st_ivas->hCrendWrapper->p_io_qfactor, Q11 ) ); // Q = *st_ivas->hCrendWrapper->p_io_qfactor + } - hTcBuffer->n_samples_rendered = 0; - move16(); - hTcBuffer->subframes_rendered = 0; - move16(); + IF( NE_32( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, hIntSetupOld, st_ivas->hEFAPdata, st_ivas->hTcBuffer, crendInPlaceRotation ? p_output_fx : st_ivas->hTcBuffer->tc_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ), IVAS_ERR_OK ) ) + { + return error; + } - return; -} + ivas_binaural_add_LFE_fx( st_ivas, n_samples_granularity, hTcBuffer->tc_fx, p_output_fx ); + FOR( Word16 i = 0; i < nchan_in; i++ ) + { + scale_sig32( p_output_fx[i], *nSamplesRendered, sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 + } + } + ELSE IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_OBJECTS_TD ) ) + { + IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, n_samples_granularity ) ), IVAS_ERR_OK ) ) + { + return error; + } -/*--------------------------------------------------------------------------* - * ivas_dec_render() - * - * Principal IVAS internal rendering routine - *--------------------------------------------------------------------------*/ + ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, hTcBuffer->tc_fx, p_output_fx ); + } + ELSE + { + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong renderer in MCT VoIP renderer flushing!" ); + } + } + ELSE + { + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong MC_MODE in VoIP renderer flushing!" ); + } + } + ELSE IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) || EQ_16( st_ivas->ivas_format, MASA_FORMAT ) ) + { + IF( EQ_16( ism_mode_old, ISM_MASA_MODE_DISC ) ) + { + Word32 *tc_local_fx[MAX_NUM_OBJECTS]; + Word16 last_dirac_md_idx; + UWord16 nSamplesAvailableNext; + ISM_MODE ism_mode_orig; + RENDERER_TYPE renderer_type_orig; + Word32 ivas_total_brate; -ivas_error ivas_dec_render_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const UWord16 nSamplesAsked, /* i : number of samples wanted */ - UWord16 *nSamplesRendered, /* o : number of samples rendered */ - UWord16 *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ - Word16 *data /* o : output synthesis signal Q0*/ -) -{ - Word16 n, nchan_out; - Word16 nchan_transport_rend; - Word16 nchan_remapped; - Word32 output_Fs; - AUDIO_CONFIG output_config; - Word16 nSamplesAskedLocal; - ivas_error error; - Word32 *p_output_fx[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; - Word32 *p_tc_fx[MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS]; - Word16 subframe_len, gd_bits, exp, nchan_in, i, j, ch; - const Word16 output_q_factor = Q11; - move16(); - Word16 nchan_out_syn_output; - - push_wmops( "ivas_dec_render" ); - /*----------------------------------------------------------------* - * Initialization of local vars after struct has been set - *----------------------------------------------------------------*/ - - output_Fs = st_ivas->hDecoderConfig->output_Fs; - move32(); - nchan_out = st_ivas->hDecoderConfig->nchan_out; - move16(); - nchan_transport_rend = st_ivas->hTcBuffer->nchan_transport_rend; - move16(); - output_config = st_ivas->hDecoderConfig->output_config; - move32(); - nSamplesAskedLocal = add( nSamplesAsked, st_ivas->hTcBuffer->n_samples_discard ); - move16(); - - FOR( n = 0; n < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; n++ ) - { - p_output_fx[n] = st_ivas->p_output_fx[n]; - } - - IF( !st_ivas->hDecoderConfig->Opt_tsm ) - { - FOR( n = 0; n < MAX_INTERN_CHANNELS; n++ ) - { - st_ivas->hTcBuffer->tc_fx[n] = st_ivas->p_output_fx[n]; - } - } - - FOR( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) - { - p_tc_fx[n] = &st_ivas->hTcBuffer->tc_fx[n][st_ivas->hTcBuffer->n_samples_rendered]; - } - - /*----------------------------------------------------------------* - * Update combined orientation access index - *----------------------------------------------------------------*/ - - IF( st_ivas->hCombinedOrientationData != NULL ) - { - /* take the discard samples into account here to make sure head rotation stays on the correct 5ms grid */ - st_ivas->hCombinedOrientationData->cur_subframe_samples_rendered_start = sub( st_ivas->hCombinedOrientationData->cur_subframe_samples_rendered_start, st_ivas->hTcBuffer->n_samples_discard ); - move16(); - - ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); - } - - /*----------------------------------------------------------------* - * Rendering - *----------------------------------------------------------------*/ - - *nSamplesRendered = s_min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); - move16(); - - test(); - test(); - IF( EQ_32( st_ivas->ivas_format, UNDEFINED_FORMAT ) ) - { - assert( 0 ); - } - ELSE IF( EQ_32( st_ivas->hTcBuffer->tc_buffer_mode, TC_BUFFER_MODE_BUFFER ) ) - { - ivas_dec_tc_buffer_playout_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->ivas_format, MONO_FORMAT ) || EQ_32( st_ivas->ivas_format, STEREO_FORMAT ) ) - { - /* Rendering */ - IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) - { - ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc_fx, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) ) - { - ivas_apply_non_diegetic_panning_fx( p_tc_fx[0], p_output_fx, st_ivas->hDecoderConfig->non_diegetic_pan_gain_fx, *nSamplesRendered ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - ivas_stereo2sba_fx( p_tc_fx, p_output_fx, *nSamplesRendered ); - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, ISM_FORMAT ) ) - { - /* Rendering */ - IF( EQ_32( st_ivas->ism_mode, ISM_MODE_PARAM ) ) - { - test(); - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) - { - ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, st_ivas->nchan_transport, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_PARAM_ISM ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - ivas_param_ism_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ); - - IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - /* Convert CICP19 -> Ambisonics */ - ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); - } - } - } - ELSE /* ISM_MODE_DISC */ - { - test(); - test(); - /* Loudspeaker or Ambisonics rendering */ - IF( EQ_32( st_ivas->renderer_type, RENDERER_TD_PANNING ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ - ivas_ism_render_sf_fx( st_ivas, st_ivas->renderer_type, p_output_fx, *nSamplesRendered ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_NON_DIEGETIC_DOWNMIX ) ) - { - ivas_apply_non_diegetic_panning_fx( p_tc_fx[0], p_output_fx, st_ivas->hDecoderConfig->non_diegetic_pan_gain_fx, *nSamplesRendered ); - } -#ifdef DEBUGGING - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) ) -#else - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) -#endif - { - /* Convert to Ambisonics */ - FOR( i = 0; i < st_ivas->nchan_transport; i++ ) - { - FOR( j = 0; j < HOA3_CHANNELS; j++ ) - { - st_ivas->hIsmRendererData->gains_fx[i][j] = L_shr( st_ivas->hIsmRendererData->gains_fx[i][j], 1 ); // Q30 -> Q29 - move32(); - st_ivas->hIsmRendererData->prev_gains_fx[i][j] = L_shr( st_ivas->hIsmRendererData->prev_gains_fx[i][j], 1 ); // Q30 -> Q29 - move32(); - } - } - - ivas_ism2sba_sf_fx( p_tc_fx, p_output_fx, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); - - Word16 sba_num_chans = imult1616( add( st_ivas->hIntSetup.ambisonics_order, 1 ), add( st_ivas->hIntSetup.ambisonics_order, 1 ) ); - FOR( j = 0; j < sba_num_chans; j++ ) - { - scale_sig32( p_output_fx[j], *nSamplesRendered, sub( Q11, sub( add( output_q_factor, 29 ), 31 ) ) ); // Q11 - } - - FOR( i = 0; i < st_ivas->nchan_transport; i++ ) - { - FOR( j = 0; j < 16; j++ ) - { - st_ivas->hIsmRendererData->gains_fx[i][j] = L_shl( st_ivas->hIsmRendererData->gains_fx[i][j], 1 ); // Q29 -> Q30 - move32(); - st_ivas->hIsmRendererData->prev_gains_fx[i][j] = L_shl( st_ivas->hIsmRendererData->prev_gains_fx[i][j], 1 ); // Q29 -> Q30 - move32(); - } - } - } - - /* Binaural rendering */ - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) - { - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - IF( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output_fx, *nSamplesRendered ) ) != IVAS_ERR_OK ) - { - return error; - } - } - ELSE - { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; - subframe_len = imult1616( st_ivas->hTcBuffer->subframe_nbslots[0], st_ivas->hTcBuffer->n_samples_granularity ); - gd_bits = find_guarded_bits_fx( subframe_len ); - exp = 13; - move16(); - nchan_in = 12; - move16(); - nchan_out = 2; - move16(); - exp = sub( exp, gd_bits ); - *st_ivas->hCrendWrapper->p_io_qfactor = exp; + /* copy from ISM delay buffer to the correct place in TCs */ move16(); - FOR( i = 0; i < nchan_in; i++ ) + FOR( ch_idx = 0; ch_idx < st_ivas->nchan_ism; ch_idx++ ) { - scale_sig32( p_output_fx[i], *nSamplesRendered, negate( sub( 11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q11 + tc_local_fx[ch_idx] = &st_ivas->hTcBuffer->tc_fx[ch_idx + 2][hTcBuffer->n_samples_rendered]; + Copy32( st_ivas->hMasaIsmData->delayBuffer_fx[ch_idx], tc_local_fx[ch_idx], st_ivas->hMasaIsmData->delayBuffer_size ); /*Q11*/ } - IF( NE_32( ( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs, 0 ) ), IVAS_ERR_OK ) ) - { - return error; - } + /* to render flushed samples, use configuration from the last received frame */ + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + renderer_type_orig = st_ivas->renderer_type; + ism_mode_orig = st_ivas->ism_mode; + st_ivas->ism_mode = ism_mode_old; + st_ivas->renderer_type = renderer_type_old; + st_ivas->hDecoderConfig->ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; + last_dirac_md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[st_ivas->hSpatParamRendCom->slots_rendered - 1]; - FOR( i = 0; i < nchan_out; i++ ) - { - scale_sig32( p_output_fx[i], *nSamplesRendered, sub( 11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 - } - } - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) || EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) - { - nchan_remapped = nchan_transport_rend; - move16(); + /* transfer adapted sf info from hTcBuffer to DirAC */ + st_ivas->hSpatParamRendCom->nb_subframes = 1; + st_ivas->hSpatParamRendCom->subframes_rendered = 0; + st_ivas->hSpatParamRendCom->subframe_nbslots[0] = JBM_CLDFB_SLOTS_IN_SUBFRAME; + st_ivas->hSpatParamRendCom->slots_rendered = 0; + st_ivas->hSpatParamRendCom->num_slots = JBM_CLDFB_SLOTS_IN_SUBFRAME; + set16_fx( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); - test(); - test(); - /* Loudspeakers, Ambisonics or Binaural rendering */ - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) - { - ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->ivas_format, MASA_FORMAT ) ) - { - IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) ) - { - ivas_dirac_dec_render_fx( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ); - } - } - ELSE - { - IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) - { - nchan_remapped = st_ivas->nchan_transport; - move16(); - test(); - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) - { - test(); - IF( EQ_32( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) ) - { - IF( NE_32( ( error = ivas_omasa_dirac_td_binaural_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - ELSE - { - ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); - } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) ) - { - ivas_omasa_dirac_rend_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OMASA_OBJECT_EXT ) || EQ_32( st_ivas->renderer_type, RENDERER_OMASA_MIX_EXT ) ) - { - ivas_dec_tc_buffer_playout_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output_fx ); - ivas_omasa_rearrange_channels_fx( p_output_fx, st_ivas->nchan_ism, *nSamplesRendered ); - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) - { - nchan_remapped = nchan_transport_rend; - move16(); - - /* Loudspeakers, Ambisonics or Binaural rendering */ - IF( EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) - { - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) ) - { - SPAR_DEC_HANDLE hSpar; - hSpar = st_ivas->hSpar; - hSpar->hMdDec->Q_mixer_mat = 30; - move16(); - - IF( NE_32( ( error = ivas_osba_dirac_td_binaural_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OSBA_STEREO ) ) - { - test(); - /* shift SBA channels to avoid overwrite by ISM upmix in 1 object case and non-TSM unified channel memory*/ - IF( EQ_16( st_ivas->nchan_ism, 1 ) && EQ_16( st_ivas->hDecoderConfig->Opt_tsm, 0 ) ) - { - Copy32( p_tc_fx[2], p_output_fx[3], *nSamplesRendered ); - Copy32( p_tc_fx[1], p_output_fx[2], *nSamplesRendered ); - p_tc_fx[1] = p_output_fx[2]; - p_tc_fx[2] = p_output_fx[3]; - } - - /* render objects */ - ivas_ism_render_sf_fx( st_ivas, st_ivas->renderer_type, p_output_fx, *nSamplesRendered ); - - /* add already rendered SBA part */ - ivas_osba_stereo_add_channels_fx( p_tc_fx, p_output_fx, st_ivas->hSbaIsmData->gain_bed_fx, nchan_out, st_ivas->nchan_ism, st_ivas->ism_mode, *nSamplesRendered ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_OSBA_AMBI ) || EQ_32( st_ivas->renderer_type, RENDERER_OSBA_LS ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) - { - IF( NE_32( ( error = ivas_osba_render_sf_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) /*EXT output = individual objects + HOA3*/ - { - IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, &p_output_fx[st_ivas->nchan_ism] ) ), IVAS_ERR_OK ) ) - { - return error; - } - - FOR( n = 0; n < st_ivas->nchan_ism; n++ ) - { - Copy32( p_tc_fx[n], p_output_fx[n], *nSamplesRendered ); - } - } - ELSE - { - IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) - { - ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); - - FOR( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) - { - scale_sig32( p_output_fx[n], *nSamplesRendered, 1 ); - } - } - ELSE - { - IF( NE_32( ( error = ivas_sba_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) - { - FOR( n = st_ivas->hIntSetup.nchan_out_woLFE - 1; n >= 0; n-- ) - { - Copy32( p_output_fx[n], p_output_fx[n + st_ivas->nchan_ism], *nSamplesRendered ); - } - FOR( n = 0; n < st_ivas->nchan_ism; n++ ) - { - set32_fx( p_output_fx[n], 0, *nSamplesRendered ); - } - } - FOR( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) - { - scale_sig32( p_output_fx[n], *nSamplesRendered, 1 ); - } - } - } - ELSE IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) ) - { - IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) ) - { - Word16 crendInPlaceRotation = FALSE; - move16(); - - test(); - test(); - test(); - IF( NE_32( st_ivas->transport_config, st_ivas->intern_config ) && ( EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) - { - IF( LT_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) - { - crendInPlaceRotation = TRUE; - move16(); - - ivas_mc2sba_fx( st_ivas->hTransSetup, p_tc_fx, p_output_fx, *nSamplesRendered, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE_FX ); - } - } - - /* Rendering */ - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; - subframe_len = imult1616( st_ivas->hTcBuffer->subframe_nbslots[0], st_ivas->hTcBuffer->n_samples_granularity ); - gd_bits = find_guarded_bits_fx( subframe_len ); - exp = 13; - move16(); - IF( NE_32( ( error = getAudioConfigNumChannels( st_ivas->intern_config, &nchan_in ) ), IVAS_ERR_OK ) ) - { - return error; - } - IF( NE_32( ( error = getAudioConfigNumChannels( st_ivas->hOutSetup.output_config, &nchan_out ) ), IVAS_ERR_OK ) ) - { - return error; - } - exp = sub( exp, gd_bits ); - *st_ivas->hCrendWrapper->p_io_qfactor = exp; - move16(); - - IF( crendInPlaceRotation ) - { - FOR( i = 0; i < nchan_in; i++ ) - { - scale_sig32( p_output_fx[i], *nSamplesRendered, negate( sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q = *st_ivas->hCrendWrapper->p_io_qfactor - } - } - ELSE - { - FOR( i = 0; i < nchan_in; i++ ) - { - scale_sig32( p_tc_fx[i], *nSamplesRendered, negate( sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ) ); // Q = *st_ivas->hCrendWrapper->p_io_qfactor - } - } - - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - IF( ( error = ivas_rend_crendProcessSubframesSplitBin( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, ( st_ivas->hSplitBinRend == NULL ) ? NULL : &st_ivas->hSplitBinRend->splitrend.multiBinPoseData, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, - &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - ELSE - { - IF( NE_32( ( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, st_ivas->intern_config, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, - &st_ivas->hIntSetup, st_ivas->hEFAPdata, st_ivas->hTcBuffer, p_output_fx, p_output_fx, *nSamplesRendered, output_Fs, 0 ) ), - IVAS_ERR_OK ) ) - { - return error; - } - - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); - } - - IF( crendInPlaceRotation ) - { - n = nchan_in; - } - ELSE - { - n = nchan_out; - } - move16(); - - FOR( i = 0; i < n; i++ ) - { - scale_sig32( p_output_fx[i], *nSamplesRendered, sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 - } - - FOR( i = n; i < nchan_in; i++ ) - { - scale_sig32( p_tc_fx[i], *nSamplesRendered, sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 - } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) - { - ivas_ls_setup_conversion_fx( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc_fx, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - ivas_mc2sba_fx( st_ivas->hIntSetup, p_tc_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) ) - { - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - else + IF( ( error = ivas_omasa_dirac_td_binaural_fx( st_ivas, (UWord16) hTcBuffer->n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, CPE_CHANNELS, p_output_fx ) ) != IVAS_ERR_OK ) { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, *nSamplesRendered ) ), IVAS_ERR_OK ) ) - { - return error; - } - - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_tc_fx, p_output_fx ); - } - } - } - ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) - { - ivas_mc_paramupmix_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_tc_fx, p_output_fx ); - - /* Rendering */ - test(); - test(); - IF( ( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) && !st_ivas->hDecoderConfig->Opt_Headrotation ) - { - /* handled in CLDFB domain already */ - IF( NE_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) && NE_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, p_output_fx, p_output_fx ); - } - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_MC ) ) - { - ivas_ls_setup_conversion_fx( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, *nSamplesRendered, p_output_fx, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); - } - } - ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_PARAMMC ) ) - { - Word16 channel_active_fx[MAX_OUTPUT_CHANNELS]; - Word16 nchan_out_cov; - Word16 nchan_out_cldfb = 0; - move16(); - - set16_fx( channel_active_fx, 0, MAX_LS_CHANNELS ); - Word16 nchan_transport_tmp = st_ivas->nchan_transport; - move16(); - output_Fs = st_ivas->hDecoderConfig->output_Fs; - move32(); - Word16 nchan_out_transport = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ); - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_FASTCONV_ROOM ) ) - { - nchan_out_cldfb = BINAURAL_CHANNELS; - move16(); - set16_fx( channel_active_fx, 1, BINAURAL_CHANNELS ); - nchan_out_cov = add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ); - } - ELSE IF( EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_LS_CONV_CLDFB ) ) - { - nchan_out_cov = nchan_out_transport; - move16(); - nchan_out_cldfb = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); - } - ELSE IF( EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_LS_CONV_COV ) || EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_MONO_STEREO ) ) - { - nchan_out_cov = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); - nchan_out_cldfb = nchan_out_cov; - move16(); - set16_fx( channel_active_fx, 1, nchan_out_cov ); - } - ELSE - { - nchan_out_cov = nchan_out_transport; - move16(); - nchan_out_cldfb = nchan_out_transport; - move16(); - set16_fx( channel_active_fx, 1, nchan_out_cov ); - } - IF( st_ivas->hParamMC->max_band_decorr > 0 ) - { - Word16 tmp; - tmp = L_norm_arr( st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_fx, st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_len ); - scale_sig32( st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_fx, st_ivas->hParamMC->h_freq_domain_decorr_ap_state->decorr_buffer_len, tmp ); // Q(st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer+ tmp) - st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer = add( st_ivas->hParamMC->h_freq_domain_decorr_ap_state->q_decorr_buffer, tmp ); - move16(); - } - /* CLDFB synthesis */ - FOR( ch = 0; ch < nchan_out_cldfb; ch++ ) - { - IF( st_ivas->cldfbSynDec[ch] ) - { - scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, ( Q5 - Q11 ) ); // Q5 - st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q5; - move16(); - } - } - Word16 tempp; - FOR( Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->num_param_bands_synth; param_band_idx++ ) - { - tempp = getScaleFactor32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_len ); - scale_sig32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_len, tempp ); // Q(31-(st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx]- tempp)) - st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx] = sub( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx], tempp ); - move16(); - - IF( LT_16( st_ivas->hParamMC->band_grouping[param_band_idx], st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr ) ) - { - tempp = getScaleFactor32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_len ); - scale_sig32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_len, tempp ); // Q(31- (st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx] - tempp)) - st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx] = sub( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx], tempp ); - move16(); - } - } - - ivas_param_mc_dec_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx, channel_active_fx ); - - FOR( ch = 0; ch < nchan_out_cldfb; ch++ ) - { - IF( st_ivas->cldfbSynDec[ch] ) - { - scale_sig32( st_ivas->cldfbSynDec[ch]->cldfb_state_fx, st_ivas->cldfbSynDec[ch]->cldfb_size, Q11 - Q5 ); // Q11 - st_ivas->cldfbSynDec[ch]->Q_cldfb_state = Q11; - move16(); - } - } - IF( EQ_16( st_ivas->hParamMC->slots_rendered, st_ivas->hParamMC->num_slots ) ) - { - FOR( Word16 param_band_idx = 0; param_band_idx < st_ivas->hParamMC->hMetadataPMC->nbands_coded; param_band_idx++ ) - { - IF( LT_16( st_ivas->hParamMC->band_grouping[param_band_idx], st_ivas->hParamMC->h_output_synthesis_params.max_band_decorr ) ) - { - Copy32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_fx[param_band_idx], imult1616( nchan_transport_tmp, nchan_out_cov ) ); - st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_old_exp[param_band_idx] = st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_res_exp[param_band_idx]; - move16(); - } - Copy32( st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_fx[param_band_idx], st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_old_fx[param_band_idx], imult1616( nchan_transport_tmp, nchan_out_cov ) ); - st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_old_exp[param_band_idx] = st_ivas->hParamMC->h_output_synthesis_cov_state.mixing_matrix_exp[param_band_idx]; - move16(); - } - } - } - ELSE IF( EQ_32( st_ivas->mc_mode, MC_MODE_MCMASA ) ) - { - nchan_remapped = st_ivas->nchan_transport; - move16(); - - test(); - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC ) || EQ_32( st_ivas->renderer_type, RENDERER_BINAURAL_PARAMETRIC_ROOM ) || EQ_32( st_ivas->renderer_type, RENDERER_STEREO_PARAMETRIC ) ) - { - ivas_dirac_dec_binaural_render_fx( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output_fx ); - } - ELSE IF( EQ_32( st_ivas->renderer_type, RENDERER_DIRAC ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) /* rendering to CICPxx and Ambisonics */ - { - ivas_dirac_dec_render_fx( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output_fx ); - - test(); - test(); - test(); - IF( EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) - { - /* we still need to copy the separate channel if available */ - IF( st_ivas->hOutSetup.separateChannelEnabled ) - { - Copy32( p_tc_fx[LFE_CHANNEL - 1], p_output_fx[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); - } - - ivas_mc2sba_fx( st_ivas->hIntSetup, p_output_fx, p_output_fx, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0 ); - } - ELSE IF( EQ_32( st_ivas->intern_config, IVAS_AUDIO_CONFIG_5_1 ) && ( EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1 ) ) ) - { - FOR( n = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; n < ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ); n++ ) - { - set32_fx( p_output_fx[n], 0, *nSamplesRendered ); - } - } - } - - /* copy discrete C and TD LFE from internal TC to output */ - IF( st_ivas->hOutSetup.separateChannelEnabled ) - { - test(); - test(); - test(); - test(); - test(); - test(); - test(); - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1 ) || - EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || - EQ_32( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && GT_16( st_ivas->hOutSetup.num_lfe, 0 ) ) ) - { - Copy32( p_tc_fx[LFE_CHANNEL], p_output_fx[LFE_CHANNEL], *nSamplesRendered ); - Copy32( p_tc_fx[LFE_CHANNEL - 1], p_output_fx[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); - } - ELSE IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe == 0 ) - { - Copy32( p_tc_fx[LFE_CHANNEL - 1], p_output_fx[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); - } - } - } - } - - /*----------------------------------------------------------------* - * Write IVAS output channels - * - compensation for saturation - * - float to integer conversion - *----------------------------------------------------------------*/ - - st_ivas->hTcBuffer->n_samples_available = sub( st_ivas->hTcBuffer->n_samples_available, *nSamplesRendered ); - st_ivas->hTcBuffer->n_samples_rendered = add( st_ivas->hTcBuffer->n_samples_rendered, *nSamplesRendered ); - move16(); - move16(); - - /* update global combined orientation start index */ - ivas_combined_orientation_update_start_index( st_ivas->hCombinedOrientationData, *nSamplesRendered ); - - IF( st_ivas->hTcBuffer->n_samples_discard > 0 ) - { - FOR( n = 0; n < s_min( MAX_OUTPUT_CHANNELS, ivas_get_nchan_buffers_dec_fx( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ) ); n++ ) - { - p_output_fx[n] += st_ivas->hTcBuffer->n_samples_discard; - } - *nSamplesRendered = sub( (Word16) *nSamplesRendered, st_ivas->hTcBuffer->n_samples_discard ); - move16(); - st_ivas->hTcBuffer->n_samples_discard = 0; - move16(); - } - - IF( EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED ) || EQ_32( output_config, IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) ) - { - const Word32 *p_output_fx_const[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; - - nchan_out_syn_output = i_mult( BINAURAL_CHANNELS, st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses ); - - /* Save TD signals for pose correction if they are to be used. - * - * NOTE: Here BASOP differs from the float version. In float, we push samples to TD ring buffer in lib_dec.c function isar_render_poses. */ - IF( st_ivas->hSplitBinRend->hMultiBinTdData != NULL ) - { - FOR( i = 0; i < nchan_out_syn_output; i++ ) - { - p_output_fx_const[i] = p_output_fx[i]; - } - ivas_TD_RINGBUF_PushChannels( st_ivas->hSplitBinRend->hMultiBinTdData, p_output_fx_const, *nSamplesRendered ); - } - -#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR - if ( st_ivas->flushing ) - { - nchan_out_syn_output = BINAURAL_CHANNELS; - move16(); - } -#endif - } - ELSE - { - nchan_out_syn_output = nchan_out; - move16(); - } - - IF( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) - { - IF( NE_32( st_ivas->ivas_format, MONO_FORMAT ) ) - { -#ifndef DISABLE_LIMITER - ivas_limiter_dec_fx( st_ivas->hLimiter, p_output_fx, nchan_out, *nSamplesRendered, st_ivas->BER_detect, output_q_factor ); -#endif - } - } - - ivas_syn_output_fx( p_output_fx, output_q_factor, *nSamplesRendered, nchan_out_syn_output, data ); - - *nSamplesAvailableNext = st_ivas->hTcBuffer->n_samples_available; - move16(); - - pop_wmops(); - return IVAS_ERR_OK; -} - -/*--------------------------------------------------------------------------* - * ivas_jbm_dec_flush_renderer() - * - * Flush samples if renderer granularity changes on a bitrate change in JBM - *--------------------------------------------------------------------------*/ - -ivas_error ivas_jbm_dec_flush_renderer_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const Word16 tc_granularity_new, /* i : new renderer granularity */ - const RENDERER_TYPE renderer_type_old, /* i : old renderer type */ - const AUDIO_CONFIG intern_config_old, /* i : old internal config */ - const IVAS_OUTPUT_SETUP_HANDLE hIntSetupOld, /* i : old internal output setup */ - const MC_MODE mc_mode_old, /* i : old MC mode */ - const ISM_MODE ism_mode_old, /* i : old ISM mode */ - UWord16 *nSamplesRendered, /* o : number of samples flushed */ - Word16 *data /* o : output synthesis signal Q0*/ -) -{ - ivas_error error; - Word16 n_samples_still_available; - Word16 n_slots_still_available; - Word16 n_samples_to_render; - Word16 n_samples_granularity; - DECODER_TC_BUFFER_HANDLE hTcBuffer; - Word32 *p_output_fx[MAX_LS_CHANNELS + MAX_NUM_OBJECTS]; - Word16 nchan_in, nchan_out; - Word16 ch_idx; - - - IF( !st_ivas->hDecoderConfig->Opt_tsm ) - { - return IVAS_ERR_OK; - } - - FOR( ch_idx = 0; ch_idx < ( MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS ); ch_idx++ ) - { - p_output_fx[ch_idx] = st_ivas->p_output_fx[ch_idx]; - } - - *nSamplesRendered = 0; - move16(); - hTcBuffer = st_ivas->hTcBuffer; - n_samples_granularity = hTcBuffer->n_samples_granularity; - move16(); - - /* get number of possible slots in new granularity */ - n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); - - // n_slots_still_available = n_samples_still_available / tc_granularity_new; - Word16 tmp, tmp_e; - tmp = BASOP_Util_Divide1616_Scale( n_samples_still_available, tc_granularity_new, &tmp_e ); - n_slots_still_available = shr( tmp, sub( 15, tmp_e ) ); - *nSamplesRendered = imult1616( n_slots_still_available, tc_granularity_new ); - n_samples_to_render = *nSamplesRendered; - move16(); - move16(); - n_samples_still_available = sub( n_samples_still_available, n_samples_to_render ); - assert( n_samples_still_available < tc_granularity_new ); - - /* update combined orientation access index */ - ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); - - IF( n_slots_still_available ) - { - - /* render available full slots (with new lower granularity) */ - FOR( ch_idx = 0; ch_idx < s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) - { - /* move it at the beginning of the TC buffer with zero padding */ - Copy32( hTcBuffer->tc_buffer_old_fx[ch_idx], hTcBuffer->tc_fx[ch_idx], n_samples_to_render ); - set_zero_fx( hTcBuffer->tc_fx[ch_idx] + n_samples_to_render, sub( hTcBuffer->n_samples_granularity, n_samples_to_render ) ); - } - - /* simple change of the slot info */ - hTcBuffer->num_slots = 1; - hTcBuffer->nb_subframes = 1; - hTcBuffer->subframes_rendered = 0; - hTcBuffer->slots_rendered = 0; - hTcBuffer->subframe_nbslots[0] = 1; - hTcBuffer->n_samples_buffered = add( n_samples_granularity, n_samples_still_available ); - hTcBuffer->n_samples_available = 0; - hTcBuffer->n_samples_flushed = n_samples_to_render; - hTcBuffer->n_samples_rendered = 0; - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - - - test(); - IF( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) ) - { - IF( EQ_16( ism_mode_old, ISM_MODE_DISC ) ) - { - /* Binaural rendering */ - IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_OBJECTS_TD ) ) - { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, n_samples_granularity ) ), IVAS_ERR_OK ) ) - { - return error; - } - } - ELSE IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ - set16_fx( st_ivas->hIsmRendererData->interpolator_fx, 32767, n_samples_granularity ); // 32767=1.0f in Q15 - - ivas_ism_render_sf_fx( st_ivas, renderer_type_old, p_output_fx, n_samples_granularity ); - - st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; - *st_ivas->hCrendWrapper->p_io_qfactor = 11; - - move16(); - IF( NE_32( ( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, - NULL, NULL, st_ivas->hTcBuffer, p_output_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ), - IVAS_ERR_OK ) ) - { - return error; - } - } - } - ELSE - { - return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong ISM_MODE in VoIP renderer flushing!" ); - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) - { - IF( EQ_16( mc_mode_old, MC_MODE_MCT ) ) - { - Word16 crendInPlaceRotation = FALSE; - - test(); - test(); - test(); - IF( NE_16( st_ivas->transport_config, intern_config_old ) && ( EQ_16( intern_config_old, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( intern_config_old, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_16( intern_config_old, IVAS_AUDIO_CONFIG_HOA3 ) ) ) - { - IF( GT_16( sub( add( hIntSetupOld->nchan_out_woLFE, hIntSetupOld->num_lfe ), add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ) ), 0 ) ) - { - crendInPlaceRotation = TRUE; - move16(); - ivas_mc2sba_fx( st_ivas->hTransSetup, hTcBuffer->tc_fx, p_output_fx, hTcBuffer->n_samples_granularity, hIntSetupOld->ambisonics_order, GAIN_LFE_FX ); - } - } - - test(); - IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_MIXER_CONV ) || EQ_16( renderer_type_old, RENDERER_BINAURAL_MIXER_CONV_ROOM ) ) - { - st_ivas->hCrendWrapper->p_io_qfactor = &st_ivas->hCrendWrapper->io_qfactor; - IF( NE_32( ( error = getAudioConfigNumChannels( intern_config_old, &nchan_in ) ), IVAS_ERR_OK ) ) - { - return error; - } - - IF( NE_32( ( error = getAudioConfigNumChannels( st_ivas->hOutSetup.output_config, &nchan_out ) ), IVAS_ERR_OK ) ) - { - return error; - } - - Word16 subframe_len, gd_bits; - subframe_len = imult1616( st_ivas->hTcBuffer->subframe_nbslots[0], n_samples_granularity ); - gd_bits = find_guarded_bits_fx( subframe_len ); - *st_ivas->hCrendWrapper->p_io_qfactor = sub( 13, gd_bits ); - FOR( Word16 i = 0; i < nchan_in; i++ ) - { - scale_sig32( p_output_fx[i], *nSamplesRendered, sub( *st_ivas->hCrendWrapper->p_io_qfactor, Q11 ) ); // Q = *st_ivas->hCrendWrapper->p_io_qfactor - } - - IF( NE_32( error = ivas_rend_crendProcessSubframe_fx( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, hIntSetupOld, st_ivas->hEFAPdata, st_ivas->hTcBuffer, crendInPlaceRotation ? p_output_fx : st_ivas->hTcBuffer->tc_fx, p_output_fx, hTcBuffer->n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ), IVAS_ERR_OK ) ) - { - return error; - } - - ivas_binaural_add_LFE_fx( st_ivas, n_samples_granularity, hTcBuffer->tc_fx, p_output_fx ); - - FOR( Word16 i = 0; i < nchan_in; i++ ) - { - scale_sig32( p_output_fx[i], *nSamplesRendered, sub( Q11, *st_ivas->hCrendWrapper->p_io_qfactor ) ); // Q11 - } - } - ELSE IF( EQ_16( renderer_type_old, RENDERER_BINAURAL_OBJECTS_TD ) ) - { - IF( NE_32( ( error = ivas_td_binaural_renderer_sf_fx( st_ivas, p_output_fx, n_samples_granularity ) ), IVAS_ERR_OK ) ) - { - return error; - } - - ivas_binaural_add_LFE_fx( st_ivas, *nSamplesRendered, hTcBuffer->tc_fx, p_output_fx ); - } - ELSE - { - return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong renderer in MCT VoIP renderer flushing!" ); - } - } - ELSE - { - return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong MC_MODE in VoIP renderer flushing!" ); - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) || EQ_16( st_ivas->ivas_format, MASA_FORMAT ) ) - { - IF( EQ_16( ism_mode_old, ISM_MASA_MODE_DISC ) ) - { - Word32 *tc_local_fx[MAX_NUM_OBJECTS]; - Word16 last_dirac_md_idx; - UWord16 nSamplesAvailableNext; - ISM_MODE ism_mode_orig; - RENDERER_TYPE renderer_type_orig; - Word32 ivas_total_brate; - - /* copy from ISM delay buffer to the correct place in TCs */ - move16(); - FOR( ch_idx = 0; ch_idx < st_ivas->nchan_ism; ch_idx++ ) - { - tc_local_fx[ch_idx] = &st_ivas->hTcBuffer->tc_fx[ch_idx + 2][hTcBuffer->n_samples_rendered]; - Copy32( st_ivas->hMasaIsmData->delayBuffer_fx[ch_idx], tc_local_fx[ch_idx], st_ivas->hMasaIsmData->delayBuffer_size ); /*Q11*/ - } - - /* to render flushed samples, use configuration from the last received frame */ - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - renderer_type_orig = st_ivas->renderer_type; - ism_mode_orig = st_ivas->ism_mode; - st_ivas->ism_mode = ism_mode_old; - st_ivas->renderer_type = renderer_type_old; - st_ivas->hDecoderConfig->ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; - last_dirac_md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[st_ivas->hSpatParamRendCom->slots_rendered - 1]; - - /* transfer adapted sf info from hTcBuffer to DirAC */ - st_ivas->hSpatParamRendCom->nb_subframes = 1; - st_ivas->hSpatParamRendCom->subframes_rendered = 0; - st_ivas->hSpatParamRendCom->subframe_nbslots[0] = JBM_CLDFB_SLOTS_IN_SUBFRAME; - st_ivas->hSpatParamRendCom->slots_rendered = 0; - st_ivas->hSpatParamRendCom->num_slots = JBM_CLDFB_SLOTS_IN_SUBFRAME; - set16_fx( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); - - IF( ( error = ivas_omasa_dirac_td_binaural_fx( st_ivas, (UWord16) hTcBuffer->n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, CPE_CHANNELS, p_output_fx ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* restore original configuration */ - st_ivas->ism_mode = ism_mode_orig; - st_ivas->renderer_type = renderer_type_orig; - st_ivas->hDecoderConfig->ivas_total_brate = ivas_total_brate; - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) - { - IF( EQ_32( ism_mode_old, ISM_SBA_MODE_DISC ) ) - { - Word32 *tc_local_fx[MAX_TRANSPORT_CHANNELS]; - Word16 last_spar_md_idx; - Word16 last_dirac_md_idx; - UWord16 nSamplesAvailableNext; - ISM_MODE ism_mode_orig; - RENDERER_TYPE renderer_type_orig; - Word32 ivas_total_brate; - - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - renderer_type_orig = st_ivas->renderer_type; - ism_mode_orig = st_ivas->ism_mode; - - /* to render flushed samples, use configuration from the last received frame */ - move32(); - st_ivas->ism_mode = ism_mode_old; - st_ivas->renderer_type = renderer_type_old; - st_ivas->hDecoderConfig->ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; - - last_spar_md_idx = st_ivas->hSpar->render_to_md_map[st_ivas->hSpar->slots_rendered - 1]; - last_dirac_md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[st_ivas->hSpatParamRendCom->slots_rendered - 1]; - move16(); - move16(); - - /* copy from ISM delay buffer to the correct place in TCs */ - FOR( ch_idx = 0; ch_idx < st_ivas->nchan_ism; ch_idx++ ) - { - tc_local_fx[ch_idx] = &st_ivas->hTcBuffer->tc_fx[ch_idx][hTcBuffer->n_samples_rendered]; - Copy32( st_ivas->hSbaIsmData->delayBuffer_fx[ch_idx], tc_local_fx[ch_idx], st_ivas->hSbaIsmData->delayBuffer_size ); - } - - /* transfer adapted sf info from hTcBuffer to SPAR and DirAC */ - st_ivas->hSpar->nb_subframes = 1; - st_ivas->hSpar->subframes_rendered = 0; - st_ivas->hSpar->subframe_nbslots[0] = JBM_CLDFB_SLOTS_IN_SUBFRAME; - st_ivas->hSpar->slots_rendered = 0; - st_ivas->hSpar->num_slots = JBM_CLDFB_SLOTS_IN_SUBFRAME; - st_ivas->hSpatParamRendCom->nb_subframes = 1; - st_ivas->hSpatParamRendCom->subframes_rendered = 0; - st_ivas->hSpatParamRendCom->subframe_nbslots[0] = JBM_CLDFB_SLOTS_IN_SUBFRAME; - st_ivas->hSpatParamRendCom->slots_rendered = 0; - st_ivas->hSpatParamRendCom->num_slots = JBM_CLDFB_SLOTS_IN_SUBFRAME; - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - - /* also adapt md maps, just use the last index */ - set16_fx( st_ivas->hSpar->render_to_md_map, last_spar_md_idx, n_slots_still_available ); - set16_fx( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); - - /* render the last subframe */ - IF( NE_32( ( error = ivas_osba_dirac_td_binaural_fx( st_ivas, (UWord16) hTcBuffer->n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) - { - return error; - } - - /* restore original configuration */ - st_ivas->ism_mode = ism_mode_orig; - st_ivas->renderer_type = renderer_type_orig; - st_ivas->hDecoderConfig->ivas_total_brate = ivas_total_brate; - } - } - ELSE - { - return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong IVAS format in VoIP renderer flushing!" ); - } - - hTcBuffer->n_samples_rendered = hTcBuffer->n_samples_granularity; - } - - /* update global combined orientation start index */ - ivas_combined_orientation_update_start_index( st_ivas->hCombinedOrientationData, *nSamplesRendered ); - - *nSamplesRendered = n_samples_to_render; - move16(); - - /* Only write out the valid data*/ - IF( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) - { - IF( NE_16( st_ivas->ivas_format, MONO_FORMAT ) ) - { -#ifndef DISABLE_LIMITER - Word16 exp = 11; - move16(); - FOR( ch_idx = 0; ch_idx < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) - { - p_output_fx[ch_idx] = st_ivas->p_output_fx[ch_idx]; - } - ivas_limiter_dec_fx( st_ivas->hLimiter, p_output_fx, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect, exp ); -#endif - } - } - - ivas_syn_output_fx( p_output_fx, Q11, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, data ); - - return IVAS_ERR_OK; -} - - -/*--------------------------------------------------------------------------* - * ivas_jbm_dec_set_discard_samples() - * - * Set number of samples to discard in the first subframe - * if the renderer granularity changes on a bitrate change in JBM processing - *--------------------------------------------------------------------------*/ - -ivas_error ivas_jbm_dec_set_discard_samples_fx( - Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ -) -{ - Word16 nMaxSlotsPerSubframe, nSlotsInFirstSubframe; - Word16 temp, temp_e; - - /* render first frame with front zero padding and discarding those samples */ - /* nMaxSlotsPerSubframe = (Word16)(st_ivas->hDecoderConfig->output_Fs / (FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES)) / st_ivas->hTcBuffer->n_samples_granularity; */ - temp = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, ONE_BY_SUBFR_PER_SEC_Q15 ) ); - temp = BASOP_Util_Divide1616_Scale( temp, st_ivas->hTcBuffer->n_samples_granularity, &temp_e ); - nMaxSlotsPerSubframe = shr( temp, sub( 15, temp_e ) ); /* Q0 */ - nSlotsInFirstSubframe = sub( nMaxSlotsPerSubframe, st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1] ); - - IF( nSlotsInFirstSubframe > 0 ) - { - st_ivas->hTcBuffer->n_samples_discard = imult1616( sub( nMaxSlotsPerSubframe, nSlotsInFirstSubframe ), st_ivas->hTcBuffer->n_samples_granularity ); - /* set last subframes number to max to ensure correct continuation */ - st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1] = nMaxSlotsPerSubframe; - move16(); - move16(); - } - - return IVAS_ERR_OK; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_get_adapted_linear_interpolator() - * - * Get an interpolator that is adapted to (time scale modified) IVAS frame - *--------------------------------------------------------------------------*/ - -void ivas_dec_get_adapted_linear_interpolator_fx( - const Word16 default_interp_length, /* i : default length of the (full-frame) interpolator */ - const Word16 interp_length, /* i : length of the interpolator to be created */ - Word16 *interpolator_fx /* o : the interpolator Q15 */ -) -{ - Word16 segment_len, idx; - Word16 dec_fx; - Word16 dec_e; - - segment_len = shr( default_interp_length, 1 ); - dec_fx = divide1616( 1, default_interp_length ); /*32767 / default_interp_length*/ - - interpolator_fx[interp_length - 1] = 32767; /* (1.0f in Q15) -1 */ - move16(); - interpolator_fx[interp_length - 2] = add( sub( 32767, dec_fx ), 1 ); // Use 32768 to maintain precision - move16(); - FOR( idx = interp_length - 3; idx >= segment_len; idx-- ) - { - interpolator_fx[idx] = s_max( 0, sub( interpolator_fx[idx + 1], dec_fx ) ); - move16(); - } - - IF( interpolator_fx[idx + 1] > 0 ) - { - dec_fx = BASOP_Util_Divide1616_Scale( interpolator_fx[idx + 1], add( segment_len, 1 ), &dec_e ); - dec_fx = shr( dec_fx, sub( 15, dec_e ) ); // Q0 - FOR( ; idx >= 0; idx-- ) - { - interpolator_fx[idx] = sub( interpolator_fx[idx + 1], dec_fx ); - move16(); - } - } - ELSE - { - set16_fx( interpolator_fx, 0, add( idx, 1 ) ); - } - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_get_adapted_subframes() - * - * Get an interpolator that is adapted to (time scale modified) IVAS frame - *--------------------------------------------------------------------------*/ - -void ivas_dec_get_adapted_subframes_fx( - const Word16 nCldfbTs, /* i : number of time slots in the current frame */ - Word16 *subframe_nbslots, /* i/o: subframe grid */ - Word16 *nb_subframes /* i/o: number of subframes in the frame */ -) -{ - UWord16 nSlotsInLastSubframe, nSlotsInFirstSubframe; - UWord16 nCldfbSlotsLocal = nCldfbTs; - move16(); - Word16 temp, temp_e; - - /* get last subframe size from previous frame, determine how many slots have to be processed - in the first subframe (i.e. potential leftover of a 5ms subframe) */ - nSlotsInFirstSubframe = ( sub( PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, subframe_nbslots[*nb_subframes - 1] ) ); - *nb_subframes = 0; - move16(); - IF( nSlotsInFirstSubframe > 0 ) - { - *nb_subframes = 1; - move16(); - nCldfbSlotsLocal = sub( nCldfbSlotsLocal, nSlotsInFirstSubframe ); - } - - temp = BASOP_Util_Divide3232_Scale( L_add( nCldfbSlotsLocal, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME - 1 ), PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, &temp_e ); - *nb_subframes = add( *nb_subframes, shr( temp, sub( 15, temp_e ) ) ); // Q0 - move16(); - nSlotsInLastSubframe = nCldfbSlotsLocal % PARAM_MC_MAX_NSLOTS_IN_SUBFRAME; - move16(); - - set16_fx( subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); - set16_fx( subframe_nbslots, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, *nb_subframes ); - - IF( nSlotsInFirstSubframe > 0 ) - { - subframe_nbslots[0] = nSlotsInFirstSubframe; - move16(); - } - - IF( nSlotsInLastSubframe > 0 ) - { - subframe_nbslots[*nb_subframes - 1] = nSlotsInLastSubframe; - move16(); - } - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_get_md_map() - * - * Get an meta data map adapted to a time scale modified IVAS frame - *--------------------------------------------------------------------------*/ - -void ivas_dec_get_md_map_fx( - const Word16 default_len, /* i : default frame length in metadata slots */ - const Word16 len, /* i : length of the modified frames in metadata slots*/ - const Word16 subframe_len, /* i : default length of a subframe */ - const Word16 offset, /* i : current read offset into the MD buffer */ - const Word16 buf_len, /* i : length of the metadata buffer */ - Word16 *map /* o : metadata index map */ -) -{ - Word16 jbm_segment_len, map_idx, src_idx, src_idx_map; - Word32 dec_fx, src_idx_fx; - Word16 temp_e; - Word16 temp; - jbm_segment_len = shr( default_len, 1 ); - - FOR( ( map_idx = len - 1, src_idx = default_len - 1 ); map_idx >= jbm_segment_len; ( map_idx--, src_idx-- ) ) - { - temp = BASOP_Util_Divide1616_Scale( src_idx, subframe_len, &temp_e ); - temp = shr( temp, sub( 15, temp_e ) ); // Q0 - src_idx_map = s_max( 0, temp ); - map[map_idx] = add( offset, src_idx_map ) % buf_len; - move16(); - } - - /* changed part (first segment), interpolate index to parameters - (we do not want to interpolate and smooth acutal direction/diffuseness values even more) */ - IF( src_idx >= 0 ) - { - dec_fx = BASOP_Util_Divide3232_Scale( L_shl( add( src_idx, 1 ), 16 ), jbm_segment_len, &temp_e ); - dec_fx = L_shr( dec_fx, sub( 15, temp_e ) ); - src_idx_fx = L_sub( L_shl( add( src_idx, 1 ), 16 ), dec_fx ); - FOR( ; map_idx >= 0; map_idx-- ) - { - temp = BASOP_Util_Divide1616_Scale( round_fx( src_idx_fx ), subframe_len, &temp_e ); - temp = shr( temp, sub( 15, temp_e ) ); // Q0 - src_idx = s_max( 0, temp ); - map[map_idx] = add( offset, src_idx ) % buf_len; - src_idx_fx = L_sub( src_idx_fx, dec_fx ); - } - } - ELSE - { - set16_fx( map, offset, add( map_idx, 1 ) ); - } - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_get_md_map_even_spacing() - * - * Get an meta data map adapted to (time scale modified) IVAS frame. - * Distribute slots evenly across the (modified) frame. - *--------------------------------------------------------------------------*/ - -void ivas_dec_get_md_map_even_spacing_fx( - const Word16 len, /* i : length of the modified frames in metadata slots*/ - const Word16 subframe_len, /* i : default length of a subframe */ - const Word16 offset, /* i : current read offset into the MD buffer */ - const Word16 buf_len, /* i : length of the metadata buffer */ - Word16 *map /* o : metadata index map */ -) -{ - Word16 map_idx, sf_idx, sf_length, increment, subframes_written; - Word32 decimal_fx, decimal_sum_fx, eps_fx; // q = 16 - Word16 subframe_map_length[MAX_PARAM_SPATIAL_SUBFRAMES]; - - /* subframe map length */ - sf_length = idiv1616( len, subframe_len ); - IF( len % subframe_len == 0 ) - { - /* even subframes */ - FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) - { - subframe_map_length[sf_idx] = sf_length; - move16(); - } - } - ELSE - { - /* uneven subframes */ - Word32 temp; - Word16 temp_e; - temp = BASOP_Util_Divide3232_Scale( L_shl( len, 16 ), subframe_len, &temp_e ); - temp = L_shr( temp, sub( 15, temp_e ) ); // Q16 - decimal_fx = L_sub( temp, L_shl( sf_length, 16 ) ); // Q16 - decimal_sum_fx = decimal_fx; - - eps_fx = 65; - move32(); - move32(); - FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) - { - increment = extract_l( L_shr( L_add( decimal_sum_fx, eps_fx ), 16 ) ); - subframe_map_length[sf_idx] = add( sf_length, increment ); - move16(); - IF( increment > 0 ) - { - decimal_sum_fx = L_sub( decimal_sum_fx, ONE_IN_Q16 ); - } - decimal_sum_fx = L_add( decimal_sum_fx, decimal_fx ); - } - } - - /* map slots to subframes */ - sf_idx = 0; - subframes_written = 0; - move16(); - move16(); - FOR( map_idx = 0; map_idx < len; map_idx++ ) - { - map[map_idx] = add( offset, sf_idx ) % buf_len; - move16(); - IF( GE_16( sub( map_idx, subframes_written ), sub( subframe_map_length[sf_idx], 1 ) ) ) - { - subframes_written = add( subframes_written, subframe_map_length[sf_idx] ); - sf_idx = add( sf_idx, 1 ); - } - } - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_get_num_tc_channels() - * - * Get the number of transport channels provided to the renderer - *--------------------------------------------------------------------------*/ - -Word16 ivas_dec_get_num_tc_channels_fx( - Decoder_Struct *st_ivas /* i : IVAS decoder handle */ -) -{ - Word16 num_tc; - Word32 ivas_total_brate; - AUDIO_CONFIG output_config; - - IF( EQ_16( st_ivas->renderer_type, RENDERER_DISABLE ) ) - { - num_tc = st_ivas->hDecoderConfig->nchan_out; - move16(); - } - ELSE - { - num_tc = st_ivas->nchan_transport; - move16(); - } - output_config = st_ivas->hDecoderConfig->output_config; - move16(); - - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - move32(); - - test(); - test(); - test(); - test(); - IF( EQ_32( st_ivas->ivas_format, MONO_FORMAT ) ) - { - num_tc = 1; - move16(); - } - ELSE IF( EQ_32( st_ivas->ivas_format, STEREO_FORMAT ) && EQ_16( st_ivas->hDecoderConfig->nchan_out, 1 ) ) - { - num_tc = 1; - move16(); - } - ELSE IF( EQ_16( st_ivas->ivas_format, ISM_FORMAT ) ) - { - if ( EQ_16( st_ivas->renderer_type, RENDERER_MONO_DOWNMIX ) ) - { - num_tc = 1; - move16(); - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) || EQ_16( st_ivas->ivas_format, MASA_FORMAT ) ) - { - test(); - test(); - test(); - test(); - test(); - test(); - IF( st_ivas->sba_dirac_stereo_flag ) - { - num_tc = CPE_CHANNELS; - move16(); - } - ELSE IF( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && ( GT_32( ivas_total_brate, IVAS_SID_5k2 ) || ( LE_32( ivas_total_brate, IVAS_SID_5k2 ) && GT_16( st_ivas->nCPE, 0 ) && st_ivas->hCPE[0] != NULL && EQ_16( st_ivas->hCPE[0]->nchan_out, 1 ) ) ) ) - { - num_tc = 1; /* Only one channel transported */ - move16(); - } - - test(); - test(); - test(); - test(); - IF( EQ_16( st_ivas->ivas_format, MASA_FORMAT ) && EQ_16( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) && EQ_16( st_ivas->nchan_transport, 2 ) && LT_32( st_ivas->hDecoderConfig->ivas_total_brate, MASA_STEREO_MIN_BITRATE ) && GT_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_SID_5k2 ) ) - { - num_tc = CPE_CHANNELS; - move16(); - } - IF( EQ_16( st_ivas->ivas_format, SBA_FORMAT ) ) - { - if ( EQ_16( num_tc, 3 ) ) - { - num_tc = add( num_tc, 1 ); - } - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, MASA_ISM_FORMAT ) ) - { - IF( NE_16( output_config, IVAS_AUDIO_CONFIG_EXTERNAL ) ) - { - test(); - IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) - { - num_tc = add( num_tc, 1 ); - } - ELSE IF( EQ_16( st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) - { - num_tc = add( num_tc, st_ivas->nchan_ism ); - } - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) - { - if ( st_ivas->sba_dirac_stereo_flag ) - { - num_tc = CPE_CHANNELS; - move16(); - } - - if ( EQ_16( num_tc, 3 ) ) - { - num_tc = add( num_tc, 1 ); - } - if ( EQ_16( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) - { - num_tc = add( num_tc, st_ivas->nchan_ism ); - } - } - ELSE IF( EQ_16( st_ivas->ivas_format, MC_FORMAT ) ) - { - IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_MONO ) ) - { - num_tc = 1; - move16(); - } - ELSE IF( EQ_16( output_config, IVAS_AUDIO_CONFIG_STEREO ) ) - { - num_tc = 2; - move16(); + return error; + } + + /* restore original configuration */ + st_ivas->ism_mode = ism_mode_orig; + st_ivas->renderer_type = renderer_type_orig; + st_ivas->hDecoderConfig->ivas_total_brate = ivas_total_brate; + } } - ELSE IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCT ) ) + ELSE IF( EQ_16( st_ivas->ivas_format, SBA_ISM_FORMAT ) ) { - /* do all static dmx already in the TC decoder if less channels than transported... */ - test(); - test(); - test(); - test(); - test(); - IF( NE_16( st_ivas->transport_config, st_ivas->intern_config ) && ( EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_FOA ) || EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA2 ) || EQ_16( st_ivas->intern_config, IVAS_AUDIO_CONFIG_HOA3 ) ) ) + IF( EQ_32( ism_mode_old, ISM_SBA_MODE_DISC ) ) { - if ( GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ) ) ) + Word32 *tc_local_fx[MAX_TRANSPORT_CHANNELS]; + Word16 last_spar_md_idx; + Word16 last_dirac_md_idx; + UWord16 nSamplesAvailableNext; + ISM_MODE ism_mode_orig; + RENDERER_TYPE renderer_type_orig; + Word32 ivas_total_brate; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + renderer_type_orig = st_ivas->renderer_type; + ism_mode_orig = st_ivas->ism_mode; + + /* to render flushed samples, use configuration from the last received frame */ + move32(); + st_ivas->ism_mode = ism_mode_old; + st_ivas->renderer_type = renderer_type_old; + st_ivas->hDecoderConfig->ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; + + last_spar_md_idx = st_ivas->hSpar->render_to_md_map[st_ivas->hSpar->slots_rendered - 1]; + last_dirac_md_idx = st_ivas->hSpatParamRendCom->render_to_md_map[st_ivas->hSpatParamRendCom->slots_rendered - 1]; + move16(); + move16(); + + /* copy from ISM delay buffer to the correct place in TCs */ + FOR( ch_idx = 0; ch_idx < st_ivas->nchan_ism; ch_idx++ ) { - num_tc = add( st_ivas->hIntSetup.nchan_out_woLFE, st_ivas->hIntSetup.num_lfe ); + tc_local_fx[ch_idx] = &st_ivas->hTcBuffer->tc_fx[ch_idx][hTcBuffer->n_samples_rendered]; + Copy32( st_ivas->hSbaIsmData->delayBuffer_fx[ch_idx], tc_local_fx[ch_idx], st_ivas->hSbaIsmData->delayBuffer_size ); } - } - ELSE IF( ( EQ_16( st_ivas->renderer_type, RENDERER_MC ) || EQ_16( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ), add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ) ) - { - num_tc = add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ); + + /* transfer adapted sf info from hTcBuffer to SPAR and DirAC */ + st_ivas->hSpar->nb_subframes = 1; + st_ivas->hSpar->subframes_rendered = 0; + st_ivas->hSpar->subframe_nbslots[0] = JBM_CLDFB_SLOTS_IN_SUBFRAME; + st_ivas->hSpar->slots_rendered = 0; + st_ivas->hSpar->num_slots = JBM_CLDFB_SLOTS_IN_SUBFRAME; + st_ivas->hSpatParamRendCom->nb_subframes = 1; + st_ivas->hSpatParamRendCom->subframes_rendered = 0; + st_ivas->hSpatParamRendCom->subframe_nbslots[0] = JBM_CLDFB_SLOTS_IN_SUBFRAME; + st_ivas->hSpatParamRendCom->slots_rendered = 0; + st_ivas->hSpatParamRendCom->num_slots = JBM_CLDFB_SLOTS_IN_SUBFRAME; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + /* also adapt md maps, just use the last index */ + set16_fx( st_ivas->hSpar->render_to_md_map, last_spar_md_idx, n_slots_still_available ); + set16_fx( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); + + /* render the last subframe */ + IF( NE_32( ( error = ivas_osba_dirac_td_binaural_fx( st_ivas, (UWord16) hTcBuffer->n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, p_output_fx ) ), IVAS_ERR_OK ) ) + { + return error; + } + + /* restore original configuration */ + st_ivas->ism_mode = ism_mode_orig; + st_ivas->renderer_type = renderer_type_orig; + st_ivas->hDecoderConfig->ivas_total_brate = ivas_total_brate; } } - ELSE IF( EQ_16( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) + ELSE { - num_tc = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; - move16(); + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong IVAS format in VoIP renderer flushing!" ); } - ELSE IF( EQ_16( st_ivas->mc_mode, MC_MODE_MCMASA ) ) - { - if ( st_ivas->hOutSetup.separateChannelEnabled ) - { - num_tc = add( num_tc, 1 ); - } - test(); - test(); - test(); - test(); - test(); - test(); - test(); - if ( st_ivas->hOutSetup.separateChannelEnabled && ( EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1 ) || - EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_4 ) || EQ_16( output_config, IVAS_AUDIO_CONFIG_7_1_4 ) || - EQ_16( output_config, IVAS_AUDIO_CONFIG_5_1_2 ) || ( EQ_16( output_config, IVAS_AUDIO_CONFIG_LS_CUSTOM ) && st_ivas->hOutSetup.num_lfe > 0 ) ) ) + hTcBuffer->n_samples_rendered = hTcBuffer->n_samples_granularity; + } + + /* update global combined orientation start index */ + ivas_combined_orientation_update_start_index( st_ivas->hCombinedOrientationData, *nSamplesRendered ); + + *nSamplesRendered = n_samples_to_render; + move16(); + + /* Only write out the valid data*/ + IF( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) + { + IF( NE_16( st_ivas->ivas_format, MONO_FORMAT ) ) + { +#ifndef DISABLE_LIMITER + Word16 exp = 11; + move16(); + FOR( ch_idx = 0; ch_idx < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) { - /* LFE is synthesized in TD with the TCs*/ - num_tc = add( num_tc, 1 ); + p_output_fx[ch_idx] = st_ivas->p_output_fx[ch_idx]; } + ivas_limiter_dec_fx( st_ivas->hLimiter, p_output_fx, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect, exp ); +#endif } } - return num_tc; + ivas_syn_output_fx( p_output_fx, Q11, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, data ); + + return IVAS_ERR_OK; } /*--------------------------------------------------------------------------* - * ivas_dec_get_render_granularity() + * ivas_jbm_dec_set_discard_samples() * - * Get renderer granularity + * Set number of samples to discard in the first subframe + * if the renderer granularity changes on a bitrate change in JBM processing *--------------------------------------------------------------------------*/ -/*! r: render granularity */ -Word16 ivas_dec_get_render_granularity_fx( - const RENDERER_TYPE renderer_type, /* i : renderer type */ - const RENDERER_TYPE renderer_type_sec, /* i : secondary renderer type */ - const Word32 output_Fs /* i : sampling rate */ +ivas_error ivas_jbm_dec_set_discard_samples_fx( + Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ ) { - Word16 render_granularity; + Word16 nMaxSlotsPerSubframe, nSlotsInFirstSubframe; + Word16 temp, temp_e; - test(); - test(); - test(); - IF( EQ_32( renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) || /* TD renderer */ - EQ_32( renderer_type, RENDERER_BINAURAL_MIXER_CONV ) || EQ_32( renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) || /* Crend */ - EQ_32( renderer_type_sec, RENDERER_BINAURAL_OBJECTS_TD ) /* TD rend as a secondary renderer -> set the common granularity for both renderers */ - ) + /* render first frame with front zero padding and discarding those samples */ + /* nMaxSlotsPerSubframe = (Word16)(st_ivas->hDecoderConfig->output_Fs / (FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES)) / st_ivas->hTcBuffer->n_samples_granularity; */ + temp = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, ONE_BY_SUBFR_PER_SEC_Q15 ) ); + temp = BASOP_Util_Divide1616_Scale( temp, st_ivas->hTcBuffer->n_samples_granularity, &temp_e ); + nMaxSlotsPerSubframe = shr( temp, sub( 15, temp_e ) ); /* Q0 */ + nSlotsInFirstSubframe = sub( nMaxSlotsPerSubframe, st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1] ); + + IF( nSlotsInFirstSubframe > 0 ) { - /* 5 ms granularity */ - render_granularity = NS2SA_FX2( output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); + st_ivas->hTcBuffer->n_samples_discard = imult1616( sub( nMaxSlotsPerSubframe, nSlotsInFirstSubframe ), st_ivas->hTcBuffer->n_samples_granularity ); + /* set last subframes number to max to ensure correct continuation */ + st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1] = nMaxSlotsPerSubframe; move16(); - } - ELSE - { - /* 1.25 ms granularity */ - render_granularity = NS2SA_FX2( output_Fs, CLDFB_SLOT_NS ); move16(); } - return render_granularity; + return IVAS_ERR_OK; } /*--------------------------------------------------------------------------* - * ivas_dec_tc_audio_allocate() + * ivas_dec_get_adapted_linear_interpolator() * - * allocate and initialize TC audio buffer + * Get an interpolator that is adapted to (time scale modified) IVAS frame *--------------------------------------------------------------------------*/ -static ivas_error ivas_dec_tc_audio_allocate_fx( - DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: TC buffer handle */ - const Word32 output_Fs, /* i : output sampling rate */ - const Word16 Opt_tsm /* i : TSM option flag */ +void ivas_dec_get_adapted_linear_interpolator_fx( + const Word16 default_interp_length, /* i : default length of the (full-frame) interpolator */ + const Word16 interp_length, /* i : length of the interpolator to be created */ + Word16 *interpolator_fx /* o : the interpolator Q15 */ ) { - Word16 nsamp_to_allocate; - Word16 ch_idx, n_samp_full, n_samp_residual, offset; + Word16 segment_len, idx; + Word16 dec_fx; + Word16 dec_e; - IF( Opt_tsm ) - { - n_samp_full = NS2SA_FX2( output_Fs, MAX_JBM_L_FRAME_NS ); - n_samp_full = s_max( n_samp_full, L_FRAME48k ); /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': ensure minimal length */ - n_samp_residual = sub( hTcBuffer->n_samples_granularity, 1 ); - } - ELSE + segment_len = shr( default_interp_length, 1 ); + dec_fx = divide1616( 1, default_interp_length ); /*32767 / default_interp_length*/ + + interpolator_fx[interp_length - 1] = 32767; /* (1.0f in Q15) -1 */ + move16(); + interpolator_fx[interp_length - 2] = add( sub( 32767, dec_fx ), 1 ); // Use 32768 to maintain precision + move16(); + FOR( idx = interp_length - 3; idx >= segment_len; idx-- ) { - n_samp_full = extract_l( Mpy_32_32( output_Fs, ONE_BY_FRAMES_PER_SEC_Q31 ) ); - n_samp_residual = 0; + interpolator_fx[idx] = s_max( 0, sub( interpolator_fx[idx + 1], dec_fx ) ); move16(); } - nsamp_to_allocate = imult1616( s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ), n_samp_full ); - - IF( Opt_tsm ) + IF( interpolator_fx[idx + 1] > 0 ) { - /* note: this is stack memory buffer for TC decoded and also time-scale modified audio signals */ - IF( ( hTcBuffer->tc_buffer_fx = (Word32 *) malloc( nsamp_to_allocate * sizeof( Word32 ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); - } - set_zero_fx( hTcBuffer->tc_buffer_fx, nsamp_to_allocate ); - - offset = 0; - move16(); - FOR( ch_idx = 0; ch_idx < s_max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) - { - hTcBuffer->tc_fx[ch_idx] = &hTcBuffer->tc_buffer_fx[offset]; - offset = add( offset, n_samp_full ); - } - FOR( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc_fx[ch_idx] = NULL; - } - - /* memory buffer for TC audio samples not rendered in the previous frame */ - FOR( ch_idx = 0; ch_idx < hTcBuffer->nchan_transport_internal; ch_idx++ ) - { - IF( ( hTcBuffer->tc_buffer_old_fx[ch_idx] = (Word32 *) malloc( n_samp_residual * sizeof( Word32 ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); - } - set_zero_fx( hTcBuffer->tc_buffer_old_fx[ch_idx], n_samp_residual ); - } - FOR( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + dec_fx = BASOP_Util_Divide1616_Scale( interpolator_fx[idx + 1], add( segment_len, 1 ), &dec_e ); + dec_fx = shr( dec_fx, sub( 15, dec_e ) ); // Q0 + FOR( ; idx >= 0; idx-- ) { - hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; + interpolator_fx[idx] = sub( interpolator_fx[idx + 1], dec_fx ); + move16(); } } - else + ELSE { - hTcBuffer->tc_buffer_fx = NULL; - - FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc_fx[ch_idx] = NULL; - } - - FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; - } + set16_fx( interpolator_fx, 0, add( idx, 1 ) ); } - hTcBuffer->tc_buffer2_fx = NULL; - - return IVAS_ERR_OK; + return; } /*--------------------------------------------------------------------------* - * ivas_jbm_dec_tc_audio_deallocate() + * ivas_dec_get_adapted_subframes() * - * deallocate TC audio buffer + * Get an interpolator that is adapted to (time scale modified) IVAS frame *--------------------------------------------------------------------------*/ -static void ivas_jbm_dec_tc_audio_deallocate_fx( - DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: JBM TSM buffer handle */ +void ivas_dec_get_adapted_subframes_fx( + const Word16 nCldfbTs, /* i : number of time slots in the current frame */ + Word16 *subframe_nbslots, /* i/o: subframe grid */ + Word16 *nb_subframes /* i/o: number of subframes in the frame */ ) { - Word16 ch_idx; + UWord16 nSlotsInLastSubframe, nSlotsInFirstSubframe; + UWord16 nCldfbSlotsLocal = nCldfbTs; + move16(); + Word16 temp, temp_e; - IF( hTcBuffer != NULL ) + /* get last subframe size from previous frame, determine how many slots have to be processed + in the first subframe (i.e. potential leftover of a 5ms subframe) */ + nSlotsInFirstSubframe = ( sub( PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, subframe_nbslots[*nb_subframes - 1] ) ); + *nb_subframes = 0; + move16(); + IF( nSlotsInFirstSubframe > 0 ) { - IF( hTcBuffer->tc_buffer_fx != NULL ) - { - FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc_fx[ch_idx] = NULL; - } + *nb_subframes = 1; + move16(); + nCldfbSlotsLocal = sub( nCldfbSlotsLocal, nSlotsInFirstSubframe ); + } - free( hTcBuffer->tc_buffer_fx ); - hTcBuffer->tc_buffer_fx = NULL; - } + temp = BASOP_Util_Divide3232_Scale( L_add( nCldfbSlotsLocal, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME - 1 ), PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, &temp_e ); + *nb_subframes = add( *nb_subframes, shr( temp, sub( 15, temp_e ) ) ); // Q0 + move16(); + nSlotsInLastSubframe = nCldfbSlotsLocal % PARAM_MC_MAX_NSLOTS_IN_SUBFRAME; + move16(); - FOR( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - IF( hTcBuffer->tc_buffer_old_fx[ch_idx] != NULL ) - { - free( hTcBuffer->tc_buffer_old_fx[ch_idx] ); - hTcBuffer->tc_buffer_old_fx[ch_idx] = NULL; - } - } + set16_fx( subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set16_fx( subframe_nbslots, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, *nb_subframes ); + + IF( nSlotsInFirstSubframe > 0 ) + { + subframe_nbslots[0] = nSlotsInFirstSubframe; + move16(); + } - IF( hTcBuffer->tc_buffer2_fx != NULL ) - { - free( hTcBuffer->tc_buffer2_fx ); - hTcBuffer->tc_buffer2_fx = NULL; - } + IF( nSlotsInLastSubframe > 0 ) + { + subframe_nbslots[*nb_subframes - 1] = nSlotsInLastSubframe; + move16(); } return; } + /*--------------------------------------------------------------------------* - * ivas_dec_tc_buffer_open() + * ivas_dec_get_md_map() * - * Open and initialize transport channel buffer handle + * Get an meta data map adapted to a time scale modified IVAS frame *--------------------------------------------------------------------------*/ -ivas_error ivas_dec_tc_buffer_open_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ - const Word16 nchan_transport_rend, /* i : number of TCs for rendering */ - const Word16 nchan_transport_internal, /* i : number of totally buffered channels */ - const Word16 nchan_full, /* i : number of channels to fully store */ - const Word16 n_samples_granularity /* i : granularity of the renderer/buffer */ +void ivas_dec_get_md_map_fx( + const Word16 default_len, /* i : default frame length in metadata slots */ + const Word16 len, /* i : length of the modified frames in metadata slots*/ + const Word16 subframe_len, /* i : default length of a subframe */ + const Word16 offset, /* i : current read offset into the MD buffer */ + const Word16 buf_len, /* i : length of the metadata buffer */ + Word16 *map /* o : metadata index map */ ) { - DECODER_TC_BUFFER_HANDLE hTcBuffer; - Word16 nMaxSlotsPerSubframe; - ivas_error error; - Word16 tmp, tmp_e; - - /*-----------------------------------------------------------------* - * prepare library opening - *-----------------------------------------------------------------*/ + Word16 jbm_segment_len, map_idx, src_idx, src_idx_map; + Word32 dec_fx, src_idx_fx; + Word16 temp_e; + Word16 temp; + jbm_segment_len = shr( default_len, 1 ); - IF( ( hTcBuffer = (DECODER_TC_BUFFER_HANDLE) malloc( sizeof( DECODER_TC_BUFFER ) ) ) == NULL ) + FOR( ( map_idx = len - 1, src_idx = default_len - 1 ); map_idx >= jbm_segment_len; ( map_idx--, src_idx-- ) ) { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + temp = BASOP_Util_Divide1616_Scale( src_idx, subframe_len, &temp_e ); + temp = shr( temp, sub( 15, temp_e ) ); // Q0 + src_idx_map = s_max( 0, temp ); + map[map_idx] = add( offset, src_idx_map ) % buf_len; + move16(); } - hTcBuffer->tc_buffer_mode = tc_buffer_mode; - move16(); - hTcBuffer->nchan_transport_rend = nchan_transport_rend; - move16(); - hTcBuffer->nchan_transport_internal = nchan_transport_internal; - move16(); - hTcBuffer->nchan_buffer_full = nchan_full; - move16(); - hTcBuffer->n_samples_granularity = n_samples_granularity; - move16(); - hTcBuffer->n_samples_available = 0; - move16(); - hTcBuffer->n_samples_buffered = 0; - move16(); - hTcBuffer->n_samples_rendered = 0; - move16(); - hTcBuffer->slots_rendered = 0; - move16(); - hTcBuffer->subframes_rendered = 0; - move16(); - hTcBuffer->n_samples_discard = 0; - move16(); - hTcBuffer->n_samples_flushed = 0; - move16(); - hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; - move16(); - - /* nMaxSlotsPerSubframe = (Word16)(st_ivas->hDecoderConfig->output_Fs / (FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES)) / st_ivas->hTcBuffer->n_samples_granularity; */ - tmp = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, ONE_BY_SUBFR_PER_SEC_Q15 ) ); - tmp = BASOP_Util_Divide1616_Scale( tmp, hTcBuffer->n_samples_granularity, &tmp_e ); - nMaxSlotsPerSubframe = shr( tmp, sub( 15, tmp_e ) ); /* Q0 */ - - hTcBuffer->num_slots = mult0( nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); - move16(); - - set16_fx( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); - set16_fx( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); - - IF( ( error = ivas_dec_tc_audio_allocate_fx( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + /* changed part (first segment), interpolate index to parameters + (we do not want to interpolate and smooth acutal direction/diffuseness values even more) */ + IF( src_idx >= 0 ) + { + dec_fx = BASOP_Util_Divide3232_Scale( L_shl( add( src_idx, 1 ), 16 ), jbm_segment_len, &temp_e ); + dec_fx = L_shr( dec_fx, sub( 15, temp_e ) ); + src_idx_fx = L_sub( L_shl( add( src_idx, 1 ), 16 ), dec_fx ); + FOR( ; map_idx >= 0; map_idx-- ) + { + temp = BASOP_Util_Divide1616_Scale( round_fx( src_idx_fx ), subframe_len, &temp_e ); + temp = shr( temp, sub( 15, temp_e ) ); // Q0 + src_idx = s_max( 0, temp ); + map[map_idx] = add( offset, src_idx ) % buf_len; + src_idx_fx = L_sub( src_idx_fx, dec_fx ); + } + } + ELSE { - return error; + set16_fx( map, offset, add( map_idx, 1 ) ); } - st_ivas->hTcBuffer = hTcBuffer; - - return IVAS_ERR_OK; + return; } /*--------------------------------------------------------------------------* - * ivas_dec_tc_buffer_reconfigure() + * ivas_dec_get_md_map_even_spacing() * - * Reconfigure transport channel buffer handle + * Get an meta data map adapted to (time scale modified) IVAS frame. + * Distribute slots evenly across the (modified) frame. *--------------------------------------------------------------------------*/ -ivas_error ivas_dec_tc_buffer_reconfigure_fx( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ - const Word16 nchan_transport_rend, /* i : new number of TCs for rendering */ - const Word16 nchan_transport_internal, /* i : new number of totally buffered channels */ - const Word16 nchan_full, /* i : new number of channels to fully store */ - const Word16 n_samples_granularity /* i : new granularity of the renderer/buffer */ +void ivas_dec_get_md_map_even_spacing_fx( + const Word16 len, /* i : length of the modified frames in metadata slots*/ + const Word16 subframe_len, /* i : default length of a subframe */ + const Word16 offset, /* i : current read offset into the MD buffer */ + const Word16 buf_len, /* i : length of the metadata buffer */ + Word16 *map /* o : metadata index map */ ) { - Word16 ch_idx, num_tc_buffer_mem, n_samples_still_available; - Word32 tc_buffer_mem[MAX_INTERN_CHANNELS][L_FRAME48k / MAX_PARAM_SPATIAL_SUBFRAMES - 1]; - ivas_error error; - DECODER_TC_BUFFER_HANDLE hTcBuffer; - - hTcBuffer = st_ivas->hTcBuffer; - move16(); - - num_tc_buffer_mem = 0; - move16(); - n_samples_still_available = 0; - move16(); + Word16 map_idx, sf_idx, sf_length, increment, subframes_written; + Word32 decimal_fx, decimal_sum_fx, eps_fx; // q = 16 + Word16 subframe_map_length[MAX_PARAM_SPATIAL_SUBFRAMES]; - IF( st_ivas->hDecoderConfig->Opt_tsm ) + /* subframe map length */ + sf_length = idiv1616( len, subframe_len ); + IF( len % subframe_len == 0 ) { - /* save samples of the TC buffer from the previous frame */ - num_tc_buffer_mem = s_min( hTcBuffer->nchan_transport_internal, nchan_transport_internal ); - n_samples_still_available = sub( hTcBuffer->n_samples_buffered, hTcBuffer->n_samples_rendered ); - - /* what is remaining from last frame needs always be smaller than the new granularity */ - assert( n_samples_still_available < n_samples_granularity ); - - FOR( ch_idx = 0; ch_idx < num_tc_buffer_mem; ch_idx++ ) + /* even subframes */ + FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) { - Copy32( hTcBuffer->tc_buffer_old_fx[ch_idx] + hTcBuffer->n_samples_flushed, tc_buffer_mem[ch_idx], n_samples_still_available ); + subframe_map_length[sf_idx] = sf_length; + move16(); } } - - /* if granularity changes, adapt subframe_nb_slots */ - IF( NE_16( n_samples_granularity, hTcBuffer->n_samples_granularity ) ) + ELSE { - Word16 nMaxSlotsPerSubframeNew; - Word16 tmp, tmp_e; - - /* nMaxSlotsPerSubframeNew = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / n_samples_granularity; */ - tmp = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, ONE_BY_SUBFR_PER_SEC_Q15 ) ); - tmp = BASOP_Util_Divide1616_Scale( tmp, n_samples_granularity, &tmp_e ); - nMaxSlotsPerSubframeNew = shr( tmp, sub( 15, tmp_e ) ); /* Q0 */ + /* uneven subframes */ + Word32 temp; + Word16 temp_e; + temp = BASOP_Util_Divide3232_Scale( L_shl( len, 16 ), subframe_len, &temp_e ); + temp = L_shr( temp, sub( 15, temp_e ) ); // Q16 + decimal_fx = L_sub( temp, L_shl( sf_length, 16 ) ); // Q16 + decimal_sum_fx = decimal_fx; - /* if samples were flushed, take that into account here */ - test(); - IF( LT_16( n_samples_granularity, hTcBuffer->n_samples_granularity ) && hTcBuffer->n_samples_flushed > 0 ) - { - hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = idiv1616( hTcBuffer->n_samples_flushed, n_samples_granularity ); - hTcBuffer->n_samples_flushed = 0; - move16(); - move16(); - } - ELSE + eps_fx = 65; + move32(); + move32(); + FOR( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) { - hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = nMaxSlotsPerSubframeNew; + increment = extract_l( L_shr( L_add( decimal_sum_fx, eps_fx ), 16 ) ); + subframe_map_length[sf_idx] = add( sf_length, increment ); move16(); + IF( increment > 0 ) + { + decimal_sum_fx = L_sub( decimal_sum_fx, ONE_IN_Q16 ); + } + decimal_sum_fx = L_add( decimal_sum_fx, decimal_fx ); } } - hTcBuffer->tc_buffer_mode = tc_buffer_mode; - move16(); - hTcBuffer->nchan_transport_rend = nchan_transport_rend; - move16(); - hTcBuffer->nchan_transport_internal = nchan_transport_internal; - move16(); - hTcBuffer->nchan_buffer_full = nchan_full; + /* map slots to subframes */ + sf_idx = 0; + subframes_written = 0; move16(); - hTcBuffer->n_samples_granularity = n_samples_granularity; move16(); + FOR( map_idx = 0; map_idx < len; map_idx++ ) + { + map[map_idx] = add( offset, sf_idx ) % buf_len; + move16(); + IF( GE_16( sub( map_idx, subframes_written ), sub( subframe_map_length[sf_idx], 1 ) ) ) + { + subframes_written = add( subframes_written, subframe_map_length[sf_idx] ); + sf_idx = add( sf_idx, 1 ); + } + } + + return; +} - /* reallocate TC audio buffers */ - ivas_jbm_dec_tc_audio_deallocate_fx( hTcBuffer ); +/*--------------------------------------------------------------------------* + * ivas_dec_get_render_granularity() + * + * Get renderer granularity + *--------------------------------------------------------------------------*/ + +/*! r: render granularity */ +Word16 ivas_dec_get_render_granularity_fx( + const RENDERER_TYPE renderer_type, /* i : renderer type */ + const RENDERER_TYPE renderer_type_sec, /* i : secondary renderer type */ + const Word32 output_Fs /* i : sampling rate */ +) +{ + Word16 render_granularity; - IF( ( error = ivas_dec_tc_audio_allocate_fx( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + test(); + test(); + test(); + IF( EQ_32( renderer_type, RENDERER_BINAURAL_OBJECTS_TD ) || /* TD renderer */ + EQ_32( renderer_type, RENDERER_BINAURAL_MIXER_CONV ) || EQ_32( renderer_type, RENDERER_BINAURAL_MIXER_CONV_ROOM ) || /* Crend */ + EQ_32( renderer_type_sec, RENDERER_BINAURAL_OBJECTS_TD ) /* TD rend as a secondary renderer -> set the common granularity for both renderers */ + ) { - return error; + /* 5 ms granularity */ + render_granularity = NS2SA_FX2( output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); + move16(); } - - /* propagate samples of the TC buffer from the previous frame */ - FOR( ch_idx = 0; ch_idx < num_tc_buffer_mem; ch_idx++ ) + ELSE { - Copy32( tc_buffer_mem[ch_idx], hTcBuffer->tc_buffer_old_fx[ch_idx], n_samples_still_available ); + /* 1.25 ms granularity */ + render_granularity = NS2SA_FX2( output_Fs, CLDFB_SLOT_NS ); + move16(); } - return IVAS_ERR_OK; + return render_granularity; } @@ -3103,28 +1705,6 @@ static void ivas_dec_tc_buffer_playout_fx( } -/*--------------------------------------------------------------------------* - * ivas_dec_tc_buffer_close() - * - * Close transport channel buffer handle - *--------------------------------------------------------------------------*/ - -void ivas_dec_tc_buffer_close_fx( - DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ -) -{ - IF( *phTcBuffer != NULL ) - { - ivas_jbm_dec_tc_audio_deallocate_fx( *phTcBuffer ); - - free( *phTcBuffer ); - *phTcBuffer = NULL; - } - - return; -} - - /*--------------------------------------------------------------------------* * ivas_dec_td_renderers_adapt_subframes() * @@ -3202,105 +1782,6 @@ void ivas_dec_td_renderers_adapt_subframes_fx( } -/*--------------------------------------------------------------------------* - * ivas_dec_get_tc_buffer_mode() - * - * - *--------------------------------------------------------------------------*/ - -TC_BUFFER_MODE ivas_dec_get_tc_buffer_mode_fx( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -) -{ - TC_BUFFER_MODE buffer_mode; - - buffer_mode = TC_BUFFER_MODE_BUFFER; - move16(); - - SWITCH( st_ivas->renderer_type ) - { - /* all renderers where we are done after TC decoding (might include DMX to mono/stereo */ - case RENDERER_DISABLE: - case RENDERER_MCMASA_MONO_STEREO: - case RENDERER_OSBA_STEREO: - case RENDERER_MONO_DOWNMIX: - buffer_mode = TC_BUFFER_MODE_BUFFER; - move16(); - BREAK; - case RENDERER_NON_DIEGETIC_DOWNMIX: - case RENDERER_TD_PANNING: - case RENDERER_BINAURAL_OBJECTS_TD: - case RENDERER_BINAURAL_FASTCONV: - case RENDERER_BINAURAL_FASTCONV_ROOM: - case RENDERER_BINAURAL_PARAMETRIC: - case RENDERER_BINAURAL_PARAMETRIC_ROOM: - case RENDERER_STEREO_PARAMETRIC: - case RENDERER_DIRAC: - case RENDERER_PARAM_ISM: - case RENDERER_BINAURAL_MIXER_CONV: - case RENDERER_BINAURAL_MIXER_CONV_ROOM: - case RENDERER_OMASA_OBJECT_EXT: - case RENDERER_OMASA_MIX_EXT: - case RENDERER_OSBA_AMBI: - case RENDERER_OSBA_LS: - buffer_mode = TC_BUFFER_MODE_RENDERER; - move16(); - BREAK; - case RENDERER_MC_PARAMMC: - IF( EQ_32( st_ivas->hParamMC->synthesis_conf, PARAM_MC_SYNTH_MONO_STEREO ) ) - { - buffer_mode = TC_BUFFER_MODE_BUFFER; /* TCs are already the DMX to mono or stereo */ - move16(); - } - ELSE - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - move16(); - } - BREAK; - case RENDERER_MC: - if ( NE_16( ivas_dec_get_num_tc_channels_fx( st_ivas ), st_ivas->hDecoderConfig->nchan_out ) ) - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - move16(); - } - BREAK; - case RENDERER_SBA_LINEAR_ENC: - test(); - test(); - test(); - test(); - IF( EQ_32( st_ivas->ivas_format, MC_FORMAT ) && EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) && ( EQ_32( st_ivas->renderer_type, RENDERER_MC ) || EQ_32( st_ivas->renderer_type, RENDERER_SBA_LINEAR_ENC ) ) && GE_16( ( add( st_ivas->hTransSetup.nchan_out_woLFE, st_ivas->hTransSetup.num_lfe ) ), ( add( st_ivas->hOutSetup.nchan_out_woLFE, st_ivas->hOutSetup.num_lfe ) ) ) ) - { - buffer_mode = TC_BUFFER_MODE_BUFFER; - move16(); - } - ELSE - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - move16(); - } - BREAK; - case RENDERER_SBA_LINEAR_DEC: - test(); - test(); - IF( EQ_32( st_ivas->ivas_format, SBA_FORMAT ) && ( EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) || EQ_32( st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) ) ) - { - buffer_mode = TC_BUFFER_MODE_BUFFER; - move16(); - } - ELSE - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - move16(); - } - BREAK; - } - - return buffer_mode; -} - - /*--------------------------------------------------------------------------* * ivas_jbm_dec_masa_metadata_open() * -- GitLab