From cea2e1a79010b70fd3c629a631e53b7b0dd8bec7 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 24 Jan 2024 18:52:30 +0530 Subject: [PATCH] ivas sce, cpe modules converted to fixed point. [x] There is a Macro IVAS_FLOAT_FIXED_TO_BE_REMOVED defined in ivas_sce_dec_fx.c & ivas_cpe_dec_fx.c, it is for computation happening in floating point. This macro and code active under this is to be removed once the intermediate conversions to float are not required. --- Workspace_msvc/lib_dec.vcxproj | 2 + Workspace_msvc/lib_dec.vcxproj.filters | 8 +- lib_com/ivas_prot.h | 4 + lib_com/ivas_prot_fx.h | 43 +- lib_dec/ivas_corecoder_dec_reconfig.c | 3 + lib_dec/ivas_cpe_dec.c | 4 +- lib_dec/ivas_cpe_dec_fx.c | 1239 ++++++++++++++++++++++++ lib_dec/ivas_jbm_dec.c | 347 ++++++- lib_dec/ivas_mct_dec.c | 22 + lib_dec/ivas_sce_dec.c | 3 +- lib_dec/ivas_sce_dec_fx.c | 513 ++++++++++ lib_dec/ivas_stat_dec.h | 18 + lib_dec/stat_dec.h | 1 + 13 files changed, 2200 insertions(+), 7 deletions(-) create mode 100644 lib_dec/ivas_cpe_dec_fx.c create mode 100644 lib_dec/ivas_sce_dec_fx.c diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index f4730d4bd..d8676806d 100644 --- a/Workspace_msvc/lib_dec.vcxproj +++ b/Workspace_msvc/lib_dec.vcxproj @@ -279,6 +279,7 @@ + @@ -319,6 +320,7 @@ + diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters index 094beaa56..ea00c940e 100644 --- a/Workspace_msvc/lib_dec.vcxproj.filters +++ b/Workspace_msvc/lib_dec.vcxproj.filters @@ -818,6 +818,12 @@ decoder_all_c + + decoder_ivas_c + + + decoder_ivas_c + decoder_ivas_c @@ -877,4 +883,4 @@ {c33b80b3-67ce-466b-91c0-4adfc9efcb5c} - + \ No newline at end of file diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index e4bc8a0c5..def5e7935 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -321,6 +321,7 @@ ivas_error ivas_dec_setup( int16_t *data /* o : output synthesis signal */ ); +#ifndef IVAS_FLOAT_FIXED ivas_error create_sce_dec( Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ const int16_t cpe_id, /* i : SCE # identifier */ @@ -332,6 +333,7 @@ ivas_error create_cpe_dec( const int16_t cpe_id, /* i : CPE # identifier */ const int32_t element_brate /* i : element bitrate */ ); +#endif // !IVAS_FLOAT_FIXED ivas_error create_mct_dec( Decoder_Struct *st_ivas /* i/o: IVAS decoder handle */ @@ -342,6 +344,7 @@ ivas_error mct_dec_reconfigure( const uint16_t b_nchan_change /* i : flag indicating different channel count */ ); +#ifndef IVAS_FLOAT_FIXED void destroy_sce_dec( SCE_DEC_HANDLE hSCE /* i/o: SCE decoder structure */ ); @@ -349,6 +352,7 @@ void destroy_sce_dec( void destroy_cpe_dec( CPE_DEC_HANDLE hCPE /* i/o: CPE decoder structure */ ); +#endif // IVAS_FLOAT_FIXED void ivas_mct_dec_close( MCT_DEC_HANDLE *hMCT /* i/o: MCT decoder structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index c111f0d22..2f1e3f98b 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -490,6 +490,47 @@ void ivas_ism_metadata_sid_dec_fx( Word16 nb_bits_metadata[] /* o : number of metadata bits */ ); +#ifdef IVAS_FLOAT_FIXED +// ivas_sce_dec_fx.c +ivas_error create_sce_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 cpe_id, /* i : SCE # identifier */ + const Word32 element_brate /* i : element bitrate */ +); + +void destroy_sce_dec( + SCE_DEC_HANDLE hSCE /* i/o: SCE decoder structure */ +); + +ivas_error ivas_sce_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 sce_id, /* i : SCE # identifier */ + Word32 *output[1], /* o : output synthesis signal */ + const Word16 output_frame, /* i : output frame length per channel */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +); + +// ivas_cpe_dec_fx.c +ivas_error create_cpe_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 cpe_id, /* i : CPE # identifier */ + const Word32 element_brate /* i : element bitrate */ +); + +void destroy_cpe_dec( + CPE_DEC_HANDLE hCPE /* i/o: CPE decoder structure */ +); + +ivas_error ivas_cpe_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 cpe_id, /* i : CPE # identifier */ + Word32 *output[CPE_CHANNELS], /* o : output synthesis signal */ + const Word16 output_frame, /* i : output frame length per channel */ + const Word16 nb_bits_metadata, /* i : number of metadata bits */ + Word16 *q_output /* i/o : Q of output synthesis signal */ +); +#endif + //ivas_lfe_dec_fx.c void ivas_lfe_dec_close_fx( @@ -565,4 +606,4 @@ void ivas_mcmasa_split_brate_fx( Word32 *brate_cpe /* o : Pointer to CPE element bitrate */ ); -#endif \ No newline at end of file +#endif diff --git a/lib_dec/ivas_corecoder_dec_reconfig.c b/lib_dec/ivas_corecoder_dec_reconfig.c index 422bb5ef5..37cb165c4 100644 --- a/lib_dec/ivas_corecoder_dec_reconfig.c +++ b/lib_dec/ivas_corecoder_dec_reconfig.c @@ -33,6 +33,9 @@ #include "options.h" #include "ivas_cnst.h" #include "ivas_prot.h" +#ifdef IVAS_FLOAT_FIXED +#include "ivas_prot_fx.h" +#endif // IVAS_FLOAT_FIXED #include "prot.h" #include #include "wmc_auto.h" diff --git a/lib_dec/ivas_cpe_dec.c b/lib_dec/ivas_cpe_dec.c index 94b93e505..df3dcced8 100644 --- a/lib_dec/ivas_cpe_dec.c +++ b/lib_dec/ivas_cpe_dec.c @@ -558,7 +558,7 @@ ivas_error ivas_cpe_dec( return error; } - +#ifndef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * create_cpe_dec() * @@ -985,7 +985,7 @@ void destroy_cpe_dec( return; } - +#endif // IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * read_stereo_mode_and_bwidth() diff --git a/lib_dec/ivas_cpe_dec_fx.c b/lib_dec/ivas_cpe_dec_fx.c new file mode 100644 index 000000000..c9cfa8a39 --- /dev/null +++ b/lib_dec/ivas_cpe_dec_fx.c @@ -0,0 +1,1239 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include "options.h" +#ifdef IVAS_FLOAT_FIXED +#include "cnst.h" +#include "ivas_cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "ivas_prot.h" +#include "ivas_prot_fx.h" +#include "prot_fx2.h" +#include "ivas_rom_com.h" +#include "wmc_auto.h" +#include + +/* NOTE: Temporary macro for computation happening in floating point. This macro and code active under this is to be removed once the intermediate conversions to float are not required */ +#define IVAS_FLOAT_FIXED_TO_BE_REMOVED + +/*--------------------------------------------------------------------------* + * Local function prototypes + *--------------------------------------------------------------------------*/ + +static void read_stereo_mode_and_bwidth_fx( CPE_DEC_HANDLE hCPE, const Decoder_Struct *st_ivas ); + +static void stereo_mode_combined_format_dec_fx( const Decoder_Struct *st_ivas, CPE_DEC_HANDLE hCPE ); + + +/*--------------------------------------------------------------------------* + * ivas_cpe_dec_fx() + * + * Channel Pair Element (CPE) decoding routine + *--------------------------------------------------------------------------*/ + +ivas_error ivas_cpe_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 cpe_id, /* i : CPE # identifier */ + Word32 *output[CPE_CHANNELS], /* o : output synthesis signal */ + const Word16 output_frame, /* i : output frame length per channel */ + const Word16 nb_bits_metadata, /* i : number of metadata bits */ + Word16 *q_output /* i/o : Q of output synthesis signal */ +) +{ + Word16 i, n, n_channels; + Word16 nb_bits, last_core; + Word16 last_bwidth; + Word16 tdm_ratio_idx; +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + float *output_flt[CPE_CHANNELS]; + float outputHB[CPE_CHANNELS][L_FRAME48k]; /* 'float' buffer for output HB synthesis, both channels */ + float res_buf[STEREO_DFT_N_8k]; +#else + Word32 outputHB_fx[CPE_CHANNELS][L_FRAME48k]; /* buffer for output HB synthesis, both channels */ + Word32 res_buf_fx[STEREO_DFT_N_8k]; +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + CPE_DEC_HANDLE hCPE; + Decoder_State **sts; + Word32 ivas_total_brate; + ivas_error error; + Word32 cpe_brate; + Word32 element_brate_ref; + + error = IVAS_ERR_OK; + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + output_flt[0] = malloc( sizeof( float ) * L_FRAME48k ); + output_flt[1] = malloc( sizeof( float ) * L_FRAME48k ); + FOR( int k = 0; k < L_FRAME48k; k++ ) + { + output_flt[0][k] = (float) output[0][k] / ( 1 << *q_output ); + output_flt[1][k] = (float) output[1][k] / ( 1 << *q_output ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + push_wmops( "ivas_cpe_dec" ); + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + + hCPE = st_ivas->hCPE[cpe_id]; + sts = hCPE->hCoreCoder; + + last_core = sts[0]->last_core; + last_bwidth = sts[0]->last_bwidth; + + sts[0]->BER_detect = s_or( sts[0]->BER_detect, st_ivas->BER_detect ); + sts[1]->BER_detect = s_or( sts[1]->BER_detect, st_ivas->BER_detect ); + + element_brate_ref = hCPE->element_brate; + + /*------------------------------------------------------------------* + * Read stereo technology info & audio bandwidth + *-----------------------------------------------------------------*/ + + stereo_mode_combined_format_dec_fx( st_ivas, hCPE ); + + read_stereo_mode_and_bwidth_fx( hCPE, st_ivas ); + + /*----------------------------------------------------------------* + * dynamically allocate data structures depending on the actual stereo mode + *----------------------------------------------------------------*/ + + IF( ( error = stereo_memory_dec( ivas_total_brate, hCPE, nb_bits_metadata, st_ivas->hDecoderConfig->output_Fs, st_ivas->ivas_format, st_ivas->mc_mode, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + { + return error; + } + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + n_channels = CPE_CHANNELS; + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + n_channels = 1; /* in DFT stereo, only M channel is coded */ + } + + tdm_ratio_idx = LRTD_STEREO_RIGHT_IS_PRIM; + + FOR( n = 0; n < n_channels; n++ ) + { + sts[n]->idchan = n; + sts[n]->element_mode = hCPE->element_mode; + + IF( !st_ivas->bfi ) + { + sts[n]->tdm_LRTD_flag = 0; + } + + /* TD stereo parameters */ + IF( hCPE->hStereoTD != NULL ) + { + hCPE->hStereoTD->tdm_lp_reuse_flag = 0; + hCPE->hStereoTD->tdm_low_rate_mode = 0; + hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0; + } + } + + /*----------------------------------------------------------------* + * Resets/updates in case of stereo switching + *----------------------------------------------------------------*/ + + stereo_switching_dec( hCPE, ivas_total_brate ); + + /*----------------------------------------------------------------* + * Configuration of stereo decoder + *----------------------------------------------------------------*/ + + /* Force to MODE1 in IVAS */ + FOR( n = 0; n < n_channels; n++ ) + { + sts[n]->codec_mode = MODE1; + } + + IF( NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) && ( NE_32( hCPE->element_brate, hCPE->last_element_brate ) || NE_16( hCPE->last_element_mode, hCPE->element_mode ) || EQ_16( sts[0]->ini_frame, 0 ) || ( NE_32( ivas_total_brate, st_ivas->hDecoderConfig->last_ivas_total_brate ) ) ) ) + { + IF( st_ivas->hQMetaData != NULL && GT_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, (Word32) ( st_ivas->hQMetaData->bits_frame_nominal * 35 /* 0.7f * FRAMES_PER_SEC */ ), &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + ELSE + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, st_ivas->hQMetaData->bits_frame_nominal * FRAMES_PER_SEC, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + } + ELSE + { + /* Note: This only works for stereo operation. If DTX would be applied for multiple CPEs a different bitrate signaling is needed */ + IF( LE_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, ivas_total_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + ELSE + { + stereo_dft_config( hCPE->hStereoDft == NULL ? NULL : hCPE->hStereoDft->hConfig, hCPE->element_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + } + } + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + IF( hCPE->hStereoTD->tdm_LRTD_flag ) + { + sts[0]->bits_frame_nominal = (Word16) ( L_shr( hCPE->element_brate, 1 ) / FRAMES_PER_SEC ); + sts[1]->bits_frame_nominal = (Word16) ( L_shr( hCPE->element_brate, 1 ) / FRAMES_PER_SEC ); + } + ELSE + { + stereo_dft_config( NULL, hCPE->element_brate, &sts[0]->bits_frame_nominal, &sts[1]->bits_frame_nominal ); + } + } + + /*----------------------------------------------------------------* + * Set bitrates per channel + * Set bitstream buffers per channel + *----------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + IF( !st_ivas->bfi ) + { + /* Update DFT Stereo memories */ + stereo_dft_dec_update( hCPE->hStereoDft, output_frame, 0 ); + + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) && LE_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + IF( EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) + { + hCPE->hCoreCoder[n]->core_brate = ivas_total_brate; + hCPE->hCoreCoder[0]->total_brate = ivas_total_brate; + } + ELSE + { + hCPE->hCoreCoder[n]->core_brate = SID_2k40; + } + } + + /* read DFT Stereo side info */ + nb_bits = extract_l( L_sub( ( hCPE->element_brate / FRAMES_PER_SEC ), Mpy_32_16_1( 26214, sts[0]->bits_frame_nominal ) ) ); // 0.8f in q15 = 26214 + cpe_brate = st_ivas->hCPE[0]->element_brate; + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + sts[1]->bit_stream = sts[0]->bit_stream + sub( sub( (Word16) ( cpe_brate / FRAMES_PER_SEC ), 1 ), nb_bits_metadata ); + sts[1]->bit_stream = sts[1]->bit_stream + (Word16) ( hCPE->brate_surplus / FRAMES_PER_SEC ); + } + ELSE + { + sts[1]->bit_stream = sts[0]->bit_stream + sub( sub( (Word16) ( ivas_total_brate / FRAMES_PER_SEC ), 1 ), nb_bits_metadata ); + } + + IF( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + nb_bits = sub( nb_bits, SID_FORMAT_NBITS ); + sts[1]->bit_stream = sts[1]->bit_stream - SID_FORMAT_NBITS; + /* set total bitrate of Stereo CNG parameters for BER detection */ + sts[1]->total_brate = L_sub( IVAS_SID_5k2, SID_2k40 ); + } + + IF( ( ( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) && LT_32( ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) || ( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) && LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) ) ) && GT_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + sts[0]->total_brate = hCPE->element_brate; /* Only mono downmix was transmitted in this case */ + } + ELSE + { + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + nb_bits = sub( nb_bits, nb_bits_metadata ); + IF( LT_32( hCPE->brate_surplus, 0 ) ) + { + nb_bits = add( nb_bits, (Word16) ( hCPE->brate_surplus / FRAMES_PER_SEC ) ); + } + } + + stereo_dft_dec_read_BS( ivas_total_brate, hCPE->element_brate, &sts[0]->total_brate, sts[1], hCPE->hStereoDft, sts[0]->bwidth, output_frame, res_buf, &nb_bits, hCPE->hStereoCng->coh, st_ivas->ivas_format ); + } + + /* subtract metadata bitbudget */ + sts[0]->total_brate = L_sub( sts[0]->total_brate, nb_bits_metadata * FRAMES_PER_SEC ); + + /* subtract bit-rate for combined format coding */ + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) ) + { + sts[0]->total_brate = L_add( sts[0]->total_brate, hCPE->brate_surplus ); + } + } + ELSE + { + hCPE->hStereoDft->sg_mem_corrupt = 1; + } + } + ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + /* signal bitrate for BW selection in the SCh */ + sts[0]->bits_frame_channel = 0; + sts[1]->bits_frame_channel = (Word16) ( hCPE->element_brate / FRAMES_PER_SEC ); + sts[1]->bits_frame_channel = add( sts[1]->bits_frame_channel, (Word16) ( hCPE->brate_surplus / FRAMES_PER_SEC ) ); + IF( st_ivas->hQMetaData != NULL ) + { + sts[1]->bits_frame_channel = sub( sts[1]->bits_frame_channel, st_ivas->hQMetaData->metadata_max_bits ); + } + } + ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) + { + /* compute bit-rate surplus per channel in combined format coding */ + Word32 brate_surplus[CPE_CHANNELS]; + IF( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + brate_surplus[0] = (Word16) L_shr( L_mult( (Word16) L_shr( ( hCPE->brate_surplus / FRAMES_PER_SEC ), 1 ), FRAMES_PER_SEC ), 1 ); + brate_surplus[1] = L_sub( hCPE->brate_surplus, brate_surplus[0] ); + } + + IF( EQ_16( is_DTXrate( ivas_total_brate ), 1 ) && ( EQ_16( sts[0]->first_CNG, 0 ) || EQ_16( sts[1]->first_CNG, 0 ) ) ) + { + IF( ( error = initMdctStereoDtxData( hCPE ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /* this is just for initialization, the true values of "total_brate" and "bits_frame_channel" are set later */ + FOR( n = 0; n < n_channels; n++ ) + { + IF( EQ_32( ivas_total_brate, IVAS_SID_5k2 ) ) + + { + sts[n]->total_brate = SID_2k40; + sts[1]->bit_stream = sts[0]->bit_stream + SID_2k40 / FRAMES_PER_SEC; + } + ELSE + { + /*total bitrate must be set to the element bitrate to avoid false BER IF bits read are larger than half the bitrate*/ + sts[n]->total_brate = hCPE->element_brate; + } + sts[n]->bits_frame_nominal = (Word16) ( sts[n]->total_brate / FRAMES_PER_SEC ); + sts[n]->bits_frame_channel = extract_l( L_shr( ( hCPE->element_brate / FRAMES_PER_SEC ), sub( n_channels, 1 ) ) ); + + /* subtract bit-rate for combined format coding */ + IF( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) + { + sts[n]->bits_frame_channel = add( sts[n]->bits_frame_channel, (Word16) ( brate_surplus[n] / FRAMES_PER_SEC ) ); + sts[n]->total_brate = L_add( sts[n]->total_brate, brate_surplus[n] ); + } + } + + IF( !st_ivas->hMCT ) + { + IF( EQ_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) && EQ_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + FOR( n = 0; n < n_channels; n++ ) + { + sts[n]->bits_frame_channel = sub( sts[n]->bits_frame_channel, shr( nb_bits_metadata, sub( n_channels, 1 ) ) ); + } + } + ELSE + { + /* subtract metadata bitbudget */ + sts[0]->bits_frame_channel = sub( sts[0]->bits_frame_channel, nb_bits_metadata ); + } + } + } + + /*----------------------------------------------------------------* + * Core codec configuration + *----------------------------------------------------------------*/ + + FOR( n = 0; n < n_channels; n++ ) + { + /* set ACELP12k8 / ACELP16k flag for flexible ACELP core */ + sts[n]->flag_ACELP16k = set_ACELP_flag_IVAS( hCPE->element_mode, hCPE->element_brate, sts[n]->total_brate, n, ( hCPE->hStereoTD != NULL ? hCPE->hStereoTD->tdm_LRTD_flag : 0 ), sts[n]->bwidth, sts[n]->cng_type ); + } + + FOR( n = 0; n < n_channels; n++ ) + { + /* set VAD flag */ + IF( EQ_16( is_DTXrate( ivas_total_brate ), 1 ) ) + { + sts[n]->VAD = 0; + sts[n]->active_cnt = 0; + IF( sts[1] != NULL ) + { + sts[1]->active_cnt = 0; + } + } + ELSE + { + sts[n]->VAD = 1; + sts[n]->active_cnt++; + sts[n]->active_cnt = s_min( sts[n]->active_cnt, 100 ); + } + + /* set CNA flag */ + IF( ( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && LE_32( hCPE->element_brate, CNA_MAX_BRATE_DFT_STEREO ) ) || LE_32( hCPE->element_brate, CNA_MAX_BRATE_STEREO ) ) + { + sts[n]->flag_cna = 1; + } + ELSE + { + sts[n]->flag_cna = 0; + } + } + + /* configure TD stereo decoder */ + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + IF( !st_ivas->bfi ) + { + tdm_configure_dec( st_ivas->ivas_format, st_ivas->ism_mode, hCPE, &tdm_ratio_idx, nb_bits_metadata ); + + sts[1]->bit_stream = sts[0]->bit_stream + (Word16) ( sts[0]->total_brate / FRAMES_PER_SEC ); + } + ELSE + { + sts[1]->coder_type = sts[1]->last_coder_type; + tdm_ratio_idx = hCPE->hStereoTD->tdm_last_ratio_idx; + } + } + + /*----------------------------------------------------------------* + * Core Decoder + *----------------------------------------------------------------*/ + + IF( NE_16( hCPE->element_mode, IVAS_CPE_DFT ) || ( EQ_16( hCPE->nchan_out, 1 ) && EQ_16( hCPE->hStereoDft->hConfig->res_cod_mode, STEREO_DFT_RES_COD_OFF ) ) ) + { + IF( ( error = ivas_core_dec( st_ivas, NULL, hCPE, st_ivas->hMCT, n_channels, output_flt, outputHB, NULL, st_ivas->sba_dirac_stereo_flag ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + IF( st_ivas->hMCT ) + { + pop_wmops(); + + return error; + } + + /*----------------------------------------------------------------* + * Stereo decoder & upmixing + *----------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && !( EQ_16( hCPE->nchan_out, 1 ) && EQ_16( hCPE->hStereoDft->hConfig->res_cod_mode, STEREO_DFT_RES_COD_OFF ) ) ) + { + float DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX]; + set_f( DFT[0], 0.0f, STEREO_DFT_BUF_MAX ); + set_f( DFT[1], 0.0f, STEREO_DFT_BUF_MAX ); + + + /* core decoder */ + IF( ( error = ivas_core_dec( NULL, NULL, hCPE, st_ivas->hMCT, n_channels, output_flt, outputHB, DFT, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + /* DFT Stereo residual decoding */ + IF( GT_16( hCPE->hStereoDft->res_cod_band_max, 0 ) && !st_ivas->bfi ) + { + stereo_dft_dec_res( hCPE, res_buf, output_flt[1] ); + + stereo_dft_dec_analyze( hCPE, output_flt[1], DFT, 1, L_FRAME8k, output_frame, DFT_STEREO_DEC_ANA_LB, 0, 0 ); + } + + /* DFT stereo CNG */ + stereo_dtf_cng( hCPE, ivas_total_brate, DFT, output_frame ); + + /* decoding */ + IF( EQ_16( hCPE->nchan_out, 1 ) ) + { + stereo_dft_unify_dmx( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng->prev_sid_nodata ); + } + ELSE + { + stereo_dft_dec( hCPE->hStereoDft, sts[0], DFT, hCPE->input_mem[1], hCPE->hStereoCng, 0, 0, 0, 0, 0, 0, MAX_PARAM_SPATIAL_SUBFRAMES ); + } + + /* synthesis iFFT */ + FOR( n = 0; n < hCPE->nchan_out; n++ ) + { + stereo_dft_dec_synthesize( hCPE, DFT, n, output_flt[n], output_frame ); + } + } + ELSE IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + IF( NE_16( hCPE->last_element_mode, IVAS_CPE_TD ) && sts[0]->tdm_LRTD_flag ) + { + hCPE->hStereoTD->tdm_last_ratio_idx = tdm_ratio_idx; + } + + /* TD stereo upmixing */ + stereo_tdm_combine( hCPE, output_flt[0], output_flt[1], output_frame, 0, tdm_ratio_idx ); + IF( sts[0]->tdm_LRTD_flag ) + { + stereo_tdm_combine( hCPE, outputHB[0], outputHB[1], output_frame, 1, tdm_ratio_idx ); + } + + hCPE->hStereoCng->last_tdm_idx = hCPE->hStereoTD->tdm_last_ratio_idx; + hCPE->hStereoTD->tdm_last_ratio_idx = tdm_ratio_idx; + + IF( EQ_16( hCPE->nchan_out, 1 ) ) + { + /* Scale the Right channel with the gain */ + stereo_tca_scale_R_channel( hCPE, output_flt[1], output_frame ); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + FOR( int k = 0; k < output_frame; k++ ) + { + output[0][k] = (Word32) ( output_flt[0][k] * ( 1 << *q_output ) ); + output[1][k] = (Word32) ( output_flt[1][k] * ( 1 << *q_output ) ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + /* stereo to mono downmix */ + FOR( i = 0; i < output_frame; i++ ) + { + output[0][i] = L_shr( L_add( output[0][i], output[1][i] ), 1 ); + } + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + FOR( int k = 0; k < output_frame; k++ ) + { + output_flt[0][k] = ( (float) output[0][k] / ( 1 << *q_output ) ); + output_flt[1][k] = ( (float) output[1][k] / ( 1 << *q_output ) ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + } + } + + /*----------------------------------------------------------------* + * Update parameters for stereo CNA + *----------------------------------------------------------------*/ + + stereo_cna_update_params( hCPE, output_flt, output_frame, tdm_ratio_idx ); + + /*----------------------------------------------------------------* + * Synthesis synchronization between CPE modes + *----------------------------------------------------------------*/ + + IF( !st_ivas->sba_dirac_stereo_flag ) + { + synchro_synthesis( ivas_total_brate, hCPE, output_flt, output_frame, 0 ); + } + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && EQ_16( hCPE->nchan_out, 1 ) && ( EQ_16( is_DTXrate( ivas_total_brate ), 0 ) || ( EQ_16( is_DTXrate( ivas_total_brate ), 1 ) && EQ_16( is_DTXrate( st_ivas->hDecoderConfig->last_ivas_total_brate ), 0 ) ) ) ) + { + applyDmxMdctStereo( hCPE, output_flt, output_frame ); + } + + /*----------------------------------------------------------------* + * IC-BWE: output LB and HB mix in ACELP mode + *----------------------------------------------------------------*/ + + stereo_icBWE_decproc( hCPE, output_flt, outputHB, last_core, last_bwidth, output_frame ); + + smooth_dft2td_transition( hCPE, output_flt, output_frame ); + + /*----------------------------------------------------------------* + * Temporal ICA, stereo adjustment and upmix + *----------------------------------------------------------------*/ + + stereo_tca_dec( hCPE, output_flt, output_frame ); + + /*----------------------------------------------------------------* + * Common Stereo updates + *----------------------------------------------------------------*/ + + hCPE->last_element_brate = hCPE->element_brate; + hCPE->last_element_mode = hCPE->element_mode; + + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + hCPE->element_brate = element_brate_ref; + } + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) || EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + stereo_cng_dec_update( hCPE, ivas_total_brate ); + } + + st_ivas->BER_detect = s_or( st_ivas->BER_detect, sts[0]->BER_detect ); + st_ivas->BER_detect = s_or( st_ivas->BER_detect, sts[1]->BER_detect ); + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + FOR( int k = 0; k < L_FRAME48k; k++ ) + { + output[0][k] = (Word32) ( output_flt[0][k] * ( 1 << *q_output ) ); + output[1][k] = (Word32) ( output_flt[1][k] * ( 1 << *q_output ) ); + } + free( output_flt[0] ); + free( output_flt[1] ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + pop_wmops(); + return error; +} + + +/*------------------------------------------------------------------------- + * create_cpe_dec_fx() + * + * Create, allocate and initialize IVAS decoder CPE handle + *-------------------------------------------------------------------------*/ + +ivas_error create_cpe_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 cpe_id, /* i : CPE # identifier */ + const Word32 element_brate /* i : element bitrate */ +) +{ + Word16 i, n; + CPE_DEC_HANDLE hCPE; + Decoder_State *st; + Word32 output_Fs; + ivas_error error; + Word32 cpe_brate; + + error = IVAS_ERR_OK; + + /*-----------------------------------------------------------------* + * Allocate CPE handle + *-----------------------------------------------------------------*/ + + IF( ( hCPE = (CPE_DEC_HANDLE) malloc( sizeof( CPE_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CPE\n" ) ); + } + + /*-----------------------------------------------------------------* + * Initialization - general parameters + *-----------------------------------------------------------------*/ + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + + hCPE->cpe_id = cpe_id; + + hCPE->element_brate = element_brate; + hCPE->last_element_brate = hCPE->element_brate; + hCPE->element_mode = st_ivas->element_mode_init; + hCPE->last_element_mode = st_ivas->element_mode_init; + + hCPE->hStereoDft = NULL; + hCPE->hStereoDftDmx = NULL; + hCPE->hStereoTD = NULL; + hCPE->hStereoMdct = NULL; + hCPE->hStereoTCA = NULL; + hCPE->hStereoICBWE = NULL; + hCPE->hStereoCng = NULL; + + hCPE->stereo_switching_counter = 10; + hCPE->NbFrameMod = 7; + hCPE->lt_es_em = 0.0f; + hCPE->lt_es_em_fx = 0; + + /* Note: nchan_out is considered to be related to the structure. This is nchan_out for CPE and for MASA_format is always 2. */ + IF( EQ_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MC_FORMAT ) ) + { + hCPE->nchan_out = CPE_CHANNELS; + } + ELSE + { + hCPE->nchan_out = s_min( CPE_CHANNELS, st_ivas->hDecoderConfig->nchan_out ); + } + + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) && ( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) ) ) + { + cpe_brate = element_brate; + } + ELSE + { + cpe_brate = st_ivas->hDecoderConfig->ivas_total_brate; + } + + IF( ( ( EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) && LT_32( st_ivas->hDecoderConfig->ivas_total_brate, MASA_STEREO_MIN_BITRATE ) ) || + ( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) && LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) ) ) && + GT_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_SID_5k2 ) ) + { + hCPE->nchan_out = 1; + } + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + for ( n = 0; n < CPE_CHANNELS; n++ ) + { + set_f( hCPE->prev_hb_synth[n], 0, NS2SA( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ) ); + set_f( hCPE->prev_synth[n], 0, NS2SA( output_Fs, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ) ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + set32_fx( hCPE->prev_hb_synth_fx[n], 0, NS2SA_fx2( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ) ); + set32_fx( hCPE->prev_synth_fx[n], 0, NS2SA_fx2( output_Fs, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS ) ); + } + + hCPE->brate_surplus = 0; + + /*-----------------------------------------------------------------* + * DFT stereo I/O Buffers: allocate and initialize + *-----------------------------------------------------------------*/ + + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + IF( EQ_16( (Word16) st_ivas->ivas_format, STEREO_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) || + ( EQ_16( (Word16) st_ivas->ivas_format, MC_FORMAT ) && EQ_16( (Word16) st_ivas->mc_mode, MC_MODE_MCMASA ) ) || st_ivas->sba_dirac_stereo_flag ) + { +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + IF( ( hCPE->input_mem[i] = (float *) malloc( sizeof( float ) * NS2SA_fx2( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set_zero( hCPE->input_mem[i], NS2SA_fx2( output_Fs, STEREO_DFT32MS_OVL_NS ) ); + + IF( ( hCPE->input_mem_LB[i] = (float *) malloc( sizeof( float ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set_zero( hCPE->input_mem_LB[i], STEREO_DFT32MS_OVL_16k ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + IF( ( hCPE->input_mem_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * NS2SA_fx2( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set32_fx( hCPE->input_mem_fx[i], 0, NS2SA_fx2( output_Fs, STEREO_DFT32MS_OVL_NS ) ); + + IF( ( hCPE->input_mem_LB_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set32_fx( hCPE->input_mem_LB_fx[i], 0, STEREO_DFT32MS_OVL_16k ); + + IF( EQ_16( i, 0 ) ) + { +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + IF( ( hCPE->input_mem_BPF[0] = (float *) malloc( sizeof( float ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set_zero( hCPE->input_mem_BPF[0], STEREO_DFT32MS_OVL_16k ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + IF( ( hCPE->input_mem_BPF_fx[0] = (Word32 *) malloc( sizeof( Word32 ) * STEREO_DFT32MS_OVL_16k ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set32_fx( hCPE->input_mem_BPF_fx[0], 0, STEREO_DFT32MS_OVL_16k ); + } + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + IF( ( hCPE->output_mem[i] = (float *) malloc( sizeof( float ) * NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set_zero( hCPE->output_mem[i], NS2SA( output_Fs, STEREO_DFT32MS_OVL_NS ) ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + IF( ( hCPE->output_mem_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * NS2SA_fx2( output_Fs, STEREO_DFT32MS_OVL_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set32_fx( hCPE->output_mem_fx[i], 0, NS2SA_fx2( output_Fs, STEREO_DFT32MS_OVL_NS ) ); + + IF( LT_16( i, hCPE->nchan_out ) ) + { + IF( ( hCPE->prev_synth_chs_fx[i] = (Word32 *) malloc( sizeof( Word32 ) * NS2SA_fx2( output_Fs, FRAME_SIZE_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set32_fx( hCPE->prev_synth_chs_fx[i], 0, NS2SA_fx2( output_Fs, FRAME_SIZE_NS ) ); + } + ELSE + { + hCPE->prev_synth_chs_fx[i] = NULL; + } + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + if ( i < hCPE->nchan_out ) + { + if ( ( hCPE->prev_synth_chs[i] = (float *) malloc( sizeof( float ) * NS2SA( output_Fs, FRAME_SIZE_NS ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DFT stereo memory\n" ) ); + } + set_zero( hCPE->prev_synth_chs[i], NS2SA( output_Fs, FRAME_SIZE_NS ) ); + } + else + { + hCPE->prev_synth_chs[i] = NULL; + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + } + ELSE + { + hCPE->input_mem_fx[i] = NULL; + hCPE->input_mem_LB_fx[i] = NULL; + IF( EQ_16( i, 0 ) ) + { + hCPE->input_mem_BPF_fx[0] = NULL; + } + hCPE->output_mem_fx[i] = NULL; + hCPE->prev_synth_chs_fx[i] = NULL; +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + hCPE->input_mem[i] = NULL; + hCPE->input_mem_LB[i] = NULL; + if ( i == 0 ) + { + hCPE->input_mem_BPF[0] = NULL; + } + hCPE->output_mem[i] = NULL; + hCPE->prev_synth_chs[i] = NULL; +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + } + } + + /*-----------------------------------------------------------------* + * CoreCoder, 2 instances: allocate and initialize + *-----------------------------------------------------------------*/ + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + IF( st_ivas->sba_dirac_stereo_flag && EQ_16( st_ivas->nchan_transport, 1 ) ) + { + /* for SBA DirAC stereo output CPE element is only used for upmix, core coder is found in SCE element used for core decoding */ + BREAK; + } + + IF( ( st = (DEC_CORE_HANDLE) malloc( sizeof( Decoder_State ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); + } + + copy_decoder_config( st_ivas, st ); + + // st->total_brate = hCPE->element_brate / ( CPE_CHANNELS ); + st->total_brate = L_shr( hCPE->element_brate, 1 ); /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + st->is_ism_format = 0; + + IF( ( error = init_decoder( st, n, st_ivas->mc_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + + hCPE->hCoreCoder[n] = st; + } + + /*-----------------------------------------------------------------* + * DFT stereo initialization + *-----------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) || ( st_ivas->sba_dirac_stereo_flag && EQ_16( hCPE->cpe_id, 0 ) ) ) + { + IF( ( error = stereo_dft_dec_create( &( hCPE->hStereoDft ), hCPE->element_brate, output_Fs, st_ivas->sba_dirac_stereo_flag, st_ivas->nchan_transport ) ) != IVAS_ERR_OK ) + { + return error; + } + } + + /*-----------------------------------------------------------------* + * DFT stereo mono DMX initialization + *-----------------------------------------------------------------*/ + + IF( NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) && EQ_16( hCPE->nchan_out, 1 ) ) + { + IF( ( hCPE->hStereoDftDmx = (STEREO_DFT_DMX_DATA_HANDLE) malloc( sizeof( STEREO_DFT_DMX_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo DFT mono output\n" ) ); + } + + stereo_dft_dmx_out_reset( hCPE->hStereoDftDmx ); + } + + /*-----------------------------------------------------------------* + * Temporal inter-channel alignment initialization + *-----------------------------------------------------------------*/ + + IF( ( NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) || ( EQ_16( (Word16) st_ivas->ivas_format, STEREO_FORMAT ) && LE_32( hCPE->element_brate, MAX_MDCT_ITD_BRATE ) ) ) && NE_16( hCPE->nchan_out, 1 ) ) + { + IF( ( hCPE->hStereoTCA = (STEREO_TCA_DEC_HANDLE) malloc( sizeof( STEREO_TCA_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo TCA\n" ) ); + } + + stereo_tca_init_dec( hCPE->hStereoTCA ); + } + + /*-----------------------------------------------------------------* + * Stereo IC BWE initialization + *-----------------------------------------------------------------*/ + + IF( NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) && !( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) && EQ_16( hCPE->nchan_out, 1 ) ) ) + { + IF( ( hCPE->hStereoICBWE = (STEREO_ICBWE_DEC_HANDLE) malloc( sizeof( STEREO_ICBWE_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo ICBWE\n" ) ); + } + + stereo_icBWE_init_dec( hCPE->hStereoICBWE ); + } + + /*-----------------------------------------------------------------* + * TD stereo initialization + *-----------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + IF( ( hCPE->hStereoTD = (STEREO_TD_DEC_DATA_HANDLE) malloc( sizeof( STEREO_TD_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for TD Stereo\n" ) ); + } + + stereo_td_init_dec( hCPE->hStereoTD, hCPE->last_element_mode ); + } + + /*-----------------------------------------------------------------* + * MDCT stereo initialization + *-----------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) && EQ_16( st_ivas->nCPE, 1 ) ) + { + IF( ( hCPE->hStereoMdct = (STEREO_MDCT_DEC_DATA_HANDLE) malloc( sizeof( STEREO_MDCT_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo MDCT\n" ) ); + } + + IF( EQ_16( (Word16) st_ivas->ivas_format, STEREO_FORMAT ) && LE_32( hCPE->element_brate, MAX_MDCT_ITD_BRATE ) ) + { + hCPE->hStereoMdct->use_itd = 1; + } + ELSE + { + hCPE->hStereoMdct->use_itd = 0; + } + + hCPE->hStereoMdct->reverse_dmx = 0; + hCPE->hStereoMdct->smooth_ratio = 1.f; + set_s( hCPE->hStereoMdct->prev_ms_mask[0], 0, MAX_SFB ); + set_s( hCPE->hStereoMdct->prev_ms_mask[1], 0, MAX_SFB ); + hCPE->hStereoMdct->lastCoh = 1.f; + hCPE->hStereoMdct->mdct_stereo_mode[0] = SMDCT_DUAL_MONO; + hCPE->hStereoMdct->mdct_stereo_mode[1] = SMDCT_DUAL_MONO; + hCPE->hStereoMdct->IGFStereoMode[0] = -1; + hCPE->hStereoMdct->IGFStereoMode[1] = -1; + } + + /*-----------------------------------------------------------------* + * Stereo CNG initialization + *-----------------------------------------------------------------*/ + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) || EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + IF( ( hCPE->hStereoCng = (STEREO_CNG_DEC_HANDLE) malloc( sizeof( STEREO_CNG_DEC ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for Stereo CNG\n" ) ); + } + stereo_cng_init_dec( hCPE->hStereoCng, &hCPE->hCoreCoder[0]->hFdCngDec->hFdCngCom->frameSize ); + } + + st_ivas->hCPE[cpe_id] = hCPE; + + return error; +} + + +/*------------------------------------------------------------------------- + * destroy_cpe_dec_fx() + * + * Destroy and deallocate IVAS decoder CPE handle + *-------------------------------------------------------------------------*/ + +void destroy_cpe_dec( + CPE_DEC_HANDLE hCPE /* i/o: CPE decoder structure */ +) +{ + Word16 n; + Decoder_State *st; + + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st = hCPE->hCoreCoder[n]; + + IF( st != NULL ) + { + destroy_core_dec( st ); + + free( st ); + st = NULL; + } + } + + IF( hCPE->hStereoDft != NULL ) + { + stereo_dft_dec_destroy( &( hCPE->hStereoDft ) ); + hCPE->hStereoDft = NULL; + } + + IF( hCPE->hStereoDftDmx != NULL ) + { + free( hCPE->hStereoDftDmx ); + hCPE->hStereoDftDmx = NULL; + } + + IF( hCPE->hStereoTD != NULL ) + { + free( hCPE->hStereoTD ); + hCPE->hStereoTD = NULL; + } + + IF( hCPE->hStereoMdct != NULL ) + { + free( hCPE->hStereoMdct ); + hCPE->hStereoMdct = NULL; + } + + IF( hCPE->hStereoTCA != NULL ) + { + free( hCPE->hStereoTCA ); + hCPE->hStereoTCA = NULL; + } + + IF( hCPE->hStereoICBWE != NULL ) + { + free( hCPE->hStereoICBWE ); + hCPE->hStereoICBWE = NULL; + } + + IF( hCPE->input_mem_LB[0] != NULL ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + free( hCPE->input_mem_LB[n] ); + hCPE->input_mem_LB[n] = NULL; + free( hCPE->input_mem[n] ); + hCPE->input_mem[n] = NULL; + free( hCPE->output_mem[n] ); + hCPE->output_mem[n] = NULL; +#ifdef IVAS_FLOAT_FIXED + free( hCPE->input_mem_LB_fx[n] ); + hCPE->input_mem_LB_fx[n] = NULL; + free( hCPE->input_mem_fx[n] ); + hCPE->input_mem_fx[n] = NULL; +#endif + + IF( hCPE->prev_synth_chs[n] != NULL ) + { + free( hCPE->prev_synth_chs[n] ); + hCPE->prev_synth_chs[n] = NULL; + } + IF( hCPE->prev_synth_chs_fx[n] != NULL ) + { + free( hCPE->prev_synth_chs_fx[n] ); + hCPE->prev_synth_chs_fx[n] = NULL; + } + } + free( hCPE->input_mem_BPF[0] ); + hCPE->input_mem_BPF[0] = NULL; +#ifdef IVAS_FLOAT_FIXED + free( hCPE->input_mem_BPF_fx[0] ); + hCPE->input_mem_BPF_fx[0] = NULL; +#endif + } + + IF( hCPE->hStereoCng != NULL ) + { + free( hCPE->hStereoCng ); + hCPE->hStereoCng = NULL; + } + + free( hCPE ); + + return; +} + + +/*------------------------------------------------------------------------- + * read_stereo_mode_and_bwidth_fx() + * + * Read stereo technology info & audio bandwidth + *-------------------------------------------------------------------------*/ + +static void read_stereo_mode_and_bwidth_fx( + CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ + const Decoder_Struct *st_ivas /* i : decoder main structure */ +) +{ + Decoder_State **sts; + + /*-----------------------------------------------------------------* + * BFI or NO_DATA frame: Use stereo parameters from last (active) frame + *-----------------------------------------------------------------*/ + + IF( st_ivas->bfi || LT_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_SID_5k2 ) ) + { + hCPE->element_mode = hCPE->last_element_mode; + } + + /*-----------------------------------------------------------------* + * SID frame: get element mode from SID side info + *-----------------------------------------------------------------*/ + + ELSE IF( EQ_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_SID_5k2 ) ) + { + SWITCH( st_ivas->sid_format ) + { + case SID_DFT_STEREO: + hCPE->element_mode = IVAS_CPE_DFT; + /* Read CNG type */ + hCPE->hCoreCoder[0]->cng_type = get_next_indice( hCPE->hCoreCoder[0], 1 ); + + /* Read BW information in SID */ + hCPE->hCoreCoder[0]->bwidth = get_next_indice( hCPE->hCoreCoder[0], 2 ); + BREAK; + case SID_MDCT_STEREO: + /* 2TC SBA DTX also uses MDCT-Stereo DTX */ + case SID_SBA_2TC: + hCPE->element_mode = IVAS_CPE_MDCT; + BREAK; + case SID_SBA_1TC: + assert( !"Forbidden value for SID format in CPE (SBA 1TC), should have already been adressed earlier" ); + BREAK; + case SID_MASA_1TC: + hCPE->element_mode = IVAS_SCE; + BREAK; + case SID_MASA_2TC: + /* 2TC MASA DTX uses MDCT or DFT based core */ + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + hCPE->element_mode = IVAS_CPE_DFT; + } + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) + { + /* Read CNG type */ + hCPE->hCoreCoder[0]->cng_type = get_next_indice( hCPE->hCoreCoder[0], 1 ); + + /* Read BW information in SID */ + hCPE->hCoreCoder[0]->bwidth = get_next_indice( hCPE->hCoreCoder[0], 2 ); + } + BREAK; + default: + /* this is what has been done for all modes previously, may need adaptation in the future */ + hCPE->element_mode = hCPE->last_element_mode; + BREAK; + } + } + + /*-----------------------------------------------------------------* + * active frame: read element mode and audio bandwidth info + *-----------------------------------------------------------------*/ + + ELSE + { + sts = hCPE->hCoreCoder; + IF( st_ivas->hMCT && NE_16( hCPE->cpe_id, 0 ) ) + { + sts[0]->bwidth = st_ivas->hCPE[0]->hCoreCoder[0]->bwidth; + sts[1]->bwidth = st_ivas->hCPE[0]->hCoreCoder[0]->bwidth; + } + ELSE + { + /* read stereo technology info */ + IF( LT_32( hCPE->element_brate, MIN_BRATE_MDCT_STEREO ) && st_ivas->hMCT == NULL ) + { + hCPE->element_mode = add( get_next_indice( sts[0], NBITS_ELEMENT_MODE ), IVAS_CPE_DFT ); + } + ELSE + { + hCPE->element_mode = IVAS_CPE_MDCT; + } + + /* read the bandwidth */ + IF( LT_32( hCPE->element_brate, MIN_BRATE_FB_STEREO ) ) + { + /* WB and SWB are supported */ + sts[0]->bwidth = add( get_next_indice( sts[0], 1 ), WB ); + sts[1]->bwidth = sts[0]->bwidth; + } + ELSE + { + /* WB, SWB and FB are supported */ + sts[0]->bwidth = get_next_indice( sts[0], NBITS_BWIDTH ); + sts[1]->bwidth = sts[0]->bwidth; + } + } + } + + return; +} + + +/*------------------------------------------------------------------------- + * stereo_mode_combined_format_dec_fx() + * + * Set stereo format in a combined format + *-------------------------------------------------------------------------*/ + +static void stereo_mode_combined_format_dec_fx( + const Decoder_Struct *st_ivas, /* i : decoder main structure */ + CPE_DEC_HANDLE hCPE /* i/o: CPE handle */ +) +{ + Word32 element_brate_ref; + + IF( EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + element_brate_ref = hCPE->element_brate; + + IF( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) && + ( ( EQ_16( st_ivas->nchan_ism, 3 ) && EQ_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_96k ) ) || + ( EQ_16( st_ivas->nchan_ism, 4 ) && EQ_32( st_ivas->hDecoderConfig->ivas_total_brate, IVAS_128k ) ) ) ) + { + IF( !st_ivas->bfi ) + { + /* read OMASA stereo mode signalling */ + IF( get_next_indice( hCPE->hCoreCoder[0], NBITS_ELEMENT_MODE ) ) + { + hCPE->element_mode = IVAS_CPE_MDCT; + } + ELSE + { + hCPE->element_mode = IVAS_CPE_DFT; + } + } + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) + { + hCPE->element_brate = IVAS_64k; + hCPE->brate_surplus = L_sub( hCPE->brate_surplus, L_sub( hCPE->element_brate, element_brate_ref ) ); + } + } + } + + return; +} +#endif diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c index 63f585fed..ec3e23c68 100644 --- a/lib_dec/ivas_jbm_dec.c +++ b/lib_dec/ivas_jbm_dec.c @@ -128,10 +128,32 @@ ivas_error ivas_jbm_dec_tc( else if ( st_ivas->ivas_format == STEREO_FORMAT ) { st_ivas->hCPE[0]->element_brate = ivas_total_brate; +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + Word16 q_output = 11; + output_fx[0] = malloc(sizeof(Word32) * L_FRAME48k); + output_fx[1] = malloc(sizeof(Word32) * L_FRAME48k); + set32_fx(&output_fx[0][0], 0, L_FRAME48k); + set32_fx(&output_fx[1][0], 0, L_FRAME48k); + + IF ( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, 0, &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < L_FRAME48k; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + free( output_fx[0] ); + free( output_fx[1] ); +#else if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, 0 ) ) != IVAS_ERR_OK ) { return error; } +#endif // IVAS_FLOAT_FIXED /* HP filtering */ for ( n = 0; n < min( nchan_out, st_ivas->nchan_transport ); n++ ) @@ -151,11 +173,37 @@ ivas_error ivas_jbm_dec_tc( { ivas_ism_dtx_dec( st_ivas, nb_bits_metadata ); +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[1]; + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( output_fx[0], 0, L_FRAME48k ); + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->prev_hb_synth[k] * ONE_IN_Q11 ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, st_ivas->hISMDTX.sce_id_dtx, &output_fx[0], output_frame, nb_bits_metadata[st_ivas->hISMDTX.sce_id_dtx] ) ) != IVAS_ERR_OK ) + { + return error; + } + for ( int k = 0; k < output_frame; k++ ) + { + p_output[st_ivas->hISMDTX.sce_id_dtx][k] = (float) output_fx[0][k] / ONE_IN_Q11; + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ONE_IN_Q11; + if ( k < 45 ) + st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->prev_hb_synth[k] = (float) st_ivas->hSCE[st_ivas->hISMDTX.sce_id_dtx]->prev_hb_synth_fx[k] / ONE_IN_Q11; + } + free( output_fx[0] ); +#else /* 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; } +#endif // IVAS_FLOAT_FIXED ivas_ism_dtx_limit_noise_energy_for_near_silence( st_ivas->hSCE, st_ivas->hISMDTX.sce_id_dtx, st_ivas->nchan_transport ); } @@ -209,10 +257,37 @@ ivas_error ivas_jbm_dec_tc( /* 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 ) ) { +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[1]; + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( output_fx[0], 0, L_FRAME48k ); + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[n]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[n]->prev_hb_synth[k] * ONE_IN_Q11 ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, n, &output_fx[0], output_frame, nb_bits_metadata[n] ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[n][k] = (float) output_fx[0][k] / ONE_IN_Q11; + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[n]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[n]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ONE_IN_Q11; + if ( k < 45 ) + st_ivas->hSCE[n]->prev_hb_synth[k] = (float) st_ivas->hSCE[n]->prev_hb_synth_fx[k] / ONE_IN_Q11; + } + free( output_fx[0] ); +#else if ( ( error = ivas_sce_dec( st_ivas, n, &p_output[n], output_frame, nb_bits_metadata[n] ) ) != IVAS_ERR_OK ) { return error; } +#endif // IVAS_FLOAT_FIXED } /* HP filtering */ @@ -264,6 +339,58 @@ ivas_error ivas_jbm_dec_tc( } /* core-decoding of transport channels */ +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[12]; + Word16 q_output = 11; + + IF( EQ_16( st_ivas->nSCE, 1 ) ) + { + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( output_fx[0], 0, L_FRAME48k ); + + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[0]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[0]->prev_hb_synth[k] * ( 1 << q_output ) ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ( 1 << q_output ); + if ( k < 45 ) + st_ivas->hSCE[0]->prev_hb_synth[k] = (float) st_ivas->hSCE[0]->prev_hb_synth_fx[k] / ( 1 << q_output ); + } + free( output_fx[0] ); + } + ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( &output_fx[0][0], 0, L_FRAME48k ); + set32_fx( &output_fx[1][0], 0, L_FRAME48k ); + + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < L_FRAME48k; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + free( output_fx[0] ); + free( output_fx[1] ); + } +#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 ) @@ -278,6 +405,7 @@ ivas_error ivas_jbm_dec_tc( return error; } } +#endif // IVAS_FLOAT_FIXED else if ( st_ivas->nCPE > 1 ) { if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) @@ -300,7 +428,6 @@ ivas_error ivas_jbm_dec_tc( dbgwrite_txt( &p_output[0][0], output_frame, "flt_ivas_agc_dec_process_output.txt", NULL ); #endif // DUMPS_ENABLED #else - Word32 *output_fx[12]; FOR( Word16 i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) { output_fx[i] = malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) ); @@ -413,6 +540,52 @@ ivas_error ivas_jbm_dec_tc( return error; } +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + Word16 q_output = 11; + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + + FOR( n = 0; n < nchan_transport_ism; n++ ) + { + set32_fx( output_fx[0], 0, L_FRAME48k ); + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[n]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[n]->prev_hb_synth[k] * ONE_IN_Q11 ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, n, &output_fx[0], output_frame, nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[st_ivas->nchan_transport + n][k] = (float) output_fx[0][k] / ONE_IN_Q11; + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[n]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[n]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ONE_IN_Q11; + if ( k < 45 ) + st_ivas->hSCE[n]->prev_hb_synth[k] = (float) st_ivas->hSCE[n]->prev_hb_synth_fx[k] / ONE_IN_Q11; + } + } + + /* decode MASA channels */ + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + + free( output_fx[0] ); + free( output_fx[1] ); +#else /* decode ISM channels */ for ( n = 0; n < nchan_transport_ism; n++ ) { @@ -427,6 +600,7 @@ ivas_error ivas_jbm_dec_tc( { return error; } +#endif // IVAS_FLOAT_FIXED if ( st_ivas->hCPE[0]->nchan_out == 1 ) { @@ -489,6 +663,55 @@ ivas_error ivas_jbm_dec_tc( } /* core-decoding of transport channels */ +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[12]; + Word16 q_output = 11; + + IF( EQ_16( st_ivas->nSCE, 1 ) ) + { + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( output_fx[0], 0, L_FRAME48k ); + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[0]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[0]->prev_hb_synth[k] * ( 1 << q_output ) ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0] + nb_bits_metadata[1] ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ( 1 << q_output ); + if ( k < 45 ) + st_ivas->hSCE[0]->prev_hb_synth[k] = (float) st_ivas->hSCE[0]->prev_hb_synth_fx[k] / ( 1 << q_output ); + } + free( output_fx[0] ); + } + ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0] + nb_bits_metadata[1], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + free( output_fx[0] ); + free( output_fx[1] ); + } +#else 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 ) @@ -503,6 +726,7 @@ ivas_error ivas_jbm_dec_tc( return error; } } +#endif // IVAS_FLOAT_FIXED 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 ) @@ -519,7 +743,6 @@ ivas_error ivas_jbm_dec_tc( dbgwrite_txt( &p_output[sba_ch_idx], output_frame, "flt_ivas_agc_dec_process_output.txt", NULL ); #endif // DUMPS_ENABLED #else - Word32 *output_fx[20]; FOR( Word16 i = 0; i < st_ivas->hSpar->hMdDec->spar_md_cfg.nchan_transport; i++ ) { output_fx[i] = malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) ); @@ -706,6 +929,28 @@ ivas_error ivas_jbm_dec_tc( /* read Parametric MC parameters from the bitstream */ ivas_param_mc_dec_read_BS( ivas_total_brate, st, st_ivas->hParamMC, &nb_bits_metadata[0] ); +#ifdef IVAS_FLOAT_FIXED + IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + Word32 *output_fx[2]; + Word16 q_output = 11; + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + + free( output_fx[0] ); + free( output_fx[1] ); + } +#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 ) @@ -713,6 +958,7 @@ ivas_error ivas_jbm_dec_tc( return error; } } +#endif // IVAS_FLOAT_FIXED else if ( st_ivas->nCPE > 1 ) { if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) @@ -749,19 +995,66 @@ ivas_error ivas_jbm_dec_tc( if ( st_ivas->hOutSetup.separateChannelEnabled ) { /* Decode the transport audio signals */ +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + Word16 q_output = 11; + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + + free( output_fx[0] ); + free( output_fx[1] ); +#else if ( ( error = ivas_cpe_dec( st_ivas, 0, p_output, output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) { return error; } +#endif // IVAS_FLOAT_FIXED /* 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 */ +#ifdef IVAS_FLOAT_FIXED + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( output_fx[0], 0, L_FRAME48k ); + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[0]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[0]->prev_hb_synth[k] * ONE_IN_Q11 ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, 0, &output_fx[0], output_frame, 0 ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[n][k] = (float) output_fx[0][k] / ONE_IN_Q11; + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ONE_IN_Q11; + if ( k < 45 ) + st_ivas->hSCE[0]->prev_hb_synth[k] = (float) st_ivas->hSCE[0]->prev_hb_synth_fx[k] / ONE_IN_Q11; + } + free( output_fx[0] ); +#else if ( ( error = ivas_sce_dec( st_ivas, 0, &p_output[n], output_frame, 0 ) ) != IVAS_ERR_OK ) { return error; } +#endif // IVAS_FLOAT_FIXED /* 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 || @@ -778,6 +1071,55 @@ ivas_error ivas_jbm_dec_tc( } else { +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + Word16 q_output = 11; + IF( EQ_16( st_ivas->nSCE, 1 ) ) + { + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( output_fx[0], 0, L_FRAME48k ); + for ( int k = 0; k < 45; k++ ) + { + st_ivas->hSCE[0]->prev_hb_synth_fx[k] = (Word32) ( st_ivas->hSCE[0]->prev_hb_synth[k] * ( 1 << q_output ) ); + } + + IF( ( error = ivas_sce_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0] ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + } + for ( int k = 0; k < 96; k++ ) + { + st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer[k] = (float) st_ivas->hSCE[0]->hCoreCoder[0]->prev_synth_buffer32_fx[k] / ( 1 << q_output ); + if ( k < 45 ) + st_ivas->hSCE[0]->prev_hb_synth[k] = (float) st_ivas->hSCE[0]->prev_hb_synth_fx[k] / ( 1 << q_output ); + } + free( output_fx[0] ); + } + ELSE IF( EQ_16( st_ivas->nCPE, 1 ) ) + { + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + + IF( ( error = ivas_cpe_dec_fx( st_ivas, 0, &output_fx[0], output_frame, nb_bits_metadata[0], &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < output_frame; k++ ) + { + p_output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + p_output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + + free( output_fx[0] ); + free( output_fx[1] ); + } +#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 ) @@ -792,6 +1134,7 @@ ivas_error ivas_jbm_dec_tc( return error; } } +#endif // IVAS_FLOAT_FIXED } if ( st_ivas->sba_dirac_stereo_flag ) /* use the flag to trigger the DFT upmix */ diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 3c971f231..e06fb74ea 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -126,10 +126,32 @@ ivas_error ivas_mct_dec( set_s( param_lpc[cpe_id][n], 0, NPRM_LPC_NEW ); } +#ifdef IVAS_FLOAT_FIXED + Word32 *output_fx[2]; + Word16 q_output = 11; + output_fx[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + output_fx[1] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set32_fx( &output_fx[0][0], 0, L_FRAME48k ); + set32_fx( &output_fx[1][0], 0, L_FRAME48k ); + + IF( ( error = ivas_cpe_dec_fx( st_ivas, cpe_id, &output_fx[0], output_frame, 0, &q_output ) ) != IVAS_ERR_OK ) + { + return error; + } + + for ( int k = 0; k < L_FRAME48k; k++ ) + { + output[0][k] = (float) output_fx[0][k] / ( 1 << q_output ); + output[1][k] = (float) output_fx[1][k] / ( 1 << q_output ); + } + free( output_fx[0] ); + free( output_fx[1] ); +#else if ( ( error = ivas_cpe_dec( st_ivas, cpe_id, output, output_frame, 0 ) ) != IVAS_ERR_OK ) { return error; } +#endif // IVAS_FLOAT_FIXED if ( cpe_id == 0 ) { diff --git a/lib_dec/ivas_sce_dec.c b/lib_dec/ivas_sce_dec.c index fc27af7f6..367ecccc8 100644 --- a/lib_dec/ivas_sce_dec.c +++ b/lib_dec/ivas_sce_dec.c @@ -285,7 +285,7 @@ ivas_error ivas_sce_dec( return error; } - +#ifndef IVAS_FLOAT_FIXED /*------------------------------------------------------------------------- * create_sce_dec() * @@ -443,3 +443,4 @@ void destroy_sce_dec( return; } +#endif // !IVAS_FLOAT_FIXED diff --git a/lib_dec/ivas_sce_dec_fx.c b/lib_dec/ivas_sce_dec_fx.c new file mode 100644 index 000000000..50a9817cc --- /dev/null +++ b/lib_dec/ivas_sce_dec_fx.c @@ -0,0 +1,513 @@ +/****************************************************************************************************** + + (C) 2022-2023 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository. All Rights Reserved. + + This software is protected by copyright law and by international treaties. + The IVAS codec Public Collaboration consisting of Dolby International AB, Ericsson AB, + Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e.V., Huawei Technologies Co. LTD., + Koninklijke Philips N.V., Nippon Telegraph and Telephone Corporation, Nokia Technologies Oy, Orange, + Panasonic Holdings Corporation, Qualcomm Technologies, Inc., VoiceAge Corporation, and other + contributors to this repository retain full ownership rights in their respective contributions in + the software. This notice grants no license of any kind, including but not limited to patent + license, nor is any license granted by implication, estoppel or otherwise. + + Contributors are required to enter into the IVAS codec Public Collaboration agreement before making + contributions. + + This software is provided "AS IS", without any express or implied warranties. The software is in the + development stage. It is intended exclusively for experts who have experience with such software and + solely for the purpose of inspection. All implied warranties of non-infringement, merchantability + and fitness for a particular purpose are hereby disclaimed and excluded. + + Any dispute, controversy or claim arising under or in relation to providing this software shall be + submitted to and settled by the final, binding jurisdiction of the courts of Munich, Germany in + accordance with the laws of the Federal Republic of Germany excluding its conflict of law rules and + the United Nations Convention on Contracts on the International Sales of Goods. + +*******************************************************************************************************/ + +#include +#include +#include "options.h" +#ifdef IVAS_FLOAT_FIXED +#include "cnst.h" +#include "ivas_cnst.h" +#include "rom_com.h" +#include "prot.h" +#include "prot_fx1.h" +#include "prot_fx2.h" +#include "ivas_prot.h" +#include "ivas_prot_fx.h" +#include "ivas_rom_com.h" +#include "wmc_auto.h" + +/* NOTE: Temporary macro for computation happening in floating point. This macro and code active under this is to be removed once the intermediate conversions to float are not required */ +#define IVAS_FLOAT_FIXED_TO_BE_REMOVED + +/*--------------------------------------------------------------------------* + * ivas_sce_dec() + * + * Single Channel Element (SCE) decoding routine + *--------------------------------------------------------------------------*/ + +ivas_error ivas_sce_dec_fx( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 sce_id, /* i : SCE # identifier */ + Word32 *output[1], /* o : output synthesis signal */ + const Word16 output_frame, /* i : output frame length per channel */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +) +{ + Word32 outputHB[1][L_FRAME48k]; /* 'float' buffer for output HB synthesis, one channel */ + SCE_DEC_HANDLE hSCE; + Decoder_State *st; + Word32 ivas_total_brate, last_ivas_total_brate; + ivas_error error; + + error = IVAS_ERR_OK; + + push_wmops( "ivas_sce_dec" ); + + hSCE = st_ivas->hSCE[sce_id]; + st = hSCE->hCoreCoder[0]; + + st->BER_detect = s_or( st->BER_detect, st_ivas->BER_detect ); + + ivas_total_brate = st_ivas->hDecoderConfig->ivas_total_brate; + last_ivas_total_brate = st_ivas->hDecoderConfig->last_ivas_total_brate; + + IF( EQ_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) ) + { + st->cng_type = FD_CNG; + } + + /*------------------------------------------------------------------* + * Read audio bandwidth info + *-----------------------------------------------------------------*/ + + /* set total_brate - needed in DTX */ + IF( !st_ivas->bfi && EQ_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + st->total_brate = L_sub( ivas_total_brate, L_shr( L_mult( nb_bits_metadata, FRAMES_PER_SEC ), 1 ) ); + assert( EQ_32( st->total_brate, SID_2k40 ) && "SCE SID must be 2.4kbps!" ); + + IF( EQ_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) && NE_16( st_ivas->hISMDTX.sce_id_dtx, sce_id ) ) + { + st->total_brate = FRAME_NO_DATA; + } + } + ELSE IF( !st_ivas->bfi && EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) + { + st->total_brate = FRAME_NO_DATA; + } + ELSE IF( !st_ivas->bfi && NE_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) && LE_32( last_ivas_total_brate, IVAS_SID_5k2 ) ) + { + st->total_brate = L_sub( hSCE->element_brate, L_shr( L_mult( nb_bits_metadata, FRAMES_PER_SEC ), 1 ) ); + } + + /* read the bandwidth */ + IF( st_ivas->bfi || LE_32( st->total_brate, SID_2k40 ) ) + { + /* BFI or SID/NO_DATA frame -> do nothing */ + } + ELSE + { + IF( st->low_rate_mode ) + { + /* ISM Low-rate mode -> always WB */ + st->bwidth = WB; + } + ELSE IF( LT_32( hSCE->element_brate, MIN_BRATE_SWB_SCE ) ) + { + /* only WB is supported */ + st->bwidth = WB; + } + ELSE IF( ( LT_32( hSCE->element_brate, MIN_BRATE_FB_STEREO ) && !st->is_ism_format ) || + ( LT_32( hSCE->element_brate, MIN_BRATE_FB_ISM ) && st->is_ism_format ) ) + { + /* WB and SWB are supported */ + st->bwidth = add( get_next_indice( st, 1 ), WB ); + } + ELSE + { + /* WB, SWB and FB are supported */ + st->bwidth = get_next_indice( st, NBITS_BWIDTH ); + } + } + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + st->idchan = 0; + st->element_mode = IVAS_SCE; + + /* Force to MODE1 in IVAS */ + st->codec_mode = MODE1; + + /* set "bits_frame_nominal" */ + IF( ( st_ivas->hQMetaData != NULL ) && + NE_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) ) + { + IF( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) + { + st->bits_frame_nominal = extract_l( L_sub( Mpy_32_16_1( hSCE->element_brate, INV_FRAME_PER_SEC_Q15 ), ISM_NB_BITS_METADATA_NOMINAL ) ); + } + ELSE IF( ( EQ_16( (Word16) st_ivas->mc_mode, MC_MODE_MCMASA ) && GE_32( ivas_total_brate, MCMASA_SEPARATE_BRATE ) ) || ( EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) ) ) + { + st->bits_frame_nominal = extract_l( Mpy_32_16_1( hSCE->element_brate, INV_FRAME_PER_SEC_Q15 ) ); + } + ELSE IF( EQ_16( (Word16) st_ivas->ism_mode, ISM_MODE_NONE ) && EQ_16( (Word16) st_ivas->ivas_format, SBA_ISM_FORMAT ) ) + { + st->bits_frame_nominal = extract_l( Mpy_32_16_1( st_ivas->hSpar->core_nominal_brate, INV_FRAME_PER_SEC_Q15 ) ); + } + ELSE + { + st->bits_frame_nominal = st_ivas->hQMetaData->bits_frame_nominal; + } + } + ELSE IF( EQ_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) ) + { + st->bits_frame_nominal = extract_l( Mpy_32_16_1( st_ivas->hSpar->core_nominal_brate, INV_FRAME_PER_SEC_Q15 ) ); + } + ELSE + { + st->bits_frame_nominal = extract_l( L_sub( Mpy_32_16_1( hSCE->element_brate, INV_FRAME_PER_SEC_Q15 ), ISM_NB_BITS_METADATA_NOMINAL ) ); + } + + + /* set "total_brate" */ + IF( !st_ivas->bfi && EQ_32( ivas_total_brate, IVAS_SID_5k2 ) ) + { + st->total_brate = L_sub( ivas_total_brate, L_shr( L_mult( nb_bits_metadata, FRAMES_PER_SEC ), 1 ) ); + + IF( EQ_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) && NE_16( st_ivas->hISMDTX.sce_id_dtx, sce_id ) ) + { + st->total_brate = FRAME_NO_DATA; + } + } + ELSE IF( !st_ivas->bfi && EQ_32( ivas_total_brate, FRAME_NO_DATA ) ) + { + st->total_brate = ivas_total_brate; + } + ELSE IF( !st_ivas->bfi && NE_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) && NE_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) /* note: in ISMs, total_brate[] is set in ivas_ism_config() */ + { + st->total_brate = L_sub( hSCE->element_brate, L_shr( L_mult( nb_bits_metadata, FRAMES_PER_SEC ), 1 ) ); + } + + /*----------------------------------------------------------------* + * Core codec configuration + *----------------------------------------------------------------*/ + + /* set ACELP12k8 / ACELP16k flag for flexible ACELP core */ + IF( ( EQ_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_DISC ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_PARAM_ONE_OBJ ) || EQ_16( (Word16) st_ivas->ism_mode, ISM_MASA_MODE_MASA_ONE_OBJ ) ) && + st->low_rate_mode && !( EQ_32( st->total_brate, SID_2k40 ) || EQ_32( st->total_brate, FRAME_NO_DATA ) ) ) + { + st->flag_ACELP16k = 0; + } + ELSE + { + st->flag_ACELP16k = set_ACELP_flag_IVAS( IVAS_SCE, hSCE->element_brate, st->total_brate, 0, 0, -1, -1 ); + } + + IF( is_DTXrate( ivas_total_brate ) ) + { + st->VAD = 0; + } + ELSE + { + st->VAD = 1; + } + + IF( st->VAD && LE_32( hSCE->element_brate, CNA_MAX_BRATE ) ) + { + st->flag_cna = 1; + } + ELSE IF( ( EQ_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_FORMAT ) ) && LE_32( hSCE->element_brate, ACELP_32k ) ) + { + st->flag_cna = 1; + } + ELSE + { + st->flag_cna = 0; + } + + /*----------------------------------------------------------------* + * Decoder + *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + float *output_flt[1]; + float outputHB_flt[1][960]; + output_flt[0] = malloc( sizeof( Word32 ) * L_FRAME48k ); + set_f( output_flt[0], 0, L_FRAME48k ); + FOR( int k = 0; k < L_FRAME48k; k++ ) + { + output_flt[0][k] = (float) output[0][k] / ONE_IN_Q11; + } +#endif // !IVAS_FLOAT_FIXED_TO_BE_REMOVED + + IF( ( error = ivas_core_dec( st_ivas, hSCE, NULL, NULL, 1, output_flt, outputHB_flt, NULL, st_ivas->sba_dirac_stereo_flag ) ) != IVAS_ERR_OK ) + { + return error; + } +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + FOR( int k = 0; k < L_FRAME48k; k++ ) + { + output[0][k] = (Word32) ( output_flt[0][k] * ONE_IN_Q11 ); + outputHB[0][k] = (Word32) ( outputHB_flt[0][k] * ONE_IN_Q11 ); + } + free( output_flt[0] ); +#endif // !IVAS_FLOAT_FIXED_TO_BE_REMOVED + + IF( st_ivas->sba_dirac_stereo_flag && ( GT_32( st->core_brate, SID_2k40 ) || EQ_16( st->cng_type, LP_CNG ) ) ) + { + /* skip addition of ACELP BWE for now, will be done after upmix */ +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + mvr2r( outputHB_flt[0], hSCE->save_hb_synth, output_frame ); +#else + Copy32( outputHB[0], hSCE->save_hb_synth_fx, output_frame ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + } + ELSE IF( !st_ivas->sba_dirac_stereo_flag ) + { + Word32 output_Fs; + + output_Fs = st_ivas->hDecoderConfig->output_Fs; + + /*----------------------------------------------------------------* + * LB synthesis synchronization between IVAS formats + *----------------------------------------------------------------*/ + + delay_signal_fx( output[0], output_frame, st->prev_synth_buffer32_fx, NS2SA_fx2( output_Fs, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS ) ); + + /*----------------------------------------------------------------* + * HB synthesis synchronization between IVAS formats + *----------------------------------------------------------------*/ + + delay_signal_fx( outputHB[0], output_frame, hSCE->prev_hb_synth_fx, NS2SA_fx2( output_Fs, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS ) ); + + /*----------------------------------------------------------------* + * output LB and HB mix + *----------------------------------------------------------------*/ + + v_add_fx( output[0], outputHB[0], output[0], output_frame ); + } + + /*----------------------------------------------------------------* + * Common updates + *----------------------------------------------------------------*/ + + hSCE->last_element_brate = hSCE->element_brate; + + st_ivas->BER_detect = s_or( st_ivas->BER_detect, st->BER_detect ); + + + pop_wmops(); + return error; +} + + +/*------------------------------------------------------------------------- + * create_sce_dec() + * + * Create, allocate and initialize IVAS decoder SCE handle + *-------------------------------------------------------------------------*/ + +ivas_error create_sce_dec( + Decoder_Struct *st_ivas, /* i/o: IVAS decoder structure */ + const Word16 sce_id, /* i : SCE # identifier */ + const Word32 element_brate /* i : element bitrate */ +) +{ + SCE_DEC_HANDLE hSCE; + Decoder_State *st; + ivas_error error; + Word16 output_frame; + + error = IVAS_ERR_OK; + output_frame = extract_l( Mpy_32_16_1( st_ivas->hDecoderConfig->output_Fs, INV_FRAME_PER_SEC_Q15 ) ); + + /*-----------------------------------------------------------------* + * Allocate SCE handle + *-----------------------------------------------------------------*/ + + IF( ( hSCE = (SCE_DEC_HANDLE) malloc( sizeof( SCE_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for SCE\n" ) ); + } + + /*-----------------------------------------------------------------* + * Initialization - general parameters + *-----------------------------------------------------------------*/ + + hSCE->sce_id = sce_id; + hSCE->element_brate = element_brate; + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + set_f( hSCE->prev_hb_synth, 0.0f, NS2SA( st_ivas->hDecoderConfig->output_Fs, L_sub( IVAS_DEC_DELAY_NS, DELAY_BWE_TOTAL_NS ) ) ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + set32_fx( hSCE->prev_hb_synth_fx, 0, NS2SA_fx2( st_ivas->hDecoderConfig->output_Fs, L_sub( IVAS_DEC_DELAY_NS, DELAY_BWE_TOTAL_NS ) ) ); + + /*-----------------------------------------------------------------* + * Core Coder, 1 instance: allocate and initialize + *-----------------------------------------------------------------*/ + + // IF ( ( st = (DEC_CORE_HANDLE) calloc( sizeof( Decoder_State ) ) ) == NULL ) + IF( ( st = (Decoder_State *) calloc( 1, sizeof( Decoder_State ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for CoreCoder structure\n" ) ); + } + + copy_decoder_config( st_ivas, st ); + + st->total_brate = hSCE->element_brate; /* dummy initialization for getting right pointers initialization of input buffers in init_coder_ace_plus() */ + st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + st->is_ism_format = 0; + IF( EQ_16( (Word16) st_ivas->ivas_format, ISM_FORMAT ) || EQ_16( (Word16) st_ivas->ivas_format, MASA_ISM_FORMAT ) ) + { + st->is_ism_format = 1; + } +#ifdef EVS_FLOAT + IF( ( error = init_decoder( st, 0, st_ivas->mc_mode ) ) != IVAS_ERR_OK ) +#else + IF( ( error = init_decoder_fx( st, EVS_MONO ) ) != IVAS_ERR_OK ) +#endif + { + return error; + } + + IF( EQ_16( (Word16) st_ivas->ivas_format, SBA_FORMAT ) && ( EQ_16( (Word16) st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_STEREO ) || ( EQ_16( (Word16) st_ivas->hDecoderConfig->output_config, IVAS_AUDIO_CONFIG_MONO ) && EQ_16( st_ivas->nchan_transport, 1 ) ) ) ) + { + IF( ( error = openCldfb_ivas( &st->cldfbSynHB, CLDFB_SYNTHESIS, st->output_Fs, CLDFB_PROTOTYPE_1_25MS ) ) != IVAS_ERR_OK ) + { + return error; + } + } + ELSE + { + st->cldfbSynHB = NULL; + } + + /* allocate and initialize "hTdCngDec" - needed in DTX */ + IF( EQ_16( sce_id, 0 ) && st->hTdCngDec == NULL ) + { + IF( ( st->hTdCngDec = (TD_CNG_DEC_HANDLE) malloc( sizeof( TD_CNG_DEC_DATA ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for DTX/TD CNG\n" ) ); + } + +#ifndef IVAS_FLOAT_FIXED_TO_BE_REMOVED + td_cng_dec_init( st ); +#else + td_cng_dec_init_flt( st ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + } + + /*-----------------------------------------------------------------* + * Synthesis buffers: allocate and initialize + *-----------------------------------------------------------------*/ + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + IF( st_ivas->sba_dirac_stereo_flag ) + { + IF( ( hSCE->save_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) ); + } + set_zero( hSCE->save_synth, output_frame ); + + IF( ( hSCE->save_hb_synth = (float *) malloc( sizeof( float ) * output_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) ); + } + set_zero( hSCE->save_hb_synth, output_frame ); + } + ELSE + { + hSCE->save_synth = NULL; + hSCE->save_hb_synth = NULL; + } +#else + IF( st_ivas->sba_dirac_stereo_flag ) + { + IF( ( hSCE->save_synth_fx = (Word32 *) malloc( sizeof( Word32 ) * output_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for stereo output\n" ) ); + } + set32_fx( hSCE->save_synth_fx, 0, output_frame ); + + IF( ( hSCE->save_hb_synth_fx = (Word32 *) malloc( sizeof( Word32 ) * output_frame ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate HB memory for stereo output\n" ) ); + } + set32_fx( hSCE->save_hb_synth_fx, 0, output_frame ); + } + ELSE + { + hSCE->save_synth_fx = NULL; + hSCE->save_hb_synth_fx = NULL; + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + hSCE->hCoreCoder[0] = st; + st_ivas->hSCE[sce_id] = hSCE; + + return error; +} + + +/*------------------------------------------------------------------------- + * destroy_sce_dec() + * + * Destroy and deallocate IVAS decoder SCE handle + *-------------------------------------------------------------------------*/ + +void destroy_sce_dec( + SCE_DEC_HANDLE hSCE /* i/o: SCE decoder structure */ +) +{ + Decoder_State *st; + + st = hSCE->hCoreCoder[0]; + + IF( st != NULL ) + { + destroy_core_dec( st ); + + free( st ); + st = NULL; + } + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + IF( hSCE->save_synth != NULL ) + { + free( hSCE->save_synth ); + hSCE->save_synth = NULL; + } + IF( hSCE->save_hb_synth != NULL ) + { + free( hSCE->save_hb_synth ); + hSCE->save_hb_synth = NULL; + } +#else + IF( hSCE->save_synth_fx != NULL ) + { + free( hSCE->save_synth_fx ); + hSCE->save_synth_fx = NULL; + } + IF( hSCE->save_hb_synth_fx != NULL ) + { + free( hSCE->save_hb_synth_fx ); + hSCE->save_hb_synth_fx = NULL; + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + free( hSCE ); + + return; +} +#endif diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h index f0a8b1809..85fd592f6 100644 --- a/lib_dec/ivas_stat_dec.h +++ b/lib_dec/ivas_stat_dec.h @@ -740,6 +740,12 @@ typedef struct sce_dec_data_structure float *save_synth; float *save_hb_synth; +#ifdef IVAS_FLOAT_FIXED + Word32 prev_hb_synth_fx[NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )]; /* HB synthesis synchro buffer */ + + Word32 *save_synth_fx; + Word32 *save_hb_synth_fx; +#endif // IVAS_FLOAT_FIXED } SCE_DEC_DATA, *SCE_DEC_HANDLE; @@ -785,9 +791,21 @@ typedef struct cpe_dec_data_structure float *prev_synth_chs[CPE_CHANNELS]; #ifdef IVAS_FLOAT_FIXED + Word32 lt_es_em_fx; + + Word32 prev_hb_synth_fx[CPE_CHANNELS][NS2SA( 48000, IVAS_DEC_DELAY_NS - DELAY_BWE_TOTAL_NS )]; + Word32 prev_synth_fx[CPE_CHANNELS][NS2SA( 48000, IVAS_DEC_DELAY_NS - STEREO_DFT32MS_OVL_NS )]; + Word32 *input_mem_fx[CPE_CHANNELS]; Word32 *input_mem_LB_fx[CPE_CHANNELS]; Word32 *input_mem_BPF_fx[1]; + + Word32 *output_mem_fx[CPE_CHANNELS]; + Word32 *prev_synth_chs_fx[CPE_CHANNELS]; + + /* buffers used for fading between MDCT and DFT Stereo */ + Word32 old_out_mdct_fx[STEREO_MDCT2DFT_FADE_LEN_48k]; + Word32 old_outLB_mdct_fx[2 * STEREO_MDCT2DFT_FADE_LEN_48k]; #endif /* buffers used for fading between MDCT and DFT Stereo */ diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 3968a56da..8849e60bc 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -2576,6 +2576,7 @@ typedef struct Decoder_State Word16 last_element_mode; /* element mode */ Word16 coder_type_fx; /* low-rate mode flag */ + Word32 prev_synth_buffer32_fx[NS2SA(48000, IVAS_DEC_DELAY_NS - DELAY_CLDFB_NS)]; #ifdef DEBUGGING Word16 id_element; /* element ID */ -- GitLab