From 4427e600ed92a816e77b60d03182499f36d21637 Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 28 Jan 2026 15:09:43 +0100 Subject: [PATCH 1/2] move functions --- lib_dec/ivas_dec.c | 1209 ++++++- lib_dec/{ivas_jbm_dec.c => ivas_dec_render.c} | 2878 +++++------------ 2 files changed, 2034 insertions(+), 2053 deletions(-) rename lib_dec/{ivas_jbm_dec.c => ivas_dec_render.c} (61%) diff --git a/lib_dec/ivas_dec.c b/lib_dec/ivas_dec.c index 4f49e0da13..bebc8a6a42 100644 --- a/lib_dec/ivas_dec.c +++ b/lib_dec/ivas_dec.c @@ -48,17 +48,1212 @@ /*--------------------------------------------------------------------------* * ivas_dec() * - * Principal IVAS decoder routine + * Principal IVAS decoder routine, decoding of metadata and transport channels *--------------------------------------------------------------------------*/ -ivas_error ivas_dec_tmp( // this will be removed in the following step - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - int16_t *data /* o : output synthesis signal */ +ivas_error ivas_dec( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ ) { - // TODO: move here function ivas_dec() - st_ivas->ivas_format = UNDEFINED_FORMAT; // temp. to avoid compilation warnings - data[0] = 0; // temp. to avoid compilation warnings + int16_t n, output_frame, nchan_out; + Decoder_State *st; /* used for bitstream handling */ + float *p_output[MAX_TRANSPORT_CHANNELS]; /* 'float' buffer for output synthesis */ + int16_t nchan_remapped; + int16_t nb_bits_metadata[MAX_SCE + 1]; + int32_t output_Fs, ivas_total_brate; + AUDIO_CONFIG output_config; + ivas_error error; + int16_t num_md_sub_frames; + int32_t ism_total_brate; + + push_wmops( "ivas_dec" ); + + /*----------------------------------------------------------------* + * Initialization of local vars after struct has been set + *----------------------------------------------------------------*/ + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + nchan_out = st_ivas->hTcBuffer->nchan_transport_rend; + output_config = st_ivas->hDecoderConfig->output_config; + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + + /* set pointers to transport channels audio */ + for ( n = 0; n < MAX_TRANSPORT_CHANNELS; n++ ) + { + p_output[n] = st_ivas->p_output_f[n]; + if ( p_output[n] != NULL ) + { + set_zero( p_output[n], L_FRAME48k ); + } + } + + /*----------------------------------------------------------------* + * Decoding + pre-rendering + *----------------------------------------------------------------*/ + + if ( st_ivas->ivas_format == STEREO_FORMAT ) + { + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* HP filtering */ + for ( n = 0; n < min( nchan_out, st_ivas->nchan_transport ); n++ ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) + { + /* Metadata decoding and configuration */ + if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) + { + ivas_ism_dtx_dec( st_ivas, nb_bits_metadata ); + + /* decode dominant object first so the noise energy of the other objects can be limited */ + if ( ( error = ivas_sce_dec( st_ivas, st_ivas->hISMDTX.sce_id_dtx, &p_output[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( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport ); + + ivas_param_ism_dec_dequant_md( st_ivas ); + } + else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) + { + if ( ( error = ivas_ism_metadata_dec( 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( st_ivas ); + } + else /* ISM_MODE_DISC */ + { + if ( ( error = ivas_ism_metadata_dec( 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 */ + if ( !( ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) && n == st_ivas->hISMDTX.sce_id_dtx ) ) + { + if ( ( error = ivas_sce_dec( st_ivas, n, &p_output[n], output_frame, nb_bits_metadata[n] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* HP filtering */ + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + ivas_ism_mono_dmx( st_ivas, p_output, output_frame ); + } + else if ( st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) + { + /* loudness correction */ + ivas_dirac_dec_binaural_sba_gain( p_output, st_ivas->nchan_transport, output_frame ); + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + set_s( nb_bits_metadata, 0, MAX_SCE ); + + /* read parameters from the bitstream */ + if ( 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 ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT ) + { + if ( ( error = ivas_spar_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->nchan_transport == CPE_CHANNELS && st_ivas->nCPE >= 1 ) + { + st_ivas->hCPE[0]->brate_surplus = 0; + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + } + + /* core-decoding of transport channels */ + if ( st_ivas->nSCE == 1 ) + { + if ( ( error = ivas_sce_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE > 1 ) + { + if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + +#ifdef DEBUG_SBA_AUDIO_DUMP + /* Dump audio signal after core-decoding */ + ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[0], "core-decoding" ); +#endif + /* TCs remapping */ + nchan_remapped = st_ivas->nchan_transport; + if ( st_ivas->sba_dirac_stereo_flag ) + { + nchan_remapped = nchan_out; + + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + ivas_agc_dec_process( st_ivas->hSpar->hAgcDec, p_output, p_output, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + if ( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec( 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 ); + } + + ivas_spar_dec_gen_umx_mat( 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( st_ivas, p_output, output_frame ); + } + else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) + { + nchan_remapped = 1; /* Only one channel transported */ + } + + /* HP filtering */ +#ifndef DEBUG_SPAR_BYPASS_EVS_CODEC + for ( n = 0; n < nchan_remapped; n++ ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } +#endif + + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + nchan_remapped = ivas_sba_remapTCs( p_output, st_ivas, output_frame ); + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || 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 ); + ivas_sba_mix_matrix_determiner( st_ivas->hSpar, p_output, st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames ); + } + else if ( st_ivas->renderer_type != RENDERER_DISABLE ) + { + ivas_spar_dec_agc_pca( st_ivas, p_output, output_frame ); + } + } + + if ( st_ivas->ivas_format == MASA_FORMAT ) + { + ivas_masa_prerender( st_ivas, p_output, output_frame, nchan_remapped ); + + /* external output */ + if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->hMasa->config.input_ivas_format == MASA_ISM_FORMAT ) + { + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + set_zero( p_output[st_ivas->nchan_transport + n], output_frame ); + } + + ivas_omasa_rearrange_channels( p_output, st_ivas->nchan_ism, output_frame ); + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + { + /* loudness correction */ + ivas_dirac_dec_binaural_sba_gain( p_output, nchan_remapped, output_frame ); + } + } + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + int16_t nchan_ism, nchan_transport_ism; + int16_t dirac_bs_md_write_idx; + + set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); + + /* Set the number of objects for the parametric rendering */ + dirac_bs_md_write_idx = 0; + if ( st_ivas->hSpatParamRendCom != NULL ) + { + st_ivas->hSpatParamRendCom->numIsmDirections = 0; + if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + { + st_ivas->hSpatParamRendCom->numIsmDirections = st_ivas->nchan_ism; + } + + dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */ + } + + /* MASA metadata decoding */ + if ( ( error = ivas_masa_decode( 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 )] ); + + /* set ISM parameters and decode ISM metadata in OMASA format */ + if ( ( error = ivas_omasa_ism_metadata_dec( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* decode ISM channels */ + for ( n = 0; n < nchan_transport_ism; n++ ) + { + if ( ( error = ivas_sce_dec( st_ivas, n, &p_output[st_ivas->nchan_transport + n], output_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* decode MASA channels */ + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hCPE[0]->nchan_out == 1 ) + { + mvr2r( p_output[0], p_output[1], output_frame ); /* Copy mono signal to stereo output channels */ + } + + /* HP filtering */ + for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + ivas_ism_mono_dmx( st_ivas, p_output, output_frame ); + } + else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + ivas_omasa_rearrange_channels( p_output, nchan_transport_ism, output_frame ); + } + else if ( 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( st_ivas, p_output, st_ivas->nchan_ism, output_frame ); + } + else if ( 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( st_ivas, p_output, st_ivas->nchan_ism, output_frame ); + } + } + } + else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) + { + int16_t nchan_ism, sba_ch_idx; + + set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); + nchan_ism = st_ivas->nchan_ism; + if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + { + /* set ISM parameters and decode ISM metadata in OSBA format */ + if ( ( error = ivas_osba_ism_metadata_dec( st_ivas, ivas_total_brate, &nchan_ism, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + sba_ch_idx = st_ivas->nchan_ism; + } + else + { + nb_bits_metadata[1] += NO_BITS_MASA_ISM_NO_OBJ; + sba_ch_idx = 0; + } + + /* SBA metadata decoding */ + if ( ( error = ivas_spar_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->nchan_transport == CPE_CHANNELS && st_ivas->nCPE >= 1 ) + { + st_ivas->hCPE[0]->element_brate = ivas_total_brate; + } + + /* core-decoding of transport channels */ + if ( st_ivas->nSCE == 1 ) + { + if ( ( error = ivas_sce_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE > 1 ) + { + if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + if ( st_ivas->sba_dirac_stereo_flag ) + { + ivas_agc_dec_process( st_ivas->hSpar->hAgcDec, &p_output[sba_ch_idx], &p_output[sba_ch_idx], st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); + + if ( st_ivas->hSpar->hPCA != NULL ) + { + ivas_pca_dec( 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[sba_ch_idx] ); + } + + ivas_spar_dec_gen_umx_mat( 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( st_ivas, &p_output[sba_ch_idx], output_frame ); + } + + /* HP filtering */ + for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + nchan_remapped = ivas_sba_remapTCs( &p_output[sba_ch_idx], st_ivas, output_frame ); + +#ifdef DEBUG_OSBA + if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + { + int16_t nchan = st_ivas->nchan_transport + st_ivas->nchan_ism; + for ( int16_t t = 0; t < output_frame; t++ ) + { + for ( int16_t c = 0; c < nchan; c++ ) + { + int16_t val = (int16_t) ( output[c][t] + 0.5f ); + dbgwrite( &val, sizeof( int16_t ), 1, 1, "./res/TC_dec_core_out.raw" ); + } + } + } +#endif + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || 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 ); + + ivas_sba_mix_matrix_determiner( st_ivas->hSpar, &p_output[sba_ch_idx], st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames ); + } + else if ( st_ivas->renderer_type != RENDERER_DISABLE && !st_ivas->sba_dirac_stereo_flag ) + { + ivas_spar_dec_agc_pca( st_ivas, &p_output[sba_ch_idx], output_frame ); + } + + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) + { + /* loudness correction */ + ivas_dirac_dec_binaural_sba_gain( &p_output[sba_ch_idx], nchan_remapped, output_frame ); + } + else if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX && st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + { + ivas_ism_mono_dmx( st_ivas, p_output, output_frame ); + + /* add W */ + for ( n = 0; n < nchan_out; n++ ) + { + v_add( p_output[n], p_output[n + max( nchan_out, nchan_ism )], p_output[n], output_frame ); + } + } + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; + + if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + /* LFE channel decoder */ + ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output[LFE_CHANNEL] ); + + if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* HP filtering */ + for ( n = 0; n < st_ivas->nchan_transport; n++ ) + { + if ( n != LFE_CHANNEL ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + } + + if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA3 ) ) + { + if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) + { + ivas_mc2sba( st_ivas->hTransSetup, p_output, p_output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); + } + } + + if ( ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + { + if ( st_ivas->renderer_type == RENDERER_MC ) + { + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); + } + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) + { + /* LFE channel decoder */ + ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output[LFE_CHANNEL] ); + + ivas_mc_paramupmix_dec_read_BS( st_ivas, st, st_ivas->hMCParamUpmix, &nb_bits_metadata[0] ); + + if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* HP filtering */ + for ( n = 0; n < st_ivas->nchan_transport; n++ ) + { + if ( n != LFE_CHANNEL ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + } + + /* Rendering */ + if ( st_ivas->renderer_type == RENDERER_MC && ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) ) + { + /* Compensate loudness for not doing full upmix */ + for ( n = 4; n < 8; n++ ) + { + v_multc( p_output[n], 2.0f, p_output[n], output_frame ); + } + + if ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) + { + ivas_ls_setup_conversion( st_ivas, audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 ), output_frame, p_output, p_output ); + } + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + /* read Parametric MC parameters from the bitstream */ + ivas_param_mc_dec_read_BS( ivas_total_brate, st, st_ivas->hParamMC, &nb_bits_metadata[0] ); + + if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE > 1 ) + { + if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* HP filtering */ + for ( n = 0; n < st_ivas->nchan_transport; n++ ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + /* Rendering */ + if ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) + { + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); + } + } + else if ( 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 ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + /* Decode the transport audio signals */ + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, 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; + + /* Decode the separated channel to output[n] to be combined with the synthesized channels */ + if ( ( error = ivas_sce_dec( st_ivas, 0, &p_output[n], output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* Delay the separated channel to sync with CLDFB delay of the DirAC synthesis, and synthesize the LFE signal. */ + if ( output_config == IVAS_AUDIO_CONFIG_5_1 || output_config == IVAS_AUDIO_CONFIG_7_1 || + output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || + output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) || output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) + { + ivas_lfe_synth_with_filters( st_ivas->hMasa->hMasaLfeSynth, p_output, output_frame, n, LFE_CHANNEL ); + } + else if ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) + { + /* Delay the separated channel to sync with the DirAC rendering */ + delay_signal( p_output[n], output_frame, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size ); + } + } + else + { + if ( st_ivas->nSCE == 1 ) + { + if ( ( error = ivas_sce_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( st_ivas->nCPE == 1 ) + { + if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + + if ( st_ivas->sba_dirac_stereo_flag ) /* use the flag to trigger the DFT upmix */ + { + ivas_sba_dirac_stereo_dec( st_ivas, p_output, output_frame ); + } + + /* HP filtering */ + for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) + { + hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + } + + if ( st_ivas->renderer_type == RENDERER_MCMASA_MONO_STEREO ) + { + ivas_mono_stereo_downmix_mcmasa( st_ivas, p_output, 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; + st_ivas->last_active_ivas_total_brate = ( ivas_total_brate <= IVAS_SID_5k2 ) ? st_ivas->last_active_ivas_total_brate : ivas_total_brate; + } + + if ( 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++; + } + + if ( st_ivas->ini_active_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && 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++; + } + + st_ivas->last_ivas_format = st_ivas->ivas_format; + +#ifdef DEBUG_MODE_INFO + dbgwrite( &st_ivas->bfi, sizeof( int16_t ), 1, output_frame, "res/bfi" ); + dbgwrite( &st_ivas->BER_detect, sizeof( int16_t ), 1, output_frame, "res/BER_detect" ); + { + float tmpF = ivas_total_brate / 1000.0f; + dbgwrite( &tmpF, sizeof( float ), 1, output_frame, "res/ivas_total_brate.dec" ); + } +#endif + + pop_wmops(); + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_get_num_tc_channels() + * + * Get the number of channels provided to the renderer + *--------------------------------------------------------------------------*/ + +int16_t ivas_dec_get_num_tc_channels( + Decoder_Struct *st_ivas /* i : IVAS decoder handle */ +) +{ + int16_t num_tc; + int32_t ivas_total_brate; + AUDIO_CONFIG output_config; + + if ( st_ivas->renderer_type == RENDERER_DISABLE ) + { + num_tc = st_ivas->hDecoderConfig->nchan_out; + } + else + { + num_tc = st_ivas->nchan_transport; + } + + output_config = st_ivas->hDecoderConfig->output_config; + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + if ( st_ivas->ivas_format == MONO_FORMAT ) + { + num_tc = 1; + } + else if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) + { + num_tc = 1; + } + else if ( st_ivas->ivas_format == ISM_FORMAT ) + { + if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) + { + num_tc = 1; + } + } + else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) + { + if ( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + } + else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0] != NULL && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) + { + num_tc = 1; /* Only one channel transported */ + } + + if ( st_ivas->ivas_format == MASA_FORMAT && output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->nchan_transport == 2 && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_5k2 ) + { + num_tc = CPE_CHANNELS; + } + + if ( st_ivas->ivas_format == SBA_FORMAT ) + { + if ( num_tc == 3 ) + { + num_tc++; + } + } + } + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { + if ( output_config != IVAS_AUDIO_CONFIG_EXTERNAL ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + { + num_tc++; + } + else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) + { + num_tc += st_ivas->nchan_ism; + } + } + } + else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) + { + if ( st_ivas->sba_dirac_stereo_flag ) + { + num_tc = CPE_CHANNELS; + } + if ( num_tc == 3 ) + { + num_tc++; + } + if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + { + num_tc += st_ivas->nchan_ism; + } + } + else if ( st_ivas->ivas_format == MC_FORMAT ) + { + if ( output_config == IVAS_AUDIO_CONFIG_MONO ) + { + num_tc = 1; + } + else if ( output_config == IVAS_AUDIO_CONFIG_STEREO ) + { + num_tc = 2; + } + else if ( st_ivas->mc_mode == MC_MODE_MCT ) + { + /* do all static dmx already in the TC decoder if less channels than transported... */ + if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA3 ) ) + { + if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) + { + num_tc = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; + } + } + else if ( ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + { + num_tc = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; + } + } + else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) + { + num_tc = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; + } + else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) + { + if ( st_ivas->hOutSetup.separateChannelEnabled ) + { + num_tc++; + } + + if ( st_ivas->hOutSetup.separateChannelEnabled && ( output_config == IVAS_AUDIO_CONFIG_5_1 || output_config == IVAS_AUDIO_CONFIG_7_1 || + output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || + output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) ) + { + /* LFE is synthesized in TD with the TCs */ + num_tc++; + } + } + } + + return num_tc; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_get_tc_buffer_mode() + * + * + *--------------------------------------------------------------------------*/ + +TC_BUFFER_MODE ivas_dec_get_tc_buffer_mode( + Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +) +{ + TC_BUFFER_MODE buffer_mode; + + buffer_mode = TC_BUFFER_MODE_BUFFER; + + 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; + 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; + break; + break; + case RENDERER_MC_PARAMMC: + if ( 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 */ + } + else + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; + case RENDERER_MC: + if ( ivas_dec_get_num_tc_channels( st_ivas ) != st_ivas->hDecoderConfig->nchan_out ) + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; + case RENDERER_SBA_LINEAR_ENC: + if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT && ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + } + else + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; + case RENDERER_SBA_LINEAR_DEC: + if ( st_ivas->ivas_format == SBA_FORMAT && ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO ) ) + { + buffer_mode = TC_BUFFER_MODE_BUFFER; + } + else + { + buffer_mode = TC_BUFFER_MODE_RENDERER; + } + break; +#ifdef DEBUGGING + default: + assert( 0 ); +#endif + } + + return buffer_mode; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_audio_allocate() + * + * allocate and initialize TC audio buffer + *--------------------------------------------------------------------------*/ + +static ivas_error ivas_dec_tc_audio_allocate( + DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: TC buffer handle */ + const int32_t output_Fs, /* i : output sampling rate */ + const int16_t Opt_tsm /* i : TSM option flag */ +) +{ + int16_t nsamp_to_allocate; + int16_t ch_idx, n_samp_full, n_samp_residual, offset; + + if ( Opt_tsm ) + { + n_samp_full = ( NS2SA( output_Fs, MAX_JBM_L_FRAME_NS ) ); + n_samp_full = max( n_samp_full, L_FRAME48k ); /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': ensure minimal length */ + n_samp_residual = hTcBuffer->n_samples_granularity - 1; + } + else + { + n_samp_full = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + n_samp_residual = 0; + } + + nsamp_to_allocate = 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 = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + } + set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); + + offset = 0; + for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; + offset += n_samp_full; + } + for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc[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[ch_idx] = (float *) malloc( n_samp_residual * sizeof( float ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); + } + set_zero( hTcBuffer->tc_buffer_old[ch_idx], n_samp_residual ); + } + for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_buffer_old[ch_idx] = NULL; + } + } + else + { + hTcBuffer->tc_buffer = NULL; + + for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = NULL; + } + + for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc_buffer_old[ch_idx] = NULL; + } + } + + hTcBuffer->tc_buffer2 = NULL; + + return IVAS_ERR_OK; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_buffer_open() + * + * Open and initialize transport channel buffer handle + *--------------------------------------------------------------------------*/ + +ivas_error ivas_dec_tc_buffer_open( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ + const int16_t nchan_transport_rend, /* i : number of TCs for rendering */ + const int16_t nchan_transport_internal, /* i : number of totally buffered channels */ + const int16_t nchan_full, /* i : number of channels to fully store */ + const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ +) +{ + DECODER_TC_BUFFER_HANDLE hTcBuffer; + int16_t nMaxSlotsPerSubframe; + ivas_error error; + + /*-----------------------------------------------------------------* + * 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; + hTcBuffer->nchan_transport_rend = nchan_transport_rend; + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + hTcBuffer->nchan_buffer_full = nchan_full; + hTcBuffer->n_samples_granularity = n_samples_granularity; + hTcBuffer->n_samples_available = 0; + hTcBuffer->n_samples_buffered = 0; + hTcBuffer->n_samples_rendered = 0; + hTcBuffer->slots_rendered = 0; + hTcBuffer->subframes_rendered = 0; + hTcBuffer->n_samples_discard = 0; + hTcBuffer->n_samples_flushed = 0; + hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; + + nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / hTcBuffer->n_samples_granularity; + hTcBuffer->num_slots = nMaxSlotsPerSubframe * MAX_PARAM_SPATIAL_SUBFRAMES; + set_s( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); + + if ( ( error = ivas_dec_tc_audio_allocate( 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_dec_tc_audio_deallocate() + * + * deallocate TC audio buffer + *--------------------------------------------------------------------------*/ + +static void ivas_dec_tc_audio_deallocate( + DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: TC buffer handle */ +) +{ + int16_t ch_idx; + + if ( hTcBuffer != NULL ) + { + if ( hTcBuffer->tc_buffer != NULL ) + { + for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + hTcBuffer->tc[ch_idx] = NULL; + } + + free( hTcBuffer->tc_buffer ); + hTcBuffer->tc_buffer = NULL; + } + + for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + { + if ( hTcBuffer->tc_buffer_old[ch_idx] != NULL ) + { + free( hTcBuffer->tc_buffer_old[ch_idx] ); + hTcBuffer->tc_buffer_old[ch_idx] = NULL; + } + } + + if ( hTcBuffer->tc_buffer2 != NULL ) + { + free( hTcBuffer->tc_buffer2 ); + hTcBuffer->tc_buffer2 = NULL; + } + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_buffer_close() + * + * Close transport channel buffer handle + *--------------------------------------------------------------------------*/ + +void ivas_dec_tc_buffer_close( + DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ +) +{ + if ( *phTcBuffer != NULL ) + { + ivas_dec_tc_audio_deallocate( *phTcBuffer ); + + free( *phTcBuffer ); + *phTcBuffer = NULL; + } + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_tc_buffer_reconfigure() + * + * Reconfigure transport channel buffer handle + *--------------------------------------------------------------------------*/ + +ivas_error ivas_dec_tc_buffer_reconfigure( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ + const int16_t nchan_transport_rend, /* i : new number of TCs for rendering */ + const int16_t nchan_transport_internal, /* i : new number of totally buffered channels */ + const int16_t nchan_full, /* i : new number of channels to fully store */ + const int16_t n_samples_granularity /* i : new granularity of the renderer/buffer */ +) +{ + int16_t ch_idx, num_tc_buffer_mem, n_samples_still_available; + float 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; + + num_tc_buffer_mem = 0; + n_samples_still_available = 0; + + if ( st_ivas->hDecoderConfig->Opt_tsm ) + { + /* save samples of the TC buffer from the previous frame */ + num_tc_buffer_mem = min( hTcBuffer->nchan_transport_internal, nchan_transport_internal ); + n_samples_still_available = 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++ ) + { + mvr2r( hTcBuffer->tc_buffer_old[ch_idx] + hTcBuffer->n_samples_flushed, tc_buffer_mem[ch_idx], n_samples_still_available ); + } + } + + /* if granularity changes, adapt subframe_nb_slots */ + if ( n_samples_granularity != hTcBuffer->n_samples_granularity ) + { +#ifdef DEBUGGING + int16_t nMaxSlotsPerSubframeOld; +#endif + int16_t nMaxSlotsPerSubframeNew; + + nMaxSlotsPerSubframeNew = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / n_samples_granularity; +#ifdef DEBUGGING + nMaxSlotsPerSubframeOld = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; + assert( hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] == nMaxSlotsPerSubframeOld ); + if ( n_samples_granularity < hTcBuffer->n_samples_granularity ) + { + assert( ( hTcBuffer->n_samples_granularity % n_samples_granularity ) == 0 ); + } + else + { + assert( ( n_samples_granularity % hTcBuffer->n_samples_granularity ) == 0 ); + } +#endif + /* if samples were flushed, take that into account here */ + if ( n_samples_granularity < hTcBuffer->n_samples_granularity && hTcBuffer->n_samples_flushed > 0 ) + { + hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = hTcBuffer->n_samples_flushed / n_samples_granularity; + hTcBuffer->n_samples_flushed = 0; + } + else + { + hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = nMaxSlotsPerSubframeNew; + } + } + + hTcBuffer->tc_buffer_mode = tc_buffer_mode; + hTcBuffer->nchan_transport_rend = nchan_transport_rend; + hTcBuffer->nchan_transport_internal = nchan_transport_internal; + hTcBuffer->nchan_buffer_full = nchan_full; + hTcBuffer->n_samples_granularity = n_samples_granularity; + + /* reallocate TC audio buffers */ + + ivas_dec_tc_audio_deallocate( hTcBuffer ); + + if ( ( error = ivas_dec_tc_audio_allocate( 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++ ) + { + mvr2r( tc_buffer_mem[ch_idx], hTcBuffer->tc_buffer_old[ch_idx], n_samples_still_available ); + } return IVAS_ERR_OK; } diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_dec_render.c similarity index 61% rename from lib_dec/ivas_jbm_dec.c rename to lib_dec/ivas_dec_render.c index 7daf20ab32..6806700255 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_dec_render.c @@ -59,673 +59,631 @@ static void ivas_jbm_masa_sf_to_slot_map( Decoder_Struct *st_ivas, const int16_t /*--------------------------------------------------------------------------* - * ivas_dec() + * 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( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ + int16_t *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ +) +{ + float tmp_buf[MAX_JBM_L_FRAME48k]; + float *p_data_f[FOA_CHANNELS + MAX_NUM_OBJECTS]; + int16_t n, n_render_timeslots, n_ch_cldfb; + int16_t ch, offset, len_offset; + DECODER_TC_BUFFER_HANDLE hTcBuffer; + + hTcBuffer = st_ivas->hTcBuffer; + n_ch_cldfb = hTcBuffer->nchan_transport_rend - hTcBuffer->nchan_buffer_full; + + if ( st_ivas->hDecoderConfig->Opt_tsm ) + { + int16_t n_samples_still_available; + int16_t n_ch_full_copy, n_ch_res_copy; + + n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; + hTcBuffer->n_samples_buffered = n_samples_still_available + nSamplesForRendering + hTcBuffer->n_samples_discard; + hTcBuffer->n_samples_available = hTcBuffer->n_samples_granularity * ( hTcBuffer->n_samples_buffered / hTcBuffer->n_samples_granularity ); + *nSamplesResidual = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_available; + n_ch_full_copy = min( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + n_ch_res_copy = 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( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ); + if ( len_offset < L_FRAME48k ) + { + offset = 0; + for ( ch = 0; ch < max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch++ ) + { + hTcBuffer->tc[ch] = &hTcBuffer->tc_buffer[offset]; + st_ivas->p_output_f[ch] = hTcBuffer->tc[ch]; + offset += len_offset; + } + } + + for ( ch = 0; ch < n_ch_full_copy; ch++ ) + { + mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); + set_zero( hTcBuffer->tc[ch], hTcBuffer->n_samples_discard ); + mvr2r( hTcBuffer->tc_buffer_old[ch], hTcBuffer->tc[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); + mvr2r( tmp_buf, hTcBuffer->tc[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); + mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); + } + + if ( n_ch_res_copy > 0 ) + { + for ( ; ch < hTcBuffer->nchan_transport_rend; ch++ ) + { + p_data_f[ch] = hTcBuffer->tc[ch]; + mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); + mvr2r( hTcBuffer->tc_buffer_old[ch], p_data_f[ch], n_samples_still_available ); + mvr2r( tmp_buf, p_data_f[ch] + n_samples_still_available, nSamplesForRendering - *nSamplesResidual ); + mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); + } + } + + n_render_timeslots = hTcBuffer->n_samples_available / hTcBuffer->n_samples_granularity; + } + else + { + for ( n = 0; n < n_ch_cldfb; n++ ) + { + p_data_f[n] = &st_ivas->p_output_f[n][0]; + } + + ch = max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); + for ( n = 0; n < ch; n++ ) + { + hTcBuffer->tc[n] = st_ivas->p_output_f[n]; /* note: buffers needed in the TD decorellator */ + } + + hTcBuffer->n_samples_buffered = nSamplesForRendering; + hTcBuffer->n_samples_available = hTcBuffer->n_samples_buffered; + *nSamplesResidual = 0; + + n_render_timeslots = DEFAULT_JBM_CLDFB_TIMESLOTS; + } + + /* CLDFB analysis for ParamMC/ParamISM */ + if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) ) + { + ivas_param_ism_dec_digest_tc( st_ivas, n_render_timeslots, p_data_f ); + } + else if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC && hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_RENDERER ) + { + ivas_param_mc_dec_digest_tc( st_ivas, (uint8_t) n_render_timeslots, p_data_f ); + } + + hTcBuffer->n_samples_rendered = 0; + hTcBuffer->subframes_rendered = 0; + + return; +} + + +/*--------------------------------------------------------------------------* + * ivas_dec_render() * - * Principal IVAS decoder routine, decoding of metadata and transport channels + * Principal IVAS internal rendering routine *--------------------------------------------------------------------------*/ -ivas_error ivas_dec( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ +ivas_error ivas_dec_render( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const uint16_t nSamplesAsked, /* i : number of samples wanted */ + uint16_t *nSamplesRendered, /* o : number of samples rendered */ + uint16_t *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ + const PCM_RESOLUTION pcm_resolution, /* i : type for the decoded PCM resolution */ + void *data /* o : output synthesis signal */ ) { - int16_t n, output_frame, nchan_out; - Decoder_State *st; /* used for bitstream handling */ - float *p_output[MAX_TRANSPORT_CHANNELS]; /* 'float' buffer for output synthesis */ + int16_t n, nchan_out; + int16_t nchan_transport_rend; int16_t nchan_remapped; - int16_t nb_bits_metadata[MAX_SCE + 1]; - int32_t output_Fs, ivas_total_brate; + int32_t output_Fs; AUDIO_CONFIG output_config; + int16_t nSamplesAskedLocal; ivas_error error; - int16_t num_md_sub_frames; - int32_t ism_total_brate; - - push_wmops( "ivas_dec" ); + float *p_output[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; + float *p_tc[MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS]; + int16_t 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; - nchan_out = st_ivas->hTcBuffer->nchan_transport_rend; + nchan_out = st_ivas->hDecoderConfig->nchan_out; + nchan_transport_rend = st_ivas->hTcBuffer->nchan_transport_rend; output_config = st_ivas->hDecoderConfig->output_config; - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; - - output_frame = (int16_t) ( output_Fs / FRAMES_PER_SEC ); + nSamplesAskedLocal = nSamplesAsked + st_ivas->hTcBuffer->n_samples_discard; - /* 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[n] = st_ivas->p_output_f[n]; - if ( p_output[n] != NULL ) + } + + if ( !st_ivas->hDecoderConfig->Opt_tsm ) + { + for ( n = 0; n < MAX_INTERN_CHANNELS; n++ ) { - set_zero( p_output[n], L_FRAME48k ); + st_ivas->hTcBuffer->tc[n] = p_output[n]; } } + for ( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) + { + p_tc[n] = &st_ivas->hTcBuffer->tc[n][st_ivas->hTcBuffer->n_samples_rendered]; + } + + /*----------------------------------------------------------------* + * 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 -= st_ivas->hTcBuffer->n_samples_discard; + + ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); + } + /*----------------------------------------------------------------* - * Decoding + pre-rendering + * Rendering *----------------------------------------------------------------*/ - if ( st_ivas->ivas_format == STEREO_FORMAT ) + *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); + + if ( st_ivas->ivas_format == UNDEFINED_FORMAT ) + { + assert( 0 ); + } + else if ( st_ivas->hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_BUFFER ) + { + ivas_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); + } + else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) { - st_ivas->hCPE[0]->element_brate = ivas_total_brate; - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, 0 ) ) != IVAS_ERR_OK ) + /* Rendering */ + if ( st_ivas->renderer_type == RENDERER_MC ) { - return error; + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); } - - /* HP filtering */ - for ( n = 0; n < min( nchan_out, st_ivas->nchan_transport ); n++ ) + else if ( st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) + { + ivas_apply_non_diegetic_panning( p_tc[0], p_output, st_ivas->hDecoderConfig->non_diegetic_pan_gain, *nSamplesRendered ); + } + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + ivas_stereo2sba( p_tc, p_output, *nSamplesRendered ); } } else if ( st_ivas->ivas_format == ISM_FORMAT ) { - /* Metadata decoding and configuration */ - if ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) + /* Rendering */ + if ( st_ivas->ism_mode == ISM_MODE_PARAM ) { - ivas_ism_dtx_dec( st_ivas, nb_bits_metadata ); - - /* decode dominant object first so the noise energy of the other objects can be limited */ - if ( ( error = ivas_sce_dec( st_ivas, st_ivas->hISMDTX.sce_id_dtx, &p_output[st_ivas->hISMDTX.sce_id_dtx], output_frame, nb_bits_metadata[st_ivas->hISMDTX.sce_id_dtx] ) ) != IVAS_ERR_OK ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - return error; + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, st_ivas->nchan_transport, p_output ); } - - ivas_ism_dtx_limit_noise_energy_for_near_silence( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport ); - - ivas_param_ism_dec_dequant_md( st_ivas ); - } - else if ( st_ivas->ism_mode == ISM_MODE_PARAM ) - { - if ( ( error = ivas_ism_metadata_dec( 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 ) + else if ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { - return error; - } + ivas_param_ism_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); - ivas_param_ism_dec_dequant_md( st_ivas ); + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + { + /* Convert CICP19 -> Ambisonics */ + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); + } + } } else /* ISM_MODE_DISC */ { - if ( ( error = ivas_ism_metadata_dec( 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 ) + /* Loudspeaker or Ambisonics rendering */ + if ( st_ivas->renderer_type == RENDERER_TD_PANNING || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - return error; + /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ + ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output, *nSamplesRendered ); + } + else if ( st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) + { + ivas_apply_non_diegetic_panning( p_tc[0], p_output, st_ivas->hDecoderConfig->non_diegetic_pan_gain, *nSamplesRendered ); + } +#ifdef DEBUGGING + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) +#else + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) +#endif + { + /* Convert to Ambisonics */ + ivas_ism2sba_sf( p_tc, p_output, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); } - } - for ( n = 0; n < st_ivas->nchan_transport; n++ ) - { - /* for DTX frames, dominant object has already been decoded before */ - if ( !( ( ivas_total_brate == IVAS_SID_5k2 || ivas_total_brate == FRAME_NO_DATA ) && n == st_ivas->hISMDTX.sce_id_dtx ) ) + /* Binaural rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) + { + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + { + if ( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else + { + if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + } + } + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - if ( ( error = ivas_sce_dec( st_ivas, n, &p_output[n], output_frame, nb_bits_metadata[n] ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_rend_crendProcessSubframe( 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, p_output, *nSamplesRendered, output_Fs, 0 ) ) != IVAS_ERR_OK ) { return error; } } - - /* HP filtering */ - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } - - if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) - { - ivas_ism_mono_dmx( st_ivas, p_output, output_frame ); - } - else if ( st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) ) - { - /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain( p_output, st_ivas->nchan_transport, output_frame ); } } else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) { - set_s( nb_bits_metadata, 0, MAX_SCE ); + nchan_remapped = nchan_transport_rend; - /* read parameters from the bitstream */ - if ( st_ivas->ivas_format == MASA_FORMAT && st_ivas->hQMetaData != NULL ) + /* Loudspeakers, Ambisonics or Binaural rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; - - if ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) - { - return error; - } + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); } - else if ( st_ivas->ivas_format == SBA_FORMAT ) + else if ( st_ivas->ivas_format == MASA_FORMAT ) { - if ( ( error = ivas_spar_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) + if ( st_ivas->renderer_type == RENDERER_DIRAC ) { - return error; + ivas_dirac_dec_render( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); } } - - if ( st_ivas->nchan_transport == CPE_CHANNELS && st_ivas->nCPE >= 1 ) - { - st_ivas->hCPE[0]->brate_surplus = 0; - st_ivas->hCPE[0]->element_brate = ivas_total_brate; - } - - /* core-decoding of transport channels */ - if ( st_ivas->nSCE == 1 ) - { - if ( ( error = ivas_sce_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( st_ivas->nCPE == 1 ) - { - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( st_ivas->nCPE > 1 ) + else { - if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) { return error; } } - -#ifdef DEBUG_SBA_AUDIO_DUMP - /* Dump audio signal after core-decoding */ - ivas_spar_dump_signal_wav( output_frame, NULL, output, st_ivas->nchan_transport, spar_foa_dec_wav[0], "core-decoding" ); -#endif - /* TCs remapping */ + } + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + { nchan_remapped = st_ivas->nchan_transport; - if ( st_ivas->sba_dirac_stereo_flag ) - { - nchan_remapped = nchan_out; - if ( st_ivas->ivas_format == SBA_FORMAT ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) + { + if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC ) { - ivas_agc_dec_process( st_ivas->hSpar->hAgcDec, p_output, p_output, st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); - - if ( st_ivas->hSpar->hPCA != NULL ) + if ( ( error = ivas_omasa_dirac_td_binaural( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ) ) != IVAS_ERR_OK ) { - ivas_pca_dec( 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 ); + return error; } - - ivas_spar_dec_gen_umx_mat( 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( st_ivas, p_output, output_frame ); - } - else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) - { - nchan_remapped = 1; /* Only one channel transported */ - } - - /* HP filtering */ -#ifndef DEBUG_SPAR_BYPASS_EVS_CODEC - for ( n = 0; n < nchan_remapped; n++ ) - { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } -#endif - - if ( st_ivas->ivas_format == SBA_FORMAT ) - { - nchan_remapped = ivas_sba_remapTCs( p_output, st_ivas, output_frame ); - - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || 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 ); - ivas_sba_mix_matrix_determiner( st_ivas->hSpar, p_output, st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames ); } - else if ( st_ivas->renderer_type != RENDERER_DISABLE ) + else { - ivas_spar_dec_agc_pca( st_ivas, p_output, output_frame ); + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); } } - - if ( st_ivas->ivas_format == MASA_FORMAT ) + else if ( st_ivas->renderer_type == RENDERER_DIRAC ) { - ivas_masa_prerender( st_ivas, p_output, output_frame, nchan_remapped ); - - /* external output */ - if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->hMasa->config.input_ivas_format == MASA_ISM_FORMAT ) - { - for ( n = 0; n < st_ivas->nchan_ism; n++ ) - { - set_zero( p_output[st_ivas->nchan_transport + n], output_frame ); - } - - ivas_omasa_rearrange_channels( p_output, st_ivas->nchan_ism, output_frame ); - } + ivas_omasa_dirac_rend( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); } - else if ( st_ivas->ivas_format == SBA_FORMAT && ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) ) + else if ( st_ivas->renderer_type == RENDERER_OMASA_OBJECT_EXT || st_ivas->renderer_type == RENDERER_OMASA_MIX_EXT ) { - /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain( p_output, nchan_remapped, output_frame ); + ivas_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); + ivas_omasa_rearrange_channels( p_output, st_ivas->nchan_ism, *nSamplesRendered ); } } - else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) + else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) { - int16_t nchan_ism, nchan_transport_ism; - int16_t dirac_bs_md_write_idx; - - set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); + nchan_remapped = nchan_transport_rend; - /* Set the number of objects for the parametric rendering */ - dirac_bs_md_write_idx = 0; - if ( st_ivas->hSpatParamRendCom != NULL ) + /* Loudspeakers, Ambisonics or Binaural rendering */ + if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) { - st_ivas->hSpatParamRendCom->numIsmDirections = 0; - if ( st_ivas->ism_mode != ISM_MASA_MODE_DISC && st_ivas->ism_mode != ISM_MASA_MODE_MASA_ONE_OBJ ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) { - st_ivas->hSpatParamRendCom->numIsmDirections = st_ivas->nchan_ism; + if ( ( error = ivas_osba_dirac_td_binaural( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) + { + return error; + } } - - dirac_bs_md_write_idx = st_ivas->hSpatParamRendCom->dirac_bs_md_write_idx; /* Store the write-index for this frame */ - } - - /* MASA metadata decoding */ - if ( ( error = ivas_masa_decode( 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 )] ); - - /* set ISM parameters and decode ISM metadata in OMASA format */ - if ( ( error = ivas_omasa_ism_metadata_dec( st_ivas, ism_total_brate, &nchan_ism, &nchan_transport_ism, dirac_bs_md_write_idx, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* decode ISM channels */ - for ( n = 0; n < nchan_transport_ism; n++ ) - { - if ( ( error = ivas_sce_dec( st_ivas, n, &p_output[st_ivas->nchan_transport + n], output_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + else if ( st_ivas->renderer_type == RENDERER_OSBA_STEREO ) { - return error; - } - } - - /* decode MASA channels */ - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( st_ivas->hCPE[0]->nchan_out == 1 ) - { - mvr2r( p_output[0], p_output[1], output_frame ); /* Copy mono signal to stereo output channels */ - } + /* shift SBA channels to avoid overwrite by ISM upmix in 1 object case and non-TSM unified channel memory*/ + if ( st_ivas->nchan_ism == 1 && st_ivas->hDecoderConfig->Opt_tsm == 0 ) + { + mvr2r( p_tc[2], p_output[3], *nSamplesRendered ); + mvr2r( p_tc[1], p_output[2], *nSamplesRendered ); + p_tc[1] = p_output[2]; + p_tc[2] = p_output[3]; + } - /* HP filtering */ - for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) - { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } + /* render objects */ + ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output, *nSamplesRendered ); - if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) - { - ivas_ism_mono_dmx( st_ivas, p_output, output_frame ); - } - else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) - { - if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) - { - ivas_omasa_rearrange_channels( p_output, nchan_transport_ism, output_frame ); + /* add already rendered SBA part */ + ivas_osba_stereo_add_channels( p_tc, p_output, st_ivas->hSbaIsmData->gain_bed, nchan_out, st_ivas->nchan_ism, *nSamplesRendered ); } - else if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ ) + else if ( st_ivas->renderer_type == RENDERER_OSBA_AMBI || st_ivas->renderer_type == RENDERER_OSBA_LS || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) { - /* Convert separate object to MASA, combine with the original MASA, and output combined MASA + empty objects. */ - ivas_omasa_combine_separate_ism_with_masa( st_ivas, p_output, st_ivas->nchan_ism, output_frame ); + if ( ( error = ivas_osba_render_sf( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) + { + return error; + } } - else if ( st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) + else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) /*EXT output = individual objects + HOA3*/ { - /* Extract objects from MASA, output MASA + all objects (i.e., extracted and separated objects) */ - ivas_omasa_render_objects_from_mix( st_ivas, p_output, st_ivas->nchan_ism, output_frame ); - } - } - } - else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) - { - int16_t nchan_ism, sba_ch_idx; + if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, &p_output[st_ivas->nchan_ism] ) ) != IVAS_ERR_OK ) + { + return error; + } - set_s( nb_bits_metadata, 0, MAX_SCE + 1 ); - nchan_ism = st_ivas->nchan_ism; - if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) - { - /* set ISM parameters and decode ISM metadata in OSBA format */ - if ( ( error = ivas_osba_ism_metadata_dec( st_ivas, ivas_total_brate, &nchan_ism, &nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) - { - return error; + for ( n = 0; n < st_ivas->nchan_ism; n++ ) + { + mvr2r( p_tc[n], p_output[n], *nSamplesRendered ); + } } - sba_ch_idx = st_ivas->nchan_ism; - } - else - { - nb_bits_metadata[1] += NO_BITS_MASA_ISM_NO_OBJ; - sba_ch_idx = 0; - } - - /* SBA metadata decoding */ - if ( ( error = ivas_spar_dec( st_ivas, nb_bits_metadata ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( st_ivas->nchan_transport == CPE_CHANNELS && st_ivas->nCPE >= 1 ) - { - st_ivas->hCPE[0]->element_brate = ivas_total_brate; - } - - /* core-decoding of transport channels */ - if ( st_ivas->nSCE == 1 ) - { - if ( ( error = ivas_sce_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + else { - return error; + if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) + { + return error; + } } } - else if ( st_ivas->nCPE == 1 ) + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) { - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); + for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) { - return error; + v_multc( p_output[n], 2.0f, p_output[n], *nSamplesRendered ); } } - else if ( st_ivas->nCPE > 1 ) + else { - if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) { return error; } - } - - if ( st_ivas->sba_dirac_stereo_flag ) - { - ivas_agc_dec_process( st_ivas->hSpar->hAgcDec, &p_output[sba_ch_idx], &p_output[sba_ch_idx], st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport, output_frame ); - - if ( st_ivas->hSpar->hPCA != NULL ) - { - ivas_pca_dec( 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[sba_ch_idx] ); - } - - ivas_spar_dec_gen_umx_mat( 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( st_ivas, &p_output[sba_ch_idx], output_frame ); - } - - /* HP filtering */ - for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) - { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } - - nchan_remapped = ivas_sba_remapTCs( &p_output[sba_ch_idx], st_ivas, output_frame ); -#ifdef DEBUG_OSBA - if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) - { - int16_t nchan = st_ivas->nchan_transport + st_ivas->nchan_ism; - for ( int16_t t = 0; t < output_frame; t++ ) + if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) { - for ( int16_t c = 0; c < nchan; c++ ) +#ifdef DEBUGGING + assert( st_ivas->ism_mode == ISM_MODE_NONE ); +#endif + for ( n = st_ivas->hIntSetup.nchan_out_woLFE - 1; n >= 0; n-- ) + { + mvr2r( p_output[n], p_output[n + st_ivas->nchan_ism], *nSamplesRendered ); + } + for ( n = 0; n < st_ivas->nchan_ism; n++ ) { - int16_t val = (int16_t) ( output[c][t] + 0.5f ); - dbgwrite( &val, sizeof( int16_t ), 1, 1, "./res/TC_dec_core_out.raw" ); + set_zero( p_output[n], *nSamplesRendered ); } } - } -#endif - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || 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 ); - - ivas_sba_mix_matrix_determiner( st_ivas->hSpar, &p_output[sba_ch_idx], st_ivas->bfi, nchan_remapped, output_frame, num_md_sub_frames ); - } - else if ( st_ivas->renderer_type != RENDERER_DISABLE && !st_ivas->sba_dirac_stereo_flag ) - { - ivas_spar_dec_agc_pca( st_ivas, &p_output[sba_ch_idx], output_frame ); - } - - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) - { - /* loudness correction */ - ivas_dirac_dec_binaural_sba_gain( &p_output[sba_ch_idx], nchan_remapped, output_frame ); - } - else if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX && st_ivas->ism_mode == ISM_SBA_MODE_DISC ) - { - ivas_ism_mono_dmx( st_ivas, p_output, output_frame ); - - /* add W */ - for ( n = 0; n < nchan_out; n++ ) + for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) { - v_add( p_output[n], p_output[n + max( nchan_out, nchan_ism )], p_output[n], output_frame ); + v_multc( p_output[n], 2.0f, p_output[n], *nSamplesRendered ); } } } else if ( st_ivas->ivas_format == MC_FORMAT ) { - st = ( st_ivas->nSCE > 0 ) ? st_ivas->hSCE[0]->hCoreCoder[0] : st_ivas->hCPE[0]->hCoreCoder[0]; - if ( st_ivas->mc_mode == MC_MODE_MCT ) { - /* LFE channel decoder */ - ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output[LFE_CHANNEL] ); - - if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - /* HP filtering */ - for ( n = 0; n < st_ivas->nchan_transport; n++ ) - { - if ( n != LFE_CHANNEL ) - { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } - } + int16_t crendInPlaceRotation = FALSE; if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA3 ) ) { - if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) + if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) { - ivas_mc2sba( st_ivas->hTransSetup, p_output, p_output, output_frame, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); + crendInPlaceRotation = TRUE; + ivas_mc2sba( st_ivas->hTransSetup, p_tc, p_output, *nSamplesRendered, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); } } - if ( ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) + /* Rendering */ + if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - if ( st_ivas->renderer_type == RENDERER_MC ) + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); + 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, crendInPlaceRotation ? p_output : p_tc, p_output, *nSamplesRendered, output_Fs ) ) != IVAS_ERR_OK ) + { + return error; + } } - else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + else { - ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, output_frame, st_ivas->hOutSetup.ambisonics_order, 0.f ); + if ( ( error = ivas_rend_crendProcessSubframe( 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, crendInPlaceRotation ? p_output : p_tc, p_output, *nSamplesRendered, output_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_tc, p_output ); } } - } - else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) - { - /* LFE channel decoder */ - ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output[LFE_CHANNEL] ); - - ivas_mc_paramupmix_dec_read_BS( st_ivas, st, st_ivas->hMCParamUpmix, &nb_bits_metadata[0] ); - - if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + else if ( st_ivas->renderer_type == RENDERER_MC ) { - return error; + ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); } - - /* HP filtering */ - for ( n = 0; n < st_ivas->nchan_transport; n++ ) + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { - if ( n != LFE_CHANNEL ) - { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } + ivas_mc2sba( st_ivas->hIntSetup, p_tc, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); } - - /* Rendering */ - if ( st_ivas->renderer_type == RENDERER_MC && ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) ) + else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) { - /* Compensate loudness for not doing full upmix */ - for ( n = 4; n < 8; n++ ) + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - v_multc( p_output[n], 2.0f, p_output[n], output_frame ); + if ( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } } - - if ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) + else { - ivas_ls_setup_conversion( st_ivas, audioCfg2channels( IVAS_AUDIO_CONFIG_5_1_2 ), output_frame, p_output, p_output ); + if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + { + return error; + } + + ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_tc, p_output ); } } } - else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) { - /* read Parametric MC parameters from the bitstream */ - ivas_param_mc_dec_read_BS( ivas_total_brate, st, st_ivas->hParamMC, &nb_bits_metadata[0] ); + ivas_mc_paramupmix_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_tc, p_output ); - if ( st_ivas->nCPE == 1 ) - { - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( st_ivas->nCPE > 1 ) + /* Rendering */ + if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && !st_ivas->hDecoderConfig->Opt_Headrotation ) { - if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + /* handled in CLDFB domain already */ + if ( output_config != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && output_config != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - return error; + ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_output, p_output ); } } - - /* HP filtering */ - for ( n = 0; n < st_ivas->nchan_transport; n++ ) + else if ( st_ivas->renderer_type == RENDERER_MC ) { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); + ivas_ls_setup_conversion( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, *nSamplesRendered, p_output, p_output ); } - - /* Rendering */ - if ( output_config == IVAS_AUDIO_CONFIG_MONO || output_config == IVAS_AUDIO_CONFIG_STEREO ) + else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { - ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, output_frame, p_output, p_output ); + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); } } + else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) + { + ivas_param_mc_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); + } else if ( 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 */ - } + nchan_remapped = st_ivas->nchan_transport; - /* read McMASA parameters from the bitstream */ - if ( ( error = ivas_masa_decode( st_ivas, st, &nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) { - return error; + ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); } - - if ( st_ivas->hOutSetup.separateChannelEnabled ) + else if ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) /* rendering to CICPxx and Ambisonics */ { - /* Decode the transport audio signals */ - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, 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; - - /* Decode the separated channel to output[n] to be combined with the synthesized channels */ - if ( ( error = ivas_sce_dec( st_ivas, 0, &p_output[n], output_frame, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } + ivas_dirac_dec_render( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); - /* Delay the separated channel to sync with CLDFB delay of the DirAC synthesis, and synthesize the LFE signal. */ - if ( output_config == IVAS_AUDIO_CONFIG_5_1 || output_config == IVAS_AUDIO_CONFIG_7_1 || - output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || - output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) || output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) - { - ivas_lfe_synth_with_filters( st_ivas->hMasa->hMasaLfeSynth, p_output, output_frame, n, LFE_CHANNEL ); - } - else if ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) - { - /* Delay the separated channel to sync with the DirAC rendering */ - delay_signal( p_output[n], output_frame, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC, st_ivas->hMasa->hMasaLfeSynth->delayBuffer_syncDirAC_size ); - } - } - else - { - if ( st_ivas->nSCE == 1 ) + if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) { - if ( ( error = ivas_sce_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + /* we still need to copy the separate channel if available */ + if ( st_ivas->hOutSetup.separateChannelEnabled ) { - return error; + mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); } + + ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); } - else if ( st_ivas->nCPE == 1 ) + else if ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_5_1 && ( output_config == IVAS_AUDIO_CONFIG_5_1_2 || output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1 ) ) { - if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + 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++ ) { - return error; + set_zero( p_output[n], *nSamplesRendered ); } } } - if ( st_ivas->sba_dirac_stereo_flag ) /* use the flag to trigger the DFT upmix */ - { - ivas_sba_dirac_stereo_dec( st_ivas, p_output, output_frame ); - } - - /* HP filtering */ - for ( n = 0; n < getNumChanSynthesis( st_ivas ); n++ ) - { - hp20( p_output[n], output_frame, st_ivas->mem_hp20_out[n], output_Fs ); - } - - if ( st_ivas->renderer_type == RENDERER_MCMASA_MONO_STEREO ) + /* copy discrete C and TD LFE from internal TC to output */ + if ( st_ivas->hOutSetup.separateChannelEnabled ) { - ivas_mono_stereo_downmix_mcmasa( st_ivas, p_output, output_frame ); + if ( output_config == IVAS_AUDIO_CONFIG_5_1 || output_config == IVAS_AUDIO_CONFIG_7_1 || + output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || + output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) + { + mvr2r( p_tc[LFE_CHANNEL], p_output[LFE_CHANNEL], *nSamplesRendered ); + mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); + } + else if ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) + { + mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); + } } } } /*----------------------------------------------------------------* - * 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 -= *nSamplesRendered; + st_ivas->hTcBuffer->n_samples_rendered += *nSamplesRendered; + + /* 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; - st_ivas->last_active_ivas_total_brate = ( ivas_total_brate <= IVAS_SID_5k2 ) ? st_ivas->last_active_ivas_total_brate : ivas_total_brate; + for ( n = 0; n < min( MAX_OUTPUT_CHANNELS, ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ) ); n++ ) + { + p_output[n] += st_ivas->hTcBuffer->n_samples_discard; + } + *nSamplesRendered -= st_ivas->hTcBuffer->n_samples_discard; + st_ivas->hTcBuffer->n_samples_discard = 0; } - if ( 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 */ + if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) { - st_ivas->ini_frame++; + nchan_out_syn_output = BINAURAL_CHANNELS * st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; +#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR + if ( st_ivas->flushing ) + { + nchan_out_syn_output = BINAURAL_CHANNELS; + } +#endif } - - if ( st_ivas->ini_active_frame < MAX_FRAME_COUNTER && !( st_ivas->bfi && st_ivas->ini_frame == 0 ) && 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 */ + else { - st_ivas->ini_active_frame++; + nchan_out_syn_output = nchan_out; } - st_ivas->last_ivas_format = st_ivas->ivas_format; - -#ifdef DEBUG_MODE_INFO - dbgwrite( &st_ivas->bfi, sizeof( int16_t ), 1, output_frame, "res/bfi" ); - dbgwrite( &st_ivas->BER_detect, sizeof( int16_t ), 1, output_frame, "res/BER_detect" ); + if ( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) { - float tmpF = ivas_total_brate / 1000.0f; - dbgwrite( &tmpF, sizeof( float ), 1, output_frame, "res/ivas_total_brate.dec" ); + if ( st_ivas->ivas_format != MONO_FORMAT ) + { +#ifndef DISABLE_LIMITER + ivas_limiter_dec( st_ivas->hLimiter, p_output, nchan_out, *nSamplesRendered, st_ivas->BER_detect ); +#endif + } } + + switch ( pcm_resolution ) + { + case PCM_INT16: +#ifdef DEBUGGING + st_ivas->noClipping += #endif + ivas_syn_output( p_output, *nSamplesRendered, nchan_out_syn_output, (int16_t *) data ); + + break; + case PCM_FLOAT32: + ivas_buffer_deinterleaved_to_interleaved( p_output, nchan_out_syn_output, *nSamplesRendered, (float *) data ); + break; + default: + error = IVAS_ERR_UNKNOWN; + break; + } + + *nSamplesAvailableNext = st_ivas->hTcBuffer->n_samples_available; pop_wmops(); return IVAS_ERR_OK; @@ -733,1470 +691,415 @@ ivas_error ivas_dec( /*--------------------------------------------------------------------------* - * 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( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const int16_t nSamplesForRendering, /* i : number of TC samples available for rendering */ - int16_t *nSamplesResidual /* o : number of samples not fitting into the renderer grid and buffer for the next call*/ +ivas_error ivas_jbm_dec_flush_renderer( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const int16_t 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 */ + uint16_t *nSamplesRendered, /* o : number of samples flushed */ + const PCM_RESOLUTION pcm_resolution, /* i : type for the decoded PCM resolution */ + void *data /* o : output synthesis signal */ ) { - float tmp_buf[MAX_JBM_L_FRAME48k]; - float *p_data_f[FOA_CHANNELS + MAX_NUM_OBJECTS]; - int16_t n, n_render_timeslots, n_ch_cldfb; - int16_t ch, offset, len_offset; + ivas_error error; + int16_t n_samples_still_available; + int16_t n_slots_still_available; + int16_t n_samples_to_render; + int16_t ch_idx; + int16_t n_samples_granularity; DECODER_TC_BUFFER_HANDLE hTcBuffer; + float *p_output[MAX_LS_CHANNELS + MAX_NUM_OBJECTS]; - hTcBuffer = st_ivas->hTcBuffer; - n_ch_cldfb = hTcBuffer->nchan_transport_rend - hTcBuffer->nchan_buffer_full; - - if ( st_ivas->hDecoderConfig->Opt_tsm ) + if ( !st_ivas->hDecoderConfig->Opt_tsm ) { - int16_t n_samples_still_available; - int16_t n_ch_full_copy, n_ch_res_copy; + return IVAS_ERR_OK; + } - n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; - hTcBuffer->n_samples_buffered = n_samples_still_available + nSamplesForRendering + hTcBuffer->n_samples_discard; - hTcBuffer->n_samples_available = hTcBuffer->n_samples_granularity * ( hTcBuffer->n_samples_buffered / hTcBuffer->n_samples_granularity ); - *nSamplesResidual = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_available; - n_ch_full_copy = min( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); - n_ch_res_copy = hTcBuffer->nchan_transport_rend - hTcBuffer->nchan_buffer_full; + for ( ch_idx = 0; ch_idx < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; ch_idx++ ) + { + p_output[ch_idx] = st_ivas->p_output_f[ch_idx]; + } - /* 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( st_ivas->hDecoderConfig->output_Fs, MAX_JBM_L_FRAME_NS ); - if ( len_offset < L_FRAME48k ) - { - offset = 0; - for ( ch = 0; ch < max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch++ ) - { - hTcBuffer->tc[ch] = &hTcBuffer->tc_buffer[offset]; - st_ivas->p_output_f[ch] = hTcBuffer->tc[ch]; - offset += len_offset; - } - } + *nSamplesRendered = 0; + hTcBuffer = st_ivas->hTcBuffer; + n_samples_granularity = hTcBuffer->n_samples_granularity; - for ( ch = 0; ch < n_ch_full_copy; ch++ ) - { - mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); - set_zero( hTcBuffer->tc[ch], hTcBuffer->n_samples_discard ); - mvr2r( hTcBuffer->tc_buffer_old[ch], hTcBuffer->tc[ch] + hTcBuffer->n_samples_discard, n_samples_still_available ); - mvr2r( tmp_buf, hTcBuffer->tc[ch] + n_samples_still_available + hTcBuffer->n_samples_discard, nSamplesForRendering - *nSamplesResidual ); - mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); - } + /* get number of possible slots in new granularity */ + n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; + n_slots_still_available = n_samples_still_available / tc_granularity_new; + *nSamplesRendered = n_slots_still_available * tc_granularity_new; + n_samples_to_render = *nSamplesRendered; + n_samples_still_available -= n_samples_to_render; + assert( n_samples_still_available < tc_granularity_new ); - if ( n_ch_res_copy > 0 ) - { - for ( ; ch < hTcBuffer->nchan_transport_rend; ch++ ) - { - p_data_f[ch] = hTcBuffer->tc[ch]; - mvr2r( hTcBuffer->tc[ch], tmp_buf, nSamplesForRendering ); - mvr2r( hTcBuffer->tc_buffer_old[ch], p_data_f[ch], n_samples_still_available ); - mvr2r( tmp_buf, p_data_f[ch] + n_samples_still_available, nSamplesForRendering - *nSamplesResidual ); - mvr2r( tmp_buf + nSamplesForRendering - *nSamplesResidual, hTcBuffer->tc_buffer_old[ch], *nSamplesResidual ); - } - } + /* update combined orientation access index */ + ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); - n_render_timeslots = hTcBuffer->n_samples_available / hTcBuffer->n_samples_granularity; - } - else + if ( n_slots_still_available ) { - for ( n = 0; n < n_ch_cldfb; n++ ) - { - p_data_f[n] = &st_ivas->p_output_f[n][0]; - } - - ch = max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); - for ( n = 0; n < ch; n++ ) + /* render available full slots (with new lower granularity) */ + for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) { - hTcBuffer->tc[n] = st_ivas->p_output_f[n]; /* note: buffers needed in the TD decorellator */ + /* move it at the beginning of the TC buffer with zero padding */ + mvr2r( hTcBuffer->tc_buffer_old[ch_idx], hTcBuffer->tc[ch_idx], n_samples_to_render ); + set_zero( hTcBuffer->tc[ch_idx] + n_samples_to_render, hTcBuffer->n_samples_granularity - n_samples_to_render ); } - hTcBuffer->n_samples_buffered = nSamplesForRendering; - hTcBuffer->n_samples_available = hTcBuffer->n_samples_buffered; - *nSamplesResidual = 0; - - n_render_timeslots = DEFAULT_JBM_CLDFB_TIMESLOTS; - } - - /* CLDFB analysis for ParamMC/ParamISM */ - if ( st_ivas->ivas_format == ISM_FORMAT && st_ivas->ism_mode == ISM_MODE_PARAM && ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) ) - { - ivas_param_ism_dec_digest_tc( st_ivas, n_render_timeslots, p_data_f ); - } - else if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_PARAMMC && hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_RENDERER ) - { - ivas_param_mc_dec_digest_tc( st_ivas, (uint8_t) n_render_timeslots, p_data_f ); - } - - hTcBuffer->n_samples_rendered = 0; - hTcBuffer->subframes_rendered = 0; - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_render() - * - * Principal IVAS internal rendering routine - *--------------------------------------------------------------------------*/ - -ivas_error ivas_dec_render( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const uint16_t nSamplesAsked, /* i : number of samples wanted */ - uint16_t *nSamplesRendered, /* o : number of samples rendered */ - uint16_t *nSamplesAvailableNext, /* o : number of samples still available in the rendering pipeline */ - const PCM_RESOLUTION pcm_resolution, /* i : type for the decoded PCM resolution */ - void *data /* o : output synthesis signal */ -) -{ - int16_t n, nchan_out; - int16_t nchan_transport_rend; - int16_t nchan_remapped; - int32_t output_Fs; - AUDIO_CONFIG output_config; - int16_t nSamplesAskedLocal; - ivas_error error; - float *p_output[MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS]; - float *p_tc[MAX_TRANSPORT_CHANNELS + MAX_NUM_OBJECTS]; - int16_t 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; - nchan_out = st_ivas->hDecoderConfig->nchan_out; - nchan_transport_rend = st_ivas->hTcBuffer->nchan_transport_rend; - output_config = st_ivas->hDecoderConfig->output_config; - nSamplesAskedLocal = nSamplesAsked + st_ivas->hTcBuffer->n_samples_discard; + /* 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 = 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; - for ( n = 0; n < MAX_OUTPUT_CHANNELS + MAX_NUM_OBJECTS; n++ ) - { - p_output[n] = st_ivas->p_output_f[n]; - } - if ( !st_ivas->hDecoderConfig->Opt_tsm ) - { - for ( n = 0; n < MAX_INTERN_CHANNELS; n++ ) + if ( st_ivas->ivas_format == ISM_FORMAT ) { - st_ivas->hTcBuffer->tc[n] = p_output[n]; - } - } - - for ( n = 0; n < st_ivas->hTcBuffer->nchan_buffer_full; n++ ) - { - p_tc[n] = &st_ivas->hTcBuffer->tc[n][st_ivas->hTcBuffer->n_samples_rendered]; - } - - /*----------------------------------------------------------------* - * 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 -= st_ivas->hTcBuffer->n_samples_discard; - - ivas_combined_orientation_set_to_start_index( st_ivas->hCombinedOrientationData ); - } - - /*----------------------------------------------------------------* - * Rendering - *----------------------------------------------------------------*/ + if ( ism_mode_old == ISM_MODE_DISC ) + { + /* Binaural rendering */ + if ( renderer_type_old == RENDERER_BINAURAL_OBJECTS_TD ) + { + if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, n_samples_granularity ) ) != IVAS_ERR_OK ) + { + return error; + } + } + else if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM ) + { + /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ + set_f( st_ivas->hIsmRendererData->interpolator, 1.0f, n_samples_granularity ); - *nSamplesRendered = min( st_ivas->hTcBuffer->n_samples_available, nSamplesAskedLocal ); + ivas_ism_render_sf( st_ivas, renderer_type_old, p_output, n_samples_granularity ); - if ( st_ivas->ivas_format == UNDEFINED_FORMAT ) - { - assert( 0 ); - } - else if ( st_ivas->hTcBuffer->tc_buffer_mode == TC_BUFFER_MODE_BUFFER ) - { - ivas_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); - } - else if ( st_ivas->ivas_format == MONO_FORMAT || st_ivas->ivas_format == STEREO_FORMAT ) - { - /* Rendering */ - if ( st_ivas->renderer_type == RENDERER_MC ) - { - ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); - } - else if ( st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) - { - ivas_apply_non_diegetic_panning( p_tc[0], p_output, st_ivas->hDecoderConfig->non_diegetic_pan_gain, *nSamplesRendered ); - } - else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - ivas_stereo2sba( p_tc, p_output, *nSamplesRendered ); - } - } - else if ( st_ivas->ivas_format == ISM_FORMAT ) - { - /* Rendering */ - if ( st_ivas->ism_mode == ISM_MODE_PARAM ) - { - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) - { - ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, st_ivas->nchan_transport, p_output ); + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, + NULL, NULL, hTcBuffer, p_output, p_output, n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + } } - else if ( st_ivas->renderer_type == RENDERER_PARAM_ISM || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) + else { - ivas_param_ism_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); - - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - /* Convert CICP19 -> Ambisonics */ - ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); - } + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong ISM_MODE in VoIP renderer flushing!" ); } } - else /* ISM_MODE_DISC */ + else if ( st_ivas->ivas_format == MC_FORMAT ) { - /* Loudspeaker or Ambisonics rendering */ - if ( st_ivas->renderer_type == RENDERER_TD_PANNING || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ - ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output, *nSamplesRendered ); - } - else if ( st_ivas->renderer_type == RENDERER_NON_DIEGETIC_DOWNMIX ) - { - ivas_apply_non_diegetic_panning( p_tc[0], p_output, st_ivas->hDecoderConfig->non_diegetic_pan_gain, *nSamplesRendered ); - } -#ifdef DEBUGGING - else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) -#else - else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) -#endif + if ( mc_mode_old == MC_MODE_MCT ) { - /* Convert to Ambisonics */ - ivas_ism2sba_sf( p_tc, p_output, st_ivas->hIsmRendererData, st_ivas->nchan_transport, *nSamplesRendered, st_ivas->hTcBuffer->n_samples_rendered, st_ivas->hIntSetup.ambisonics_order ); - } + int16_t crendInPlaceRotation = FALSE; - /* Binaural rendering */ - if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) - { - if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) + if ( st_ivas->transport_config != intern_config_old && ( intern_config_old == IVAS_AUDIO_CONFIG_FOA || intern_config_old == IVAS_AUDIO_CONFIG_HOA2 || intern_config_old == IVAS_AUDIO_CONFIG_HOA3 ) ) { - if ( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) < ( hIntSetupOld->nchan_out_woLFE + hIntSetupOld->num_lfe ) ) { - return error; + crendInPlaceRotation = TRUE; + ivas_mc2sba( st_ivas->hTransSetup, hTcBuffer->tc, p_output, n_samples_granularity, hIntSetupOld->ambisonics_order, GAIN_LFE ); } } - else + if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV || renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM ) { - if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) + if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, + hIntSetupOld, st_ivas->hEFAPdata, hTcBuffer, crendInPlaceRotation ? p_output : hTcBuffer->tc, p_output, n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ) != IVAS_ERR_OK ) { return error; } + + ivas_binaural_add_LFE( st_ivas, n_samples_granularity, hTcBuffer->tc, p_output ); } - } - else if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - if ( ( error = ivas_rend_crendProcessSubframe( 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, p_output, *nSamplesRendered, output_Fs, 0 ) ) != IVAS_ERR_OK ) + else if ( renderer_type_old == RENDERER_BINAURAL_OBJECTS_TD ) { - return error; - } - } - } - } - else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) - { - nchan_remapped = nchan_transport_rend; - - /* Loudspeakers, Ambisonics or Binaural rendering */ - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) - { - ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); - } - else if ( st_ivas->ivas_format == MASA_FORMAT ) - { - if ( st_ivas->renderer_type == RENDERER_DIRAC ) - { - ivas_dirac_dec_render( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); - } - } - else - { - if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } - else if ( st_ivas->ivas_format == MASA_ISM_FORMAT ) - { - nchan_remapped = st_ivas->nchan_transport; + if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, n_samples_granularity ) ) != IVAS_ERR_OK ) + { + return error; + } - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) - { - if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC && st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC ) - { - if ( ( error = ivas_omasa_dirac_td_binaural( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ) ) != IVAS_ERR_OK ) + ivas_binaural_add_LFE( st_ivas, n_samples_granularity, hTcBuffer->tc, p_output ); + } + else { - return error; + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong renderer in MCT VoIP renderer flushing!" ); } } else { - ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong MC_MODE in VoIP renderer flushing!" ); } } - else if ( st_ivas->renderer_type == RENDERER_DIRAC ) + else if ( st_ivas->ivas_format == MASA_ISM_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) { - ivas_omasa_dirac_rend( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); - } - else if ( st_ivas->renderer_type == RENDERER_OMASA_OBJECT_EXT || st_ivas->renderer_type == RENDERER_OMASA_MIX_EXT ) - { - ivas_dec_tc_buffer_playout( st_ivas, nSamplesAskedLocal, nSamplesRendered, p_output ); - ivas_omasa_rearrange_channels( p_output, st_ivas->nchan_ism, *nSamplesRendered ); - } - } - else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) - { - nchan_remapped = nchan_transport_rend; - - /* Loudspeakers, Ambisonics or Binaural rendering */ - if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) - { - if ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ) - { - if ( ( error = ivas_osba_dirac_td_binaural( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( st_ivas->renderer_type == RENDERER_OSBA_STEREO ) - { - /* shift SBA channels to avoid overwrite by ISM upmix in 1 object case and non-TSM unified channel memory*/ - if ( st_ivas->nchan_ism == 1 && st_ivas->hDecoderConfig->Opt_tsm == 0 ) - { - mvr2r( p_tc[2], p_output[3], *nSamplesRendered ); - mvr2r( p_tc[1], p_output[2], *nSamplesRendered ); - p_tc[1] = p_output[2]; - p_tc[2] = p_output[3]; - } - - /* render objects */ - ivas_ism_render_sf( st_ivas, st_ivas->renderer_type, p_output, *nSamplesRendered ); - - /* add already rendered SBA part */ - ivas_osba_stereo_add_channels( p_tc, p_output, st_ivas->hSbaIsmData->gain_bed, nchan_out, st_ivas->nchan_ism, *nSamplesRendered ); - } - else if ( st_ivas->renderer_type == RENDERER_OSBA_AMBI || st_ivas->renderer_type == RENDERER_OSBA_LS || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) - { - if ( ( error = ivas_osba_render_sf( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) /*EXT output = individual objects + HOA3*/ - { - if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, &p_output[st_ivas->nchan_ism] ) ) != IVAS_ERR_OK ) - { - return error; - } - - for ( n = 0; n < st_ivas->nchan_ism; n++ ) - { - mvr2r( p_tc[n], p_output[n], *nSamplesRendered ); - } - } - else - { - if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) - { - return error; - } - } - } - else if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM ) - { - ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); - for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) - { - v_multc( p_output[n], 2.0f, p_output[n], *nSamplesRendered ); - } - } - else - { - if ( ( error = ivas_sba_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ) ) != IVAS_ERR_OK ) - { - return error; - } - - if ( output_config == IVAS_AUDIO_CONFIG_EXTERNAL ) - { -#ifdef DEBUGGING - assert( st_ivas->ism_mode == ISM_MODE_NONE ); -#endif - for ( n = st_ivas->hIntSetup.nchan_out_woLFE - 1; n >= 0; n-- ) - { - mvr2r( p_output[n], p_output[n + st_ivas->nchan_ism], *nSamplesRendered ); - } - for ( n = 0; n < st_ivas->nchan_ism; n++ ) - { - set_zero( p_output[n], *nSamplesRendered ); - } - } - for ( n = 0; n < st_ivas->hDecoderConfig->nchan_out; n++ ) - { - v_multc( p_output[n], 2.0f, p_output[n], *nSamplesRendered ); - } - } - } - else if ( st_ivas->ivas_format == MC_FORMAT ) - { - if ( st_ivas->mc_mode == MC_MODE_MCT ) - { - int16_t crendInPlaceRotation = FALSE; - - if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA3 ) ) - { - if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) < ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) - { - crendInPlaceRotation = TRUE; - ivas_mc2sba( st_ivas->hTransSetup, p_tc, p_output, *nSamplesRendered, st_ivas->hIntSetup.ambisonics_order, GAIN_LFE ); - } - } - - /* Rendering */ - if ( st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV || st_ivas->renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || 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, crendInPlaceRotation ? p_output : p_tc, p_output, *nSamplesRendered, output_Fs ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - if ( ( error = ivas_rend_crendProcessSubframe( 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, crendInPlaceRotation ? p_output : p_tc, p_output, *nSamplesRendered, output_Fs, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_tc, p_output ); - } - } - else if ( st_ivas->renderer_type == RENDERER_MC ) - { - ivas_ls_setup_conversion( st_ivas, st_ivas->nchan_transport, *nSamplesRendered, p_tc, p_output ); - } - else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - ivas_mc2sba( st_ivas->hIntSetup, p_tc, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); - } - else if ( st_ivas->renderer_type == RENDERER_BINAURAL_OBJECTS_TD ) - { - if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - if ( ( error = ivas_td_binaural_renderer_sf_splitBinaural( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else - { - if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, *nSamplesRendered ) ) != IVAS_ERR_OK ) - { - return error; - } - - ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_tc, p_output ); - } - } - } - else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) - { - ivas_mc_paramupmix_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_tc, p_output ); - - /* Rendering */ - if ( ( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV || st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV_ROOM ) && !st_ivas->hDecoderConfig->Opt_Headrotation ) - { - /* handled in CLDFB domain already */ - if ( output_config != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED && output_config != IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - ivas_binaural_add_LFE( st_ivas, *nSamplesRendered, p_output, p_output ); - } - } - else if ( st_ivas->renderer_type == RENDERER_MC ) - { - ivas_ls_setup_conversion( st_ivas, MC_PARAMUPMIX_MAX_INPUT_CHANS, *nSamplesRendered, p_output, p_output ); - } - else if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); - } - } - else if ( st_ivas->mc_mode == MC_MODE_PARAMMC ) - { - ivas_param_mc_dec_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); - } - else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) - { - nchan_remapped = st_ivas->nchan_transport; - - if ( st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC || st_ivas->renderer_type == RENDERER_BINAURAL_PARAMETRIC_ROOM || st_ivas->renderer_type == RENDERER_STEREO_PARAMETRIC ) - { - ivas_dirac_dec_binaural_render( st_ivas, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, nchan_remapped, p_output ); - } - else if ( st_ivas->renderer_type == RENDERER_DIRAC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) /* rendering to CICPxx and Ambisonics */ - { - ivas_dirac_dec_render( st_ivas, nchan_remapped, nSamplesAskedLocal, nSamplesRendered, nSamplesAvailableNext, p_output ); - - if ( st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) - { - /* we still need to copy the separate channel if available */ - if ( st_ivas->hOutSetup.separateChannelEnabled ) - { - mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); - } - - ivas_mc2sba( st_ivas->hIntSetup, p_output, p_output, *nSamplesRendered, st_ivas->hOutSetup.ambisonics_order, 0.f ); - } - else if ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_5_1 && ( output_config == IVAS_AUDIO_CONFIG_5_1_2 || output_config == IVAS_AUDIO_CONFIG_5_1_4 || 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++ ) - { - set_zero( p_output[n], *nSamplesRendered ); - } - } - } - - /* copy discrete C and TD LFE from internal TC to output */ - if ( st_ivas->hOutSetup.separateChannelEnabled ) - { - if ( output_config == IVAS_AUDIO_CONFIG_5_1 || output_config == IVAS_AUDIO_CONFIG_7_1 || - output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || - output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) - { - mvr2r( p_tc[LFE_CHANNEL], p_output[LFE_CHANNEL], *nSamplesRendered ); - mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); - } - else if ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe == 0 ) - { - mvr2r( p_tc[LFE_CHANNEL - 1], p_output[st_ivas->hOutSetup.separateChannelIndex], *nSamplesRendered ); - } - } - } - } - - /*----------------------------------------------------------------* - * Write IVAS output channels - * - compensation for saturation - * - float to integer conversion - *----------------------------------------------------------------*/ - - st_ivas->hTcBuffer->n_samples_available -= *nSamplesRendered; - st_ivas->hTcBuffer->n_samples_rendered += *nSamplesRendered; - - /* 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 < min( MAX_OUTPUT_CHANNELS, ivas_get_nchan_buffers_dec( st_ivas, st_ivas->sba_analysis_order, st_ivas->hDecoderConfig->ivas_total_brate ) ); n++ ) - { - p_output[n] += st_ivas->hTcBuffer->n_samples_discard; - } - *nSamplesRendered -= st_ivas->hTcBuffer->n_samples_discard; - st_ivas->hTcBuffer->n_samples_discard = 0; - } - - if ( output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_CODED || output_config == IVAS_AUDIO_CONFIG_BINAURAL_SPLIT_PCM ) - { - nchan_out_syn_output = BINAURAL_CHANNELS * st_ivas->hSplitBinRend->splitrend.multiBinPoseData.num_poses; -#ifdef TMP_1342_WORKAROUND_DEC_FLUSH_BROKEN_IN_SR - if ( st_ivas->flushing ) - { - nchan_out_syn_output = BINAURAL_CHANNELS; - } -#endif - } - else - { - nchan_out_syn_output = nchan_out; - } - - if ( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) - { - if ( st_ivas->ivas_format != MONO_FORMAT ) - { -#ifndef DISABLE_LIMITER - ivas_limiter_dec( st_ivas->hLimiter, p_output, nchan_out, *nSamplesRendered, st_ivas->BER_detect ); -#endif - } - } - - switch ( pcm_resolution ) - { - case PCM_INT16: -#ifdef DEBUGGING - st_ivas->noClipping += -#endif - ivas_syn_output( p_output, *nSamplesRendered, nchan_out_syn_output, (int16_t *) data ); - - break; - case PCM_FLOAT32: - ivas_buffer_deinterleaved_to_interleaved( p_output, nchan_out_syn_output, *nSamplesRendered, (float *) data ); - break; - default: - error = IVAS_ERR_UNKNOWN; - break; - } - - *nSamplesAvailableNext = st_ivas->hTcBuffer->n_samples_available; - - 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( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const int16_t 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 */ - uint16_t *nSamplesRendered, /* o : number of samples flushed */ - const PCM_RESOLUTION pcm_resolution, /* i : type for the decoded PCM resolution */ - void *data /* o : output synthesis signal */ -) -{ - ivas_error error; - int16_t n_samples_still_available; - int16_t n_slots_still_available; - int16_t n_samples_to_render; - int16_t ch_idx; - int16_t n_samples_granularity; - DECODER_TC_BUFFER_HANDLE hTcBuffer; - float *p_output[MAX_LS_CHANNELS + MAX_NUM_OBJECTS]; - - 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[ch_idx] = st_ivas->p_output_f[ch_idx]; - } - - *nSamplesRendered = 0; - hTcBuffer = st_ivas->hTcBuffer; - n_samples_granularity = hTcBuffer->n_samples_granularity; - - /* get number of possible slots in new granularity */ - n_samples_still_available = hTcBuffer->n_samples_buffered - hTcBuffer->n_samples_rendered; - n_slots_still_available = n_samples_still_available / tc_granularity_new; - *nSamplesRendered = n_slots_still_available * tc_granularity_new; - n_samples_to_render = *nSamplesRendered; - 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 < max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) - { - /* move it at the beginning of the TC buffer with zero padding */ - mvr2r( hTcBuffer->tc_buffer_old[ch_idx], hTcBuffer->tc[ch_idx], n_samples_to_render ); - set_zero( hTcBuffer->tc[ch_idx] + n_samples_to_render, 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 = 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; - - - if ( st_ivas->ivas_format == ISM_FORMAT ) - { - if ( ism_mode_old == ISM_MODE_DISC ) - { - /* Binaural rendering */ - if ( renderer_type_old == RENDERER_BINAURAL_OBJECTS_TD ) - { - if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, n_samples_granularity ) ) != IVAS_ERR_OK ) - { - return error; - } - } - else if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - /* Convert to CICPxx; used also for ISM->CICP19->binaural_room rendering */ - set_f( st_ivas->hIsmRendererData->interpolator, 1.0f, n_samples_granularity ); - - ivas_ism_render_sf( st_ivas, renderer_type_old, p_output, n_samples_granularity ); - - if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, IVAS_AUDIO_CONFIG_7_1_4, IVAS_AUDIO_CONFIG_BINAURAL_ROOM_IR, st_ivas->hDecoderConfig, NULL, - NULL, NULL, hTcBuffer, p_output, p_output, 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 ( st_ivas->ivas_format == MC_FORMAT ) - { - if ( mc_mode_old == MC_MODE_MCT ) - { - int16_t crendInPlaceRotation = FALSE; - - if ( st_ivas->transport_config != intern_config_old && ( intern_config_old == IVAS_AUDIO_CONFIG_FOA || intern_config_old == IVAS_AUDIO_CONFIG_HOA2 || intern_config_old == IVAS_AUDIO_CONFIG_HOA3 ) ) - { - if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) < ( hIntSetupOld->nchan_out_woLFE + hIntSetupOld->num_lfe ) ) - { - crendInPlaceRotation = TRUE; - ivas_mc2sba( st_ivas->hTransSetup, hTcBuffer->tc, p_output, n_samples_granularity, hIntSetupOld->ambisonics_order, GAIN_LFE ); - } - } - if ( renderer_type_old == RENDERER_BINAURAL_MIXER_CONV || renderer_type_old == RENDERER_BINAURAL_MIXER_CONV_ROOM ) - { - if ( ( error = ivas_rend_crendProcessSubframe( st_ivas->hCrendWrapper, intern_config_old, st_ivas->hOutSetup.output_config, st_ivas->hDecoderConfig, st_ivas->hCombinedOrientationData, - hIntSetupOld, st_ivas->hEFAPdata, hTcBuffer, crendInPlaceRotation ? p_output : hTcBuffer->tc, p_output, n_samples_granularity, st_ivas->hDecoderConfig->output_Fs, 0 ) ) != IVAS_ERR_OK ) - { - return error; - } - - ivas_binaural_add_LFE( st_ivas, n_samples_granularity, hTcBuffer->tc, p_output ); - } - else if ( renderer_type_old == RENDERER_BINAURAL_OBJECTS_TD ) - { - if ( ( error = ivas_td_binaural_renderer_sf( st_ivas, p_output, n_samples_granularity ) ) != IVAS_ERR_OK ) - { - return error; - } - - ivas_binaural_add_LFE( st_ivas, n_samples_granularity, hTcBuffer->tc, p_output ); - } - 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 ( st_ivas->ivas_format == MASA_ISM_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) - { - if ( ism_mode_old == ISM_MASA_MODE_DISC ) - { - float *tc_local[MAX_NUM_OBJECTS]; - int16_t last_dirac_md_idx; - uint16_t nSamplesAvailableNext; - ISM_MODE ism_mode_orig; - RENDERER_TYPE renderer_type_orig; - int32_t ivas_total_brate; - - /* 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[ch_idx] = &hTcBuffer->tc[ch_idx + 2][hTcBuffer->n_samples_rendered]; - mvr2r( st_ivas->hMasaIsmData->delayBuffer[ch_idx], tc_local[ch_idx], st_ivas->hMasaIsmData->delayBuffer_size ); - } - - /* 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; - set_s( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); - - if ( ( error = ivas_omasa_dirac_td_binaural( st_ivas, (uint16_t) hTcBuffer->n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, CPE_CHANNELS, p_output ) ) != 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 ( st_ivas->ivas_format == SBA_ISM_FORMAT ) - { - if ( ism_mode_old == ISM_SBA_MODE_DISC ) - { - float *tc_local[MAX_TRANSPORT_CHANNELS]; - int16_t last_spar_md_idx; - int16_t last_dirac_md_idx; - uint16_t nSamplesAvailableNext; - ISM_MODE ism_mode_orig; - RENDERER_TYPE renderer_type_orig; - int32_t ivas_total_brate; - - /* 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_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]; -#ifdef DEBUGGING - assert( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ); -#endif - - /* 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[ch_idx] = &st_ivas->hTcBuffer->tc[ch_idx][hTcBuffer->n_samples_rendered]; - mvr2r( st_ivas->hSbaIsmData->delayBuffer[ch_idx], tc_local[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; - - /* also adapt md maps, just use the last index */ - set_s( st_ivas->hSpar->render_to_md_map, last_spar_md_idx, n_slots_still_available ); - set_s( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); - - /* render the last subframe */ - if ( ( error = ivas_osba_dirac_td_binaural( st_ivas, (uint16_t) n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, p_output ) ) != 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; - - /* Only write out the valid data*/ - if ( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) - { - if ( st_ivas->ivas_format != MONO_FORMAT ) - { -#ifndef DISABLE_LIMITER - ivas_limiter_dec( st_ivas->hLimiter, p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect ); -#endif - } - } - - switch ( pcm_resolution ) - { - case PCM_INT16: -#ifdef DEBUGGING - st_ivas->noClipping += -#endif - ivas_syn_output( p_output, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, (int16_t *) data ); - break; - case PCM_FLOAT32: - ivas_buffer_deinterleaved_to_interleaved( p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, (float *) data ); - break; - default: - error = IVAS_ERR_UNKNOWN; - break; - } - - 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( - Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ -) -{ - int16_t nMaxSlotsPerSubframe, nSlotsInFirstSubframe; - - /* render first frame with front zero padding and discarding those samples */ - nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; - nSlotsInFirstSubframe = nMaxSlotsPerSubframe - st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; - - if ( nSlotsInFirstSubframe > 0 ) - { - st_ivas->hTcBuffer->n_samples_discard = ( 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; - } - - 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( - const int16_t default_interp_length, /* i : default length of the (full-frame) interpolator */ - const int16_t interp_length, /* i : length of the interpolator to be created */ - float *interpolator /* o : the interpolator */ -) -{ - int16_t segment_len, idx; - float dec; -#ifdef DEBUGGING - assert( default_interp_length % 2 == 0 ); -#endif - - segment_len = ( default_interp_length >> 1 ); - dec = 1.0f / default_interp_length; - - interpolator[interp_length - 1] = 1.0f; - for ( idx = interp_length - 2; idx >= segment_len; idx-- ) - { - interpolator[idx] = max( 0.0f, interpolator[idx + 1] - dec ); - } - - if ( interpolator[idx + 1] > 0.0f ) - { - dec = interpolator[idx + 1] / ( segment_len + 1 ); - for ( ; idx >= 0; idx-- ) - { - interpolator[idx] = interpolator[idx + 1] - dec; - } - } - else - { - set_f( interpolator, 0.0f, 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( - const int16_t nCldfbTs, /* i : number of time slots in the current frame */ - int16_t *subframe_nbslots, /* i/o: subframe grid */ - int16_t *nb_subframes /* i/o: number of subframes in the frame */ -) -{ - uint16_t nSlotsInLastSubframe, nSlotsInFirstSubframe; - uint16_t nCldfbSlotsLocal = nCldfbTs; - - /* 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 = ( PARAM_MC_MAX_NSLOTS_IN_SUBFRAME - subframe_nbslots[*nb_subframes - 1] ); - *nb_subframes = 0; - if ( nSlotsInFirstSubframe > 0 ) - { - *nb_subframes = 1; - nCldfbSlotsLocal -= nSlotsInFirstSubframe; - } - - *nb_subframes += (int16_t) ceilf( (float) nCldfbSlotsLocal / (float) PARAM_MC_MAX_NSLOTS_IN_SUBFRAME ); - nSlotsInLastSubframe = nCldfbSlotsLocal % PARAM_MC_MAX_NSLOTS_IN_SUBFRAME; - - set_s( subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); - set_s( subframe_nbslots, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, *nb_subframes ); - - if ( nSlotsInFirstSubframe > 0 ) - { - subframe_nbslots[0] = nSlotsInFirstSubframe; - } - - if ( nSlotsInLastSubframe > 0 ) - { - subframe_nbslots[*nb_subframes - 1] = nSlotsInLastSubframe; - } - - return; -} - - -/*--------------------------------------------------------------------------* - * ivas_dec_get_md_map() - * - * Get an meta data map adapted to (time scale modified) IVAS frame - *--------------------------------------------------------------------------*/ - -void ivas_dec_get_md_map( - const int16_t default_len, /* i : default frame length in metadata slots */ - const int16_t len, /* i : length of the modified frames in metadata slots */ - const int16_t subframe_len, /* i : default length of a subframe */ - const int16_t offset, /* i : current read offset into the MD buffer */ - const int16_t buf_len, /* i : length of the metadata buffer */ - int16_t *map /* o : metadata index map */ -) -{ - int16_t jbm_segment_len, map_idx, src_idx, src_idx_map; - float dec, src_idx_f; - -#ifdef DEBUGGING - assert( default_len % 2 == 0 ); -#endif - jbm_segment_len = ( default_len >> 1 ); - dec = 1.0f / default_len; - - for ( map_idx = len - 1, src_idx = default_len - 1; map_idx >= jbm_segment_len; map_idx--, src_idx-- ) - { - src_idx_map = max( 0, src_idx / subframe_len ); - map[map_idx] = ( offset + src_idx_map ) % buf_len; - } - - /* 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 = ( (float) ( src_idx + 1 ) ) / ( (float) jbm_segment_len ); - src_idx_f = (float) ( src_idx + 1 ) - dec; - for ( ; map_idx >= 0; map_idx-- ) - { - src_idx = max( 0, ( (int16_t) round_f( src_idx_f ) ) / subframe_len ); - map[map_idx] = ( offset + src_idx ) % buf_len; - src_idx_f -= dec; - } - } - else - { - set_s( map, offset, 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( - const int16_t len, /* i : length of the modified frames in metadata slots */ - const int16_t subframe_len, /* i : default length of a subframe */ - const int16_t offset, /* i : current read offset into the MD buffer */ - const int16_t buf_len, /* i : length of the metadata buffer */ - int16_t *map /* o : metadata index map */ -) -{ - int16_t map_idx, sf_idx, sf_length, increment, subframes_written; - float decimal, decimal_sum, eps; - int16_t subframe_map_length[MAX_PARAM_SPATIAL_SUBFRAMES]; - - /* subframe map length */ - sf_length = 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; - } - } - else - { - /* uneven subframes */ - decimal = ( (float) len / (float) subframe_len ) - (float) sf_length; - decimal_sum = decimal; - eps = 0.001f; - for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) - { - increment = (int16_t) floorf( decimal_sum + eps ); - subframe_map_length[sf_idx] = sf_length + increment; - if ( increment > 0 ) + if ( ism_mode_old == ISM_MASA_MODE_DISC ) { - decimal_sum -= 1.0f; - } - decimal_sum += decimal; - } - } - - /* map slots to subframes */ - sf_idx = 0; - subframes_written = 0; - for ( map_idx = 0; map_idx < len; map_idx++ ) - { - map[map_idx] = ( offset + sf_idx ) % buf_len; - if ( map_idx - subframes_written >= subframe_map_length[sf_idx] - 1 ) - { - subframes_written += subframe_map_length[sf_idx]; - ++sf_idx; - } - } + float *tc_local[MAX_NUM_OBJECTS]; + int16_t last_dirac_md_idx; + uint16_t nSamplesAvailableNext; + ISM_MODE ism_mode_orig; + RENDERER_TYPE renderer_type_orig; + int32_t ivas_total_brate; - return; -} + /* 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[ch_idx] = &hTcBuffer->tc[ch_idx + 2][hTcBuffer->n_samples_rendered]; + mvr2r( st_ivas->hMasaIsmData->delayBuffer[ch_idx], tc_local[ch_idx], st_ivas->hMasaIsmData->delayBuffer_size ); + } + /* 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]; -/*--------------------------------------------------------------------------* - * ivas_dec_get_num_tc_channels() - * - * Get the number of channels provided to the renderer - *--------------------------------------------------------------------------*/ + /* 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; + set_s( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); -int16_t ivas_dec_get_num_tc_channels( - Decoder_Struct *st_ivas /* i : IVAS decoder handle */ -) -{ - int16_t num_tc; - int32_t ivas_total_brate; - AUDIO_CONFIG output_config; + if ( ( error = ivas_omasa_dirac_td_binaural( st_ivas, (uint16_t) hTcBuffer->n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, CPE_CHANNELS, p_output ) ) != IVAS_ERR_OK ) + { + return error; + } - if ( st_ivas->renderer_type == RENDERER_DISABLE ) - { - num_tc = st_ivas->hDecoderConfig->nchan_out; - } - else - { - num_tc = st_ivas->nchan_transport; - } + /* 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 ( st_ivas->ivas_format == SBA_ISM_FORMAT ) + { + if ( ism_mode_old == ISM_SBA_MODE_DISC ) + { + float *tc_local[MAX_TRANSPORT_CHANNELS]; + int16_t last_spar_md_idx; + int16_t last_dirac_md_idx; + uint16_t nSamplesAvailableNext; + ISM_MODE ism_mode_orig; + RENDERER_TYPE renderer_type_orig; + int32_t ivas_total_brate; - output_config = st_ivas->hDecoderConfig->output_config; + /* 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_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]; +#ifdef DEBUGGING + assert( st_ivas->renderer_type == RENDERER_BINAURAL_FASTCONV ); +#endif - ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + /* 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[ch_idx] = &st_ivas->hTcBuffer->tc[ch_idx][hTcBuffer->n_samples_rendered]; + mvr2r( st_ivas->hSbaIsmData->delayBuffer[ch_idx], tc_local[ch_idx], st_ivas->hSbaIsmData->delayBuffer_size ); + } - if ( st_ivas->ivas_format == MONO_FORMAT ) - { - num_tc = 1; - } - else if ( st_ivas->ivas_format == STEREO_FORMAT && st_ivas->hDecoderConfig->nchan_out == 1 ) - { - num_tc = 1; - } - else if ( st_ivas->ivas_format == ISM_FORMAT ) - { - if ( st_ivas->renderer_type == RENDERER_MONO_DOWNMIX ) - { - num_tc = 1; - } - } - else if ( st_ivas->ivas_format == SBA_FORMAT || st_ivas->ivas_format == MASA_FORMAT ) - { - if ( st_ivas->sba_dirac_stereo_flag ) - { - num_tc = CPE_CHANNELS; - } - else if ( st_ivas->ivas_format == MASA_FORMAT && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ( ivas_total_brate > IVAS_SID_5k2 || ( ivas_total_brate <= IVAS_SID_5k2 && st_ivas->nCPE > 0 && st_ivas->hCPE[0] != NULL && st_ivas->hCPE[0]->nchan_out == 1 ) ) ) - { - num_tc = 1; /* Only one channel transported */ - } + /* 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; - if ( st_ivas->ivas_format == MASA_FORMAT && output_config == IVAS_AUDIO_CONFIG_EXTERNAL && st_ivas->nchan_transport == 2 && ivas_total_brate < MASA_STEREO_MIN_BITRATE && ivas_total_brate > IVAS_SID_5k2 ) - { - num_tc = CPE_CHANNELS; - } + /* also adapt md maps, just use the last index */ + set_s( st_ivas->hSpar->render_to_md_map, last_spar_md_idx, n_slots_still_available ); + set_s( st_ivas->hSpatParamRendCom->render_to_md_map, last_dirac_md_idx, n_slots_still_available ); - if ( st_ivas->ivas_format == SBA_FORMAT ) - { - if ( num_tc == 3 ) - { - num_tc++; + /* render the last subframe */ + if ( ( error = ivas_osba_dirac_td_binaural( st_ivas, (uint16_t) n_samples_granularity, nSamplesRendered, &nSamplesAvailableNext, p_output ) ) != 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 ( st_ivas->ivas_format == MASA_ISM_FORMAT ) - { - if ( output_config != IVAS_AUDIO_CONFIG_EXTERNAL ) + else { - if ( st_ivas->ism_mode == ISM_MASA_MODE_MASA_ONE_OBJ || st_ivas->ism_mode == ISM_MASA_MODE_PARAM_ONE_OBJ ) - { - num_tc++; - } - else if ( st_ivas->ism_mode == ISM_MASA_MODE_DISC ) - { - num_tc += st_ivas->nchan_ism; - } + return IVAS_ERROR( IVAS_ERR_WRONG_MODE, "Wrong IVAS format in VoIP renderer flushing!" ); } + + hTcBuffer->n_samples_rendered = hTcBuffer->n_samples_granularity; } - else if ( st_ivas->ivas_format == SBA_ISM_FORMAT ) + + /* update global combined orientation start index */ + ivas_combined_orientation_update_start_index( st_ivas->hCombinedOrientationData, *nSamplesRendered ); + + *nSamplesRendered = n_samples_to_render; + + /* Only write out the valid data*/ + if ( is_split_rendering_enabled( st_ivas->hDecoderConfig, st_ivas->hRenderConfig ) == 0 ) { - if ( st_ivas->sba_dirac_stereo_flag ) - { - num_tc = CPE_CHANNELS; - } - if ( num_tc == 3 ) - { - num_tc++; - } - if ( st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + if ( st_ivas->ivas_format != MONO_FORMAT ) { - num_tc += st_ivas->nchan_ism; +#ifndef DISABLE_LIMITER + ivas_limiter_dec( st_ivas->hLimiter, p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, st_ivas->BER_detect ); +#endif } } - else if ( st_ivas->ivas_format == MC_FORMAT ) - { - if ( output_config == IVAS_AUDIO_CONFIG_MONO ) - { - num_tc = 1; - } - else if ( output_config == IVAS_AUDIO_CONFIG_STEREO ) - { - num_tc = 2; - } - else if ( st_ivas->mc_mode == MC_MODE_MCT ) - { - /* do all static dmx already in the TC decoder if less channels than transported... */ - if ( st_ivas->transport_config != st_ivas->intern_config && ( st_ivas->intern_config == IVAS_AUDIO_CONFIG_FOA || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA2 || st_ivas->intern_config == IVAS_AUDIO_CONFIG_HOA3 ) ) - { - if ( ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe ) ) - { - num_tc = st_ivas->hIntSetup.nchan_out_woLFE + st_ivas->hIntSetup.num_lfe; - } - } - else if ( ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) - { - num_tc = st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe; - } - } - else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX ) - { - num_tc = MC_PARAMUPMIX_MAX_TRANSPORT_CHANS; - } - else if ( st_ivas->mc_mode == MC_MODE_MCMASA ) - { - if ( st_ivas->hOutSetup.separateChannelEnabled ) - { - num_tc++; - } - if ( st_ivas->hOutSetup.separateChannelEnabled && ( output_config == IVAS_AUDIO_CONFIG_5_1 || output_config == IVAS_AUDIO_CONFIG_7_1 || - output_config == IVAS_AUDIO_CONFIG_5_1_4 || output_config == IVAS_AUDIO_CONFIG_7_1_4 || - output_config == IVAS_AUDIO_CONFIG_5_1_2 || ( output_config == IVAS_AUDIO_CONFIG_LS_CUSTOM && st_ivas->hOutSetup.num_lfe > 0 ) ) ) - { - /* LFE is synthesized in TD with the TCs */ - num_tc++; - } - } + switch ( pcm_resolution ) + { + case PCM_INT16: +#ifdef DEBUGGING + st_ivas->noClipping += +#endif + ivas_syn_output( p_output, *nSamplesRendered, st_ivas->hDecoderConfig->nchan_out, (int16_t *) data ); + break; + case PCM_FLOAT32: + ivas_buffer_deinterleaved_to_interleaved( p_output, st_ivas->hDecoderConfig->nchan_out, *nSamplesRendered, (float *) data ); + break; + default: + error = IVAS_ERR_UNKNOWN; + break; } - return num_tc; + 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 */ -int16_t ivas_dec_get_render_granularity( - const RENDERER_TYPE renderer_type, /* i : renderer type */ - const RENDERER_TYPE renderer_type_sec, /* i : secondary renderer type */ - const int32_t output_Fs /* i : sampling rate */ +ivas_error ivas_jbm_dec_set_discard_samples( + Decoder_Struct *st_ivas /* i/o: main IVAS decoder structre */ ) { - int16_t render_granularity; + int16_t nMaxSlotsPerSubframe, nSlotsInFirstSubframe; - if ( renderer_type == RENDERER_BINAURAL_OBJECTS_TD || /* TD renderer */ - renderer_type == RENDERER_BINAURAL_MIXER_CONV || renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM || /* Crend */ - renderer_type_sec == RENDERER_BINAURAL_OBJECTS_TD /* TD rend as a secondary renderer -> set the common granularity for both renderers */ - ) - { - /* 5 ms granularity */ - render_granularity = NS2SA( output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); - } - else + /* render first frame with front zero padding and discarding those samples */ + nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; + nSlotsInFirstSubframe = nMaxSlotsPerSubframe - st_ivas->hTcBuffer->subframe_nbslots[st_ivas->hTcBuffer->nb_subframes - 1]; + + if ( nSlotsInFirstSubframe > 0 ) { - /* 1.25 ms granularity */ - render_granularity = NS2SA( output_Fs, CLDFB_SLOT_NS ); + st_ivas->hTcBuffer->n_samples_discard = ( 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; } - 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( - DECODER_TC_BUFFER_HANDLE hTcBuffer, /* i/o: TC buffer handle */ - const int32_t output_Fs, /* i : output sampling rate */ - const int16_t Opt_tsm /* i : TSM option flag */ +void ivas_dec_get_adapted_linear_interpolator( + const int16_t default_interp_length, /* i : default length of the (full-frame) interpolator */ + const int16_t interp_length, /* i : length of the interpolator to be created */ + float *interpolator /* o : the interpolator */ ) { - int16_t nsamp_to_allocate; - int16_t ch_idx, n_samp_full, n_samp_residual, offset; - - if ( Opt_tsm ) - { - n_samp_full = ( NS2SA( output_Fs, MAX_JBM_L_FRAME_NS ) ); - n_samp_full = max( n_samp_full, L_FRAME48k ); /* buffers are shared between 'hTcBuffer->tc[]' and 'p_output_f[]': ensure minimal length */ - n_samp_residual = hTcBuffer->n_samples_granularity - 1; - } - else - { - n_samp_full = (int16_t) ( output_Fs / FRAMES_PER_SEC ); - n_samp_residual = 0; - } - - nsamp_to_allocate = max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ) * n_samp_full; + int16_t segment_len, idx; + float dec; +#ifdef DEBUGGING + assert( default_interp_length % 2 == 0 ); +#endif - if ( Opt_tsm ) - { - /* note: this is stack memory buffer for TC decoded and also time-scale modified audio signals */ - if ( ( hTcBuffer->tc_buffer = (float *) malloc( nsamp_to_allocate * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); - } - set_zero( hTcBuffer->tc_buffer, nsamp_to_allocate ); + segment_len = ( default_interp_length >> 1 ); + dec = 1.0f / default_interp_length; - offset = 0; - for ( ch_idx = 0; ch_idx < max( hTcBuffer->nchan_transport_rend, hTcBuffer->nchan_buffer_full ); ch_idx++ ) - { - hTcBuffer->tc[ch_idx] = &hTcBuffer->tc_buffer[offset]; - offset += n_samp_full; - } - for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc[ch_idx] = NULL; - } + interpolator[interp_length - 1] = 1.0f; + for ( idx = interp_length - 2; idx >= segment_len; idx-- ) + { + interpolator[idx] = max( 0.0f, interpolator[idx + 1] - dec ); + } - /* 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[ch_idx] = (float *) malloc( n_samp_residual * sizeof( float ) ) ) == NULL ) - { - return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TC Buffer\n" ) ); - } - set_zero( hTcBuffer->tc_buffer_old[ch_idx], n_samp_residual ); - } - for ( ; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) + if ( interpolator[idx + 1] > 0.0f ) + { + dec = interpolator[idx + 1] / ( segment_len + 1 ); + for ( ; idx >= 0; idx-- ) { - hTcBuffer->tc_buffer_old[ch_idx] = NULL; + interpolator[idx] = interpolator[idx + 1] - dec; } } else { - hTcBuffer->tc_buffer = NULL; - - for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc[ch_idx] = NULL; - } - - for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc_buffer_old[ch_idx] = NULL; - } + set_f( interpolator, 0.0f, idx + 1 ); } - hTcBuffer->tc_buffer2 = NULL; - - return IVAS_ERR_OK; + return; } /*--------------------------------------------------------------------------* - * ivas_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_dec_tc_audio_deallocate( - DECODER_TC_BUFFER_HANDLE hTcBuffer /* i/o: TC buffer handle */ +void ivas_dec_get_adapted_subframes( + const int16_t nCldfbTs, /* i : number of time slots in the current frame */ + int16_t *subframe_nbslots, /* i/o: subframe grid */ + int16_t *nb_subframes /* i/o: number of subframes in the frame */ ) { - int16_t ch_idx; + uint16_t nSlotsInLastSubframe, nSlotsInFirstSubframe; + uint16_t nCldfbSlotsLocal = nCldfbTs; - 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 = ( PARAM_MC_MAX_NSLOTS_IN_SUBFRAME - subframe_nbslots[*nb_subframes - 1] ); + *nb_subframes = 0; + if ( nSlotsInFirstSubframe > 0 ) { - if ( hTcBuffer->tc_buffer != NULL ) - { - for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - hTcBuffer->tc[ch_idx] = NULL; - } + *nb_subframes = 1; + nCldfbSlotsLocal -= nSlotsInFirstSubframe; + } - free( hTcBuffer->tc_buffer ); - hTcBuffer->tc_buffer = NULL; - } + *nb_subframes += (int16_t) ceilf( (float) nCldfbSlotsLocal / (float) PARAM_MC_MAX_NSLOTS_IN_SUBFRAME ); + nSlotsInLastSubframe = nCldfbSlotsLocal % PARAM_MC_MAX_NSLOTS_IN_SUBFRAME; - for ( ch_idx = 0; ch_idx < MAX_INTERN_CHANNELS; ch_idx++ ) - { - if ( hTcBuffer->tc_buffer_old[ch_idx] != NULL ) - { - free( hTcBuffer->tc_buffer_old[ch_idx] ); - hTcBuffer->tc_buffer_old[ch_idx] = NULL; - } - } + set_s( subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); + set_s( subframe_nbslots, PARAM_MC_MAX_NSLOTS_IN_SUBFRAME, *nb_subframes ); - if ( hTcBuffer->tc_buffer2 != NULL ) - { - free( hTcBuffer->tc_buffer2 ); - hTcBuffer->tc_buffer2 = NULL; - } + if ( nSlotsInFirstSubframe > 0 ) + { + subframe_nbslots[0] = nSlotsInFirstSubframe; + } + + if ( nSlotsInLastSubframe > 0 ) + { + subframe_nbslots[*nb_subframes - 1] = nSlotsInLastSubframe; } return; @@ -2204,158 +1107,151 @@ static void ivas_dec_tc_audio_deallocate( /*--------------------------------------------------------------------------* - * ivas_dec_tc_buffer_open() + * ivas_dec_get_md_map() * - * Open and initialize transport channel buffer handle + * Get an meta data map adapted to (time scale modified) IVAS frame *--------------------------------------------------------------------------*/ -ivas_error ivas_dec_tc_buffer_open( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const TC_BUFFER_MODE tc_buffer_mode, /* i : buffer mode */ - const int16_t nchan_transport_rend, /* i : number of TCs for rendering */ - const int16_t nchan_transport_internal, /* i : number of totally buffered channels */ - const int16_t nchan_full, /* i : number of channels to fully store */ - const int16_t n_samples_granularity /* i : granularity of the renderer/buffer */ +void ivas_dec_get_md_map( + const int16_t default_len, /* i : default frame length in metadata slots */ + const int16_t len, /* i : length of the modified frames in metadata slots */ + const int16_t subframe_len, /* i : default length of a subframe */ + const int16_t offset, /* i : current read offset into the MD buffer */ + const int16_t buf_len, /* i : length of the metadata buffer */ + int16_t *map /* o : metadata index map */ ) { - DECODER_TC_BUFFER_HANDLE hTcBuffer; - int16_t nMaxSlotsPerSubframe; - ivas_error error; + int16_t jbm_segment_len, map_idx, src_idx, src_idx_map; + float dec, src_idx_f; - /*-----------------------------------------------------------------* - * prepare library opening - *-----------------------------------------------------------------*/ +#ifdef DEBUGGING + assert( default_len % 2 == 0 ); +#endif + jbm_segment_len = ( default_len >> 1 ); + dec = 1.0f / default_len; - 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" ) ); + src_idx_map = max( 0, src_idx / subframe_len ); + map[map_idx] = ( offset + src_idx_map ) % buf_len; } - hTcBuffer->tc_buffer_mode = tc_buffer_mode; - hTcBuffer->nchan_transport_rend = nchan_transport_rend; - hTcBuffer->nchan_transport_internal = nchan_transport_internal; - hTcBuffer->nchan_buffer_full = nchan_full; - hTcBuffer->n_samples_granularity = n_samples_granularity; - hTcBuffer->n_samples_available = 0; - hTcBuffer->n_samples_buffered = 0; - hTcBuffer->n_samples_rendered = 0; - hTcBuffer->slots_rendered = 0; - hTcBuffer->subframes_rendered = 0; - hTcBuffer->n_samples_discard = 0; - hTcBuffer->n_samples_flushed = 0; - hTcBuffer->nb_subframes = MAX_PARAM_SPATIAL_SUBFRAMES; - - nMaxSlotsPerSubframe = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / hTcBuffer->n_samples_granularity; - hTcBuffer->num_slots = nMaxSlotsPerSubframe * MAX_PARAM_SPATIAL_SUBFRAMES; - set_s( hTcBuffer->subframe_nbslots, 0, MAX_JBM_SUBFRAMES_5MS ); - set_s( hTcBuffer->subframe_nbslots, nMaxSlotsPerSubframe, MAX_PARAM_SPATIAL_SUBFRAMES ); - - if ( ( error = ivas_dec_tc_audio_allocate( 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 = ( (float) ( src_idx + 1 ) ) / ( (float) jbm_segment_len ); + src_idx_f = (float) ( src_idx + 1 ) - dec; + for ( ; map_idx >= 0; map_idx-- ) + { + src_idx = max( 0, ( (int16_t) round_f( src_idx_f ) ) / subframe_len ); + map[map_idx] = ( offset + src_idx ) % buf_len; + src_idx_f -= dec; + } + } + else { - return error; + set_s( map, offset, 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( - Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ - const TC_BUFFER_MODE tc_buffer_mode, /* i : new buffer mode */ - const int16_t nchan_transport_rend, /* i : new number of TCs for rendering */ - const int16_t nchan_transport_internal, /* i : new number of totally buffered channels */ - const int16_t nchan_full, /* i : new number of channels to fully store */ - const int16_t n_samples_granularity /* i : new granularity of the renderer/buffer */ +void ivas_dec_get_md_map_even_spacing( + const int16_t len, /* i : length of the modified frames in metadata slots */ + const int16_t subframe_len, /* i : default length of a subframe */ + const int16_t offset, /* i : current read offset into the MD buffer */ + const int16_t buf_len, /* i : length of the metadata buffer */ + int16_t *map /* o : metadata index map */ ) { - int16_t ch_idx, num_tc_buffer_mem, n_samples_still_available; - float 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; - - num_tc_buffer_mem = 0; - n_samples_still_available = 0; + int16_t map_idx, sf_idx, sf_length, increment, subframes_written; + float decimal, decimal_sum, eps; + int16_t subframe_map_length[MAX_PARAM_SPATIAL_SUBFRAMES]; - if ( st_ivas->hDecoderConfig->Opt_tsm ) + /* subframe map length */ + sf_length = len / subframe_len; + if ( len % subframe_len == 0 ) { - /* save samples of the TC buffer from the previous frame */ - num_tc_buffer_mem = min( hTcBuffer->nchan_transport_internal, nchan_transport_internal ); - n_samples_still_available = 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++ ) { - mvr2r( hTcBuffer->tc_buffer_old[ch_idx] + hTcBuffer->n_samples_flushed, tc_buffer_mem[ch_idx], n_samples_still_available ); + subframe_map_length[sf_idx] = sf_length; } } - - /* if granularity changes, adapt subframe_nb_slots */ - if ( n_samples_granularity != hTcBuffer->n_samples_granularity ) + else { -#ifdef DEBUGGING - int16_t nMaxSlotsPerSubframeOld; -#endif - int16_t nMaxSlotsPerSubframeNew; - - nMaxSlotsPerSubframeNew = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / n_samples_granularity; -#ifdef DEBUGGING - nMaxSlotsPerSubframeOld = (int16_t) ( st_ivas->hDecoderConfig->output_Fs / ( FRAMES_PER_SEC * MAX_PARAM_SPATIAL_SUBFRAMES ) ) / st_ivas->hTcBuffer->n_samples_granularity; - assert( hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] == nMaxSlotsPerSubframeOld ); - if ( n_samples_granularity < hTcBuffer->n_samples_granularity ) - { - assert( ( hTcBuffer->n_samples_granularity % n_samples_granularity ) == 0 ); - } - else - { - assert( ( n_samples_granularity % hTcBuffer->n_samples_granularity ) == 0 ); - } -#endif - /* if samples were flushed, take that into account here */ - if ( n_samples_granularity < hTcBuffer->n_samples_granularity && hTcBuffer->n_samples_flushed > 0 ) + /* uneven subframes */ + decimal = ( (float) len / (float) subframe_len ) - (float) sf_length; + decimal_sum = decimal; + eps = 0.001f; + for ( sf_idx = 0; sf_idx < MAX_PARAM_SPATIAL_SUBFRAMES; sf_idx++ ) { - hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = hTcBuffer->n_samples_flushed / n_samples_granularity; - hTcBuffer->n_samples_flushed = 0; + increment = (int16_t) floorf( decimal_sum + eps ); + subframe_map_length[sf_idx] = sf_length + increment; + if ( increment > 0 ) + { + decimal_sum -= 1.0f; + } + decimal_sum += decimal; } - else + } + + /* map slots to subframes */ + sf_idx = 0; + subframes_written = 0; + for ( map_idx = 0; map_idx < len; map_idx++ ) + { + map[map_idx] = ( offset + sf_idx ) % buf_len; + if ( map_idx - subframes_written >= subframe_map_length[sf_idx] - 1 ) { - hTcBuffer->subframe_nbslots[hTcBuffer->subframes_rendered - 1] = nMaxSlotsPerSubframeNew; + subframes_written += subframe_map_length[sf_idx]; + ++sf_idx; } } - hTcBuffer->tc_buffer_mode = tc_buffer_mode; - hTcBuffer->nchan_transport_rend = nchan_transport_rend; - hTcBuffer->nchan_transport_internal = nchan_transport_internal; - hTcBuffer->nchan_buffer_full = nchan_full; - hTcBuffer->n_samples_granularity = n_samples_granularity; + return; +} + - /* reallocate TC audio buffers */ +/*--------------------------------------------------------------------------* + * ivas_dec_get_render_granularity() + * + * Get renderer granularity + *--------------------------------------------------------------------------*/ - ivas_dec_tc_audio_deallocate( hTcBuffer ); +/*! r: render granularity */ +int16_t ivas_dec_get_render_granularity( + const RENDERER_TYPE renderer_type, /* i : renderer type */ + const RENDERER_TYPE renderer_type_sec, /* i : secondary renderer type */ + const int32_t output_Fs /* i : sampling rate */ +) +{ + int16_t render_granularity; - if ( ( error = ivas_dec_tc_audio_allocate( hTcBuffer, st_ivas->hDecoderConfig->output_Fs, st_ivas->hDecoderConfig->Opt_tsm ) ) != IVAS_ERR_OK ) + if ( renderer_type == RENDERER_BINAURAL_OBJECTS_TD || /* TD renderer */ + renderer_type == RENDERER_BINAURAL_MIXER_CONV || renderer_type == RENDERER_BINAURAL_MIXER_CONV_ROOM || /* Crend */ + 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( output_Fs, FRAME_SIZE_NS / MAX_PARAM_SPATIAL_SUBFRAMES ); } - - /* propagate samples of the TC buffer from the previous frame */ - for ( ch_idx = 0; ch_idx < num_tc_buffer_mem; ch_idx++ ) + else { - mvr2r( tc_buffer_mem[ch_idx], hTcBuffer->tc_buffer_old[ch_idx], n_samples_still_available ); + /* 1.25 ms granularity */ + render_granularity = NS2SA( output_Fs, CLDFB_SLOT_NS ); } - return IVAS_ERR_OK; + return render_granularity; } @@ -2404,28 +1300,6 @@ static void ivas_dec_tc_buffer_playout( } -/*--------------------------------------------------------------------------* - * ivas_dec_tc_buffer_close() - * - * Close transport channel buffer handle - *--------------------------------------------------------------------------*/ - -void ivas_dec_tc_buffer_close( - DECODER_TC_BUFFER_HANDLE *phTcBuffer /* i/o: TC buffer handle */ -) -{ - if ( *phTcBuffer != NULL ) - { - ivas_dec_tc_audio_deallocate( *phTcBuffer ); - - free( *phTcBuffer ); - *phTcBuffer = NULL; - } - - return; -} - - /*--------------------------------------------------------------------------* * ivas_dec_td_renderers_adapt_subframes() * @@ -2476,94 +1350,6 @@ void ivas_dec_td_renderers_adapt_subframes( } -/*--------------------------------------------------------------------------* - * ivas_dec_get_tc_buffer_mode() - * - * - *--------------------------------------------------------------------------*/ - -TC_BUFFER_MODE ivas_dec_get_tc_buffer_mode( - Decoder_Struct *st_ivas /* i/o: IVAS decoder structure */ -) -{ - TC_BUFFER_MODE buffer_mode; - - buffer_mode = TC_BUFFER_MODE_BUFFER; - - 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; - 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; - break; - break; - case RENDERER_MC_PARAMMC: - if ( 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 */ - } - else - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - } - break; - case RENDERER_MC: - if ( ivas_dec_get_num_tc_channels( st_ivas ) != st_ivas->hDecoderConfig->nchan_out ) - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - } - break; - case RENDERER_SBA_LINEAR_ENC: - if ( st_ivas->ivas_format == MC_FORMAT && st_ivas->mc_mode == MC_MODE_MCT && ( st_ivas->renderer_type == RENDERER_MC || st_ivas->renderer_type == RENDERER_SBA_LINEAR_ENC ) && ( st_ivas->hTransSetup.nchan_out_woLFE + st_ivas->hTransSetup.num_lfe ) >= ( st_ivas->hOutSetup.nchan_out_woLFE + st_ivas->hOutSetup.num_lfe ) ) - { - buffer_mode = TC_BUFFER_MODE_BUFFER; - } - else - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - } - break; - case RENDERER_SBA_LINEAR_DEC: - if ( st_ivas->ivas_format == SBA_FORMAT && ( st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_MONO || st_ivas->hDecoderConfig->output_config == IVAS_AUDIO_CONFIG_STEREO ) ) - { - buffer_mode = TC_BUFFER_MODE_BUFFER; - } - else - { - buffer_mode = TC_BUFFER_MODE_RENDERER; - } - break; -#ifdef DEBUGGING - default: - assert( 0 ); -#endif - } - - return buffer_mode; -} - - /*--------------------------------------------------------------------------* * ivas_jbm_dec_masa_metadata_open() * -- GitLab From d4b6659a94bc2c7bae2f5970fc223533a6c2d595 Mon Sep 17 00:00:00 2001 From: vaclav Date: Wed, 28 Jan 2026 15:16:54 +0100 Subject: [PATCH 2/2] move functions - update MSVC project --- Workspace_msvc/lib_dec.vcxproj | 2 +- Workspace_msvc/lib_dec.vcxproj.filters | 9 +++------ 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 57b0ff748e..cc2f5b5b40 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -210,6 +210,7 @@ + @@ -219,7 +220,6 @@ - diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index 8eddbb60a0..9ca8447fb5 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -4,9 +4,6 @@ decoder_ivas_c - - decoder_ivas_c - decoder_ivas_c @@ -49,9 +46,6 @@ decoder_ivas_c - - decoder_ivas_c - decoder_ivas_c @@ -515,6 +509,9 @@ decoder_all_c + + decoder_ivas_c + -- GitLab