diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index f4730d4bd6dd5553a8d650cea5035494b8f686a2..d8676806d58bb4b36bc572fd2fc37923f6536ff6 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 094beaa56f5966efa7e6f744a06eb54d45897298..ea00c940e0302fbc2e23ec94002960134f894c63 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 e4bc8a0c5b85a1f142ebd16580cb93f662b807da..def5e79355df13688421c3c82f9173953aede39a 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 c111f0d22164db8938dfd939d2bc66145525faa4..2f1e3f98bd6581260cc94b594ab8835ae0be8f71 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 422bb5ef577a9d028d9a2262565cb3299d8b1206..37cb165c4877dc7f09dbffcf2a64c2f457c71fb5 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 94b93e505b7f7d29189a0f73b184da99c0fed189..df3dcced85fe56c5dd7e212bd7f6aabed0c1f8b6 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 0000000000000000000000000000000000000000..c9cfa8a399733cd681f4c8d1cd705aa46ba689ab
--- /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 63f585fed998608e8802ae0b9a573ccaf2882198..ec3e23c683df12dd0047aa4bbcbeb1e1403c92eb 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 3c971f231e5c23a7194c81f7a1497179216bba21..e06fb74eac014003f4624437bd60f7b8e1a5ad08 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 fc27af7f6ff47fa2b06d982f5d519eab5611d344..367ecccc893dd520a99c6e5655aaad0f0dc1c359 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 0000000000000000000000000000000000000000..50a9817cce277ebfd0d2ae83979ce6e197d64b08
--- /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 f0a8b1809bfc4ccb3e93ca84812313bd4319b1af..85fd592f682a437eea160bb64bd0f7b9c7d5fa2c 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 3968a56da72918e42b5c2a8ca800ec1201698a2e..8849e60bc5ba613b5623524a6588ea445bbac673 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 */