diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj
index 8f4a7ba25ad60dbcff5ccbea673cfe33240dcd0c..f4730d4bd6dd5553a8d650cea5035494b8f686a2 100644
--- a/Workspace_msvc/lib_dec.vcxproj
+++ b/Workspace_msvc/lib_dec.vcxproj
@@ -292,6 +292,7 @@
+
diff --git a/Workspace_msvc/lib_dec.vcxproj.filters b/Workspace_msvc/lib_dec.vcxproj.filters
index 61337a076118a3aea034821b403591006b791eb6..094beaa56f5966efa7e6f744a06eb54d45897298 100644
--- a/Workspace_msvc/lib_dec.vcxproj.filters
+++ b/Workspace_msvc/lib_dec.vcxproj.filters
@@ -818,6 +818,9 @@
decoder_all_c
+
+ decoder_ivas_c
+
diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h
index aa3057070f944ca22883b9f8d10cc5850581ffbd..b47dcb65a27002648ef5ace79feaacf60879b8bd 100644
--- a/lib_com/ivas_cnst.h
+++ b/lib_com/ivas_cnst.h
@@ -1457,6 +1457,7 @@ typedef enum
#define IVAS_LFE_MAX_NUM_DCT_PASS_BINS 8
#define IVAS_LFE_MAX_NUM_DCT_COEFFS (IVAS_LFE_MAX_NUM_DCT_PASS_BINS * IVAS_LFE_NUM_COEFFS_IN_SUBGRP)
#define IVAS_LFE_FADE_NS 8000000L /* 8.0 ms */
+#define IVAS_LFE_FADE_S_Q15 263 /* 8.0 ms in Q15 */
#define IVAS_MAX_NUM_QUANT_STRATS 2
#define IVAS_MAX_NUM_DCT_COEF_GROUPS 4
#define IVAS_LFE_SHIFT_BITS 5
diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h
index a0f622c28ec56f9227532a5efe905760cae1604a..8dfa630f500886ded777c6a8b749aabdd1c1afc2 100644
--- a/lib_com/ivas_prot_fx.h
+++ b/lib_com/ivas_prot_fx.h
@@ -490,6 +490,31 @@ void ivas_ism_metadata_sid_dec_fx(
Word16 nb_bits_metadata[] /* o : number of metadata bits */
);
+//ivas_lfe_dec_fx.c
+
+void ivas_lfe_dec_close_fx(
+ LFE_DEC_HANDLE *hLFE /* i/o: LFE encoder handle */
+);
+
+ivas_error ivas_create_lfe_dec_fx(
+ LFE_DEC_HANDLE *hLFE_out, /* o : IVAS LFE decoder structure */
+ const Word32 output_Fs, /* i : output sampling rate */
+ const Word32 binauralization_delay_ns /* i : additional LFE delay to sync with binaural renderer */
+);
+
+void ivas_lfe_dec_fx(
+ LFE_DEC_HANDLE hLFE, /* i/o: LFE decoder handle */
+ Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 bfi, /* i : BFI flag */
+ Word32 output_lfe_ch[] /* o : output LFE synthesis */
+);
+
+void ivas_lfe_dec_close_fx(
+ LFE_DEC_HANDLE *hLFE /* i/o: LFE decoder handle */
+);
+
+
void td_stereo_param_updt_fx(
const Word16 lsp_old_PCh[], /* i : primary channel old LSPs */
const Word16 lsf_old_PCh[], /* i : primary channel old LSFs */
@@ -518,4 +543,5 @@ void stereo_cng_compute_PScorr_fx(
const Word16 L_frame_0, /* i : L_frame channel 0 */
const Word16 L_frame_1 /* i : L_frame channel 1 */
);
+
#endif
\ No newline at end of file
diff --git a/lib_com/ivas_rom_com.c b/lib_com/ivas_rom_com.c
index d472f79aa503c85d81bf69120b6eaef6d629e799..9ce55d69cc6e33622794bc6b6e736f782f220713 100644
--- a/lib_com/ivas_rom_com.c
+++ b/lib_com/ivas_rom_com.c
@@ -3487,11 +3487,17 @@ const int16_t ivas_lfe_num_ele_in_coder_models[2][4] =
{ 63, 31, 7, 1 },{ 31, 15, 3, 0 }
};
+const Word16 ivas_lfe_log2_num_ele_in_coder_models_fx[2][4] =
+{
+ { 6, 5, 3, 1 },{ 5, 4, 2, 0 }
+};
+
const int16_t ivas_lfe_num_dct_pass_bins_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 8, 6 };
const int16_t ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP] = { 1, 0 };
const float ivas_lfe_lpf_delay[2] = { 0.00175f, 0.0035f };
+const Word16 ivas_lfe_lpf_delay_Q15[2] = { 57, 114 };
const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2] =
{
diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h
index 8473de40f0781c14b05f3588067f0b1627d5c0c5..e2f1b564ed144b5a5100e3525376b9c1e862e8fe 100644
--- a/lib_com/ivas_rom_com.h
+++ b/lib_com/ivas_rom_com.h
@@ -400,10 +400,12 @@ extern const Word32 ivas_lfe_window_coeff_16k_fx[IVAS_LFE_FADE_LEN_16K];
extern const int16_t ivas_lfe_num_ele_in_coder_models[2][4];
+extern const Word16 ivas_lfe_log2_num_ele_in_coder_models_fx[2][4];
extern const int16_t ivas_lfe_num_dct_pass_bins_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP];
extern const int16_t ivas_lfe_min_shift_tbl[IVAS_LFE_NUM_COEFFS_IN_SUBGRP];
extern const ivas_lfe_freq_models ivas_str_lfe_freq_models;
extern const float ivas_lfe_lpf_delay[2];
+extern const Word16 ivas_lfe_lpf_delay_Q15[2];
extern const double d_hamm_lfe_plc[LFE_PLC_LENANA / 2];
diff --git a/lib_com/prot_fx1.h b/lib_com/prot_fx1.h
index 8f69b205e9f60e92938b598ca3c023e6a58db8d9..91b003e18eda396ba19c443e51a68fb30b5291ea 100644
--- a/lib_com/prot_fx1.h
+++ b/lib_com/prot_fx1.h
@@ -491,6 +491,13 @@ void delay_signal(
const Word16 delay /* i : delay in samples */
);
+void delay_signal32(
+ Word32 x[], /* i/o: signal to be delayed */
+ const Word16 len, /* i : length of the input signal */
+ Word32 mem[], /* i/o: synchronization memory */
+ const Word16 delay /* i : delay in samples */
+);
+
Word16 ceil_log_2( UWord64 val );
#ifdef IVAS_FLOAT_FIXED
diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c
index ef622eca12ebb68cbdf5927a0dc834b661fede7d..290647252bd92abfd80cd206e5e60bc14c859d35 100644
--- a/lib_com/rom_com.c
+++ b/lib_com/rom_com.c
@@ -39898,3 +39898,11 @@ const Word16 T_DIV_L_Frame[] = /*0Q15 * 2^-7 */
,8192 /*512*/
,6553 /*640*/
};
+
+const Word32 tbl_two_pow_shift_by_4[35] = {
+ 1073741824, 902905664, 759250112, 638450688, 536870912, 451452832, 379625056, 319225344,
+ 268435456, 225726416, 189812528, 159612672, 134217728, 112863208, 94906264, 79806336,
+ 67108864, 56431604, 47453132, 39903168, 33554432, 28215802, 23726566, 19951584,
+ 16777216, 14107901, 11863283, 9975792, 8388608, 7053950, 5931641, 4987896,
+ 4194304, 3526975, 2965820
+};
diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h
index 75a3047543c5e294650ec616956388fb7a3ca464..db63ef4f94417aad98f77c8799cfa2241abb02c8 100644
--- a/lib_com/rom_com.h
+++ b/lib_com/rom_com.h
@@ -2050,4 +2050,7 @@ extern const Word16 T_DIV_L_Frame[];/*0Q15 * 2^-7 */
extern const Word16 pow_tilt_16k[64]; /* Q7 */
extern const Word16 pow_tilt_25_6k[64]; /* Q7 */
extern const Word16 pow_tilt_32k[64]; /* Q7 */
+
+//ivas_lfe_dec_fx.c
+extern const Word32 tbl_two_pow_shift_by_4[35]; /* Q30 */
#endif
diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c
index 7343343d8321c17918fbfe31cc78b30e2d12c92b..e05a662fb8a888cf47d829f0a8780ebd6480eb40 100644
--- a/lib_com/tools_fx.c
+++ b/lib_com/tools_fx.c
@@ -3401,3 +3401,25 @@ void v_add_fx(
return;
}
+/*-------------------------------------------------------------------*
+ * delay_signal()
+ *
+ * Delay buffer by defined number of samples
+ *-------------------------------------------------------------------*/
+
+void delay_signal32(
+ Word32 x[], /* i/o: signal to be delayed */
+ const Word16 len, /* i : length of the input signal */
+ Word32 mem[], /* i/o: synchronization memory */
+ const Word16 delay /* i : delay in samples */
+)
+{
+ Word32 tmp_buffer[L_FRAME48k];
+
+ Copy32(mem, tmp_buffer, delay);
+ Copy32(x + len - delay, mem, delay);
+ Copy32(x, x + delay, len - delay);
+ Copy32(tmp_buffer, x, delay);
+
+ return;
+}
diff --git a/lib_dec/ivas_init_dec.c b/lib_dec/ivas_init_dec.c
index 74702e66f5c4726daf6e05b4c3925ed84ed2c046..92525bfd3a60475cb0f18489ac97863184d25a14 100644
--- a/lib_dec/ivas_init_dec.c
+++ b/lib_dec/ivas_init_dec.c
@@ -42,6 +42,10 @@
#include
#include "wmc_auto.h"
#include "ivas_prot_fx.h"
+#ifdef IVAS_FLOAT_FIXED
+#include "prot_fx1.h"
+#include "prot_fx2.h"
+#endif // IVAS_FLOAT_FIXED
/*-------------------------------------------------------------------*
@@ -1851,13 +1855,22 @@ ivas_error ivas_init_decoder(
}
}
- IF ( ( error = ivas_create_lfe_dec( &st_ivas->hLFE, output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK )
+#ifdef IVAS_FLOAT_FIXED_TEST
+ IF( ( error = ivas_create_lfe_dec_fx( &st_ivas->hLFE, output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK )
+#else
+ IF( ( error = ivas_create_lfe_dec( &st_ivas->hLFE, output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK )
+#endif // IVAS_FLOAT_FIXED
{
return error;
}
set_zero( st_ivas->hLFE->prevsynth_buf, LFE_PLC_BUFLEN );
set_zero( st_ivas->hLFE->prior_out_buffer, L_FRAME48k );
+#ifdef IVAS_FLOAT_FIXED
+ set32_fx(st_ivas->hLFE->prevsynth_buf_fx,0, LFE_PLC_BUFLEN);
+ set32_fx(st_ivas->hLFE->prior_out_buffer_fx,0, L_FRAME48k);
+#endif // IVAS_FLOAT_FIXED
+
}
/*-----------------------------------------------------------------*
@@ -2312,7 +2325,11 @@ void ivas_destroy_dec(
ivas_mct_dec_close( &st_ivas->hMCT );
/* LFE handle */
+#ifdef IVAS_FLOAT_FIXED_TEST
+ ivas_lfe_dec_close_fx( &( st_ivas->hLFE ) );
+#else
ivas_lfe_dec_close( &( st_ivas->hLFE ) );
+#endif // IVAS_FLOAT_FIXED
/* Param-Upmix MC handle */
ivas_mc_paramupmix_dec_close( &( st_ivas->hMCParamUpmix ) );
diff --git a/lib_dec/ivas_jbm_dec.c b/lib_dec/ivas_jbm_dec.c
index 3c7387b429dbbae328ba346a28d6ece0abd8de2a..9e2080f9082fa997a8a22d195c616afdabd04ad1 100644
--- a/lib_dec/ivas_jbm_dec.c
+++ b/lib_dec/ivas_jbm_dec.c
@@ -601,7 +601,21 @@ ivas_error ivas_jbm_dec_tc(
if ( st_ivas->mc_mode == MC_MODE_MCT )
{
/* LFE channel decoder */
+#ifdef IVAS_FLOAT_FIXED_TEST
+ Word32 *p_output_fx;
+
+ p_output_fx = (Word32 *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) );
+
+ ivas_lfe_dec_fx( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output_fx );
+
+ for ( int p = 0; p < 960; p++ )
+ {
+ p_output[LFE_CHANNEL][p] = (float) p_output_fx[p] / ONE_IN_Q9;
+ }
+ free( p_output_fx );
+#else
ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output[LFE_CHANNEL] );
+#endif // IVAS_FLOAT_FIXED
if ( ( error = ivas_mct_dec( st_ivas, p_output, output_frame, 0 ) ) != IVAS_ERR_OK )
{
@@ -640,7 +654,21 @@ ivas_error ivas_jbm_dec_tc(
else if ( st_ivas->mc_mode == MC_MODE_PARAMUPMIX )
{
/* LFE channel decoder */
+#ifdef IVAS_FLOAT_FIXED_TEST
+ Word32 *p_output_fx;
+
+ p_output_fx = (Word32 *) malloc( ( 48000 / FRAMES_PER_SEC ) * sizeof( Word32 ) );
+
+ ivas_lfe_dec_fx( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output_fx );
+
+ for ( int p = 0; p < 960; p++ )
+ {
+ p_output[LFE_CHANNEL][p] = (float) p_output_fx[p] / ONE_IN_Q9;
+ }
+ free( p_output_fx );
+#else
ivas_lfe_dec( st_ivas->hLFE, st, output_frame, st_ivas->bfi, p_output[LFE_CHANNEL] );
+#endif // IVAS_FLOAT_FIXED
ivas_mc_paramupmix_dec_read_BS( st_ivas, st, st_ivas->hMCParamUpmix, &nb_bits_metadata[0] );
diff --git a/lib_dec/ivas_lfe_dec_fx.c b/lib_dec/ivas_lfe_dec_fx.c
new file mode 100644
index 0000000000000000000000000000000000000000..694c68d98b4483ff3c44d39350935ce4b22e2df7
--- /dev/null
+++ b/lib_dec/ivas_lfe_dec_fx.c
@@ -0,0 +1,503 @@
+/******************************************************************************************************
+
+ (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 "options.h"
+#ifdef IVAS_FLOAT_FIXED
+#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 "rom_com.h"
+#include "math.h"
+#include "wmc_auto.h"
+
+
+/*------------------------------------------------------------------------------------------*
+ * Local constants
+ *------------------------------------------------------------------------------------------*/
+
+/* Delay handling of LFE: overall_lfe_delay = max(11.5, BLOCK_OFFSET_MS); */
+#define BLOCK_OFFSET_MS 12
+#define BLOCK_OFFSET_S_Q15 393
+
+
+/*-----------------------------------------------------------------------------------------*
+ * Function ivas_lfe_dec_delay_adjust_fx()
+ *
+ * Adjusts the input to be passed to filtering block taking into consideration
+ * LFE delay calculated during initialization time
+ *-----------------------------------------------------------------------------------------*/
+
+static void ivas_lfe_dec_delay_adjust_fx(
+ LFE_DEC_HANDLE hLFE,
+ Word32 *pInbuf,
+ Word32 output_lfe_ch[] )
+{
+ Word16 i, diff, loop_counter;
+ Word16 fade_len, dct_len, zero_pad_len;
+ Word32 tmp_buffer[L_FRAME48k];
+
+ diff = sub( hLFE->lfe_prior_buf_len, hLFE->pWindow_state->fade_len );
+ loop_counter = LT_16( diff, 0 ) ? 0 : diff;
+ fade_len = hLFE->pWindow_state->fade_len;
+ dct_len = hLFE->pWindow_state->dct_len;
+ zero_pad_len = hLFE->pWindow_state->zero_pad_len;
+
+ FOR( i = 0; i < loop_counter; i++ )
+ {
+ tmp_buffer[i] = hLFE->prior_out_buffer_fx[i];
+ }
+
+ FOR( i = 0; i < fade_len; i++ )
+ {
+ tmp_buffer[i + loop_counter] = L_add( hLFE->prior_out_buffer_fx[i + loop_counter], pInbuf[i] );
+ }
+ loop_counter = add( loop_counter, fade_len );
+
+ FOR( i = 0; i < add( fade_len, shl( zero_pad_len, 1 ) ); i++ )
+ {
+ tmp_buffer[i + loop_counter] = pInbuf[i + fade_len];
+ }
+
+ FOR( i = 0; i < hLFE->lfe_prior_buf_len; i++ )
+ {
+ hLFE->prior_out_buffer_fx[i] = tmp_buffer[i + dct_len];
+ }
+
+ FOR( i = 0; i < dct_len; i++ )
+ {
+ output_lfe_ch[i] = tmp_buffer[i];
+ }
+
+ return;
+}
+
+
+/*-----------------------------------------------------------------------------------------*
+ * Function ivas_lfe_dec_windowing_fx()
+ *
+ * LFE windowing block, input is passed through Fielder window
+ *-----------------------------------------------------------------------------------------*/
+
+static void ivas_lfe_dec_windowing_fx(
+ LFE_DEC_HANDLE hLFE,
+ Word32 *pInbuf )
+{
+ Word16 i;
+ Word16 fade_len;
+ Word16 zero_pad_len;
+ const Word32 *pWindow_coeffs;
+
+ fade_len = hLFE->pWindow_state->fade_len;
+ zero_pad_len = hLFE->pWindow_state->zero_pad_len;
+ pWindow_coeffs = hLFE->pWindow_state->pWindow_coeffs_fx;
+
+ FOR( i = 0; i < fade_len; i++ )
+ {
+ pInbuf[i] = Mpy_32_32( pInbuf[add( zero_pad_len, i )], pWindow_coeffs[i] );
+ }
+
+ FOR( i = 0; i < shl( zero_pad_len, 2 ); i++ )
+ {
+ pInbuf[add( fade_len, i )] = pInbuf[add( add( zero_pad_len, fade_len ), i )];
+ }
+
+ FOR( i = 0; i < fade_len; i++ )
+ {
+ pInbuf[add( add( shl( zero_pad_len, 2 ), fade_len ), i )] = Mpy_32_32( pInbuf[add( add( i_mult( zero_pad_len, 3 ), fade_len ), i )], pWindow_coeffs[sub( sub( fade_len, i ), 1 )] );
+ }
+
+ return;
+}
+
+
+/*-----------------------------------------------------------------------------------------*
+ * Function ivas_lfe_dec_dequant_fx()
+ *
+ * LDE de-quatization block, calls arithmetic deccoding block inside
+ *-----------------------------------------------------------------------------------------*/
+
+static Word16 ivas_lfe_dec_dequant_fx(
+ LFE_DEC_HANDLE hLFE,
+ Decoder_State *st0,
+ Word32 *pOut_buf,
+ Word16 *num_dct_pass_bins )
+{
+ Word16 shift_bits, i;
+ Word16 quant_strategy;
+ Word16 coding_strategy;
+ Word16 base2_bit_size;
+ Word16 lfe_bits;
+ Word16 all_zeros_dct;
+ Word16 min_shift_bits;
+ Word16 shift;
+ Word16 sign_bits[IVAS_LFE_MAX_NUM_DCT_COEFFS];
+ Word16 abs_values[IVAS_LFE_MAX_NUM_DCT_COEFFS];
+ Word16 values[IVAS_LFE_MAX_NUM_DCT_COEFFS];
+ Word16 num_dct_coeffs, num_groups;
+
+ all_zeros_dct = get_next_indice( st0, 1 );
+ lfe_bits = st0->next_bit_pos;
+ shift_bits = IVAS_LFE_SHIFT_BITS;
+ min_shift_bits = 0;
+ shift = 0;
+
+ IF( EQ_16( all_zeros_dct, 1 ) )
+ {
+ FOR( i = 0; i < IVAS_LFE_MAX_NUM_DCT_COEFFS; i++ )
+ {
+ pOut_buf[i] = 0;
+ }
+ }
+ ELSE
+ {
+ Word32 two_pow_shift_by_4;
+ Tastat as;
+ Word16 iii, extra_bits_read;
+
+ extra_bits_read = 0;
+ quant_strategy = get_next_indice( st0, 1 );
+ *num_dct_pass_bins = ivas_lfe_num_dct_pass_bins_tbl[quant_strategy];
+ num_dct_coeffs = shl( *num_dct_pass_bins, 1 );
+ num_groups = shr( num_dct_coeffs, 2 );
+ min_shift_bits = ivas_lfe_min_shift_tbl[quant_strategy];
+ shift = add( get_next_indice( st0, shift_bits ), shl( min_shift_bits, 2 ) );
+
+ FOR( i = 0; i < num_dct_coeffs; i++ )
+ {
+ sign_bits[i] = get_next_indice( st0, 1 );
+ }
+
+ coding_strategy = get_next_indice( st0, 1 );
+
+ IF( coding_strategy )
+ {
+ FOR( iii = 0; iii < num_groups; iii++ )
+ {
+ base2_bit_size = hLFE->lfe_dec_indices_coeffs_tbl[quant_strategy][iii];
+ FOR( i = 0; i < 4; i++ )
+ {
+ abs_values[iii * 4 + i] = get_next_indice( st0, base2_bit_size );
+ }
+ }
+ }
+ ELSE
+ {
+ FOR( iii = 0; iii < num_groups; iii++ )
+ {
+ extra_bits_read = 0;
+ ivas_ari_start_decoding_14bits_ext_1_lfe( st0, &as, &extra_bits_read );
+
+ FOR( i = 0; i < 4; i++ )
+ {
+ abs_values[iii * 4 + i] = ivas_ari_decode_14bits_bit_ext_1_lfe( st0, &as, hLFE->cum_freq_models[quant_strategy][iii], &extra_bits_read );
+ }
+ ivas_ari_done_decoding_14bits_ext_1_lfe( st0, extra_bits_read );
+ }
+ }
+
+ FOR( i = 0; i < num_dct_coeffs; i++ )
+ {
+ values[i] = shl( abs_values[i], 9 ); // Q9
+ IF( GT_16( sign_bits[i], 0 ) )
+ {
+ values[i] = shl( sub( negate( abs_values[i] ), 1 ), 9 ); // Q9
+ }
+ }
+
+ two_pow_shift_by_4 = tbl_two_pow_shift_by_4[shift];
+
+ FOR( i = 0; i < num_groups; i++ )
+ {
+ pOut_buf[2 * i] = Mpy_32_16_1( two_pow_shift_by_4, values[4 * i] ); // Q30 + Q9 >> 15 = Q24
+ pOut_buf[2 * i + 1] = Mpy_32_16_1( two_pow_shift_by_4, values[4 * i + 1] ); // Q30 + Q9 >> 15 = Q24
+
+ pOut_buf[2 * i + *num_dct_pass_bins] = Mpy_32_16_1( two_pow_shift_by_4, values[4 * i + 2] ); // Q30 + Q9 >> 15 = Q24
+ pOut_buf[2 * i + *num_dct_pass_bins + 1] = Mpy_32_16_1( two_pow_shift_by_4, values[4 * i + 3] ); // Q30 + Q9 >> 15 = Q24
+ }
+ }
+
+ lfe_bits = sub( st0->next_bit_pos, lfe_bits );
+
+ return lfe_bits;
+}
+
+
+/*-----------------------------------------------------------------------------------------*
+ * Function ivas_lfe_dec_fx()
+ *
+ * LFE channel decoder
+ *-----------------------------------------------------------------------------------------*/
+
+void ivas_lfe_dec_fx(
+ LFE_DEC_HANDLE hLFE, /* i/o: LFE decoder handle */
+ Decoder_State *st0, /* i/o: decoder state structure - for bitstream handling*/
+ const Word16 output_frame, /* i : output frame length per channel */
+ const Word16 bfi, /* i : BFI flag */
+ Word32 output_lfe_ch[] /* o : output LFE synthesis */
+)
+{
+ Word16 num_dct_pass_bins;
+ Word16 i, j, dct_len, q_out = 0;
+ Word32 out[L_FRAME48k];
+ Word32 t_audio[L_FRAME48k];
+ Word32 lfe_dct[IVAS_LFE_MAX_NUM_DCT_COEFFS];
+
+ dct_len = hLFE->pWindow_state->dct_len;
+ num_dct_pass_bins = IVAS_LFE_MAX_NUM_DCT_PASS_BINS;
+
+ IF( EQ_16( bfi, 0 ) )
+ {
+ ivas_lfe_dec_dequant_fx( hLFE, st0, lfe_dct, &num_dct_pass_bins ); // Q24
+
+ set32_fx( t_audio, 0, dct_len );
+ Copy32( lfe_dct, t_audio, num_dct_pass_bins ); // Q24
+ q_out = Q24;
+ ivas_imdct_fx( t_audio, out, dct_len, &q_out ); // Q9
+ ivas_lfe_dec_windowing_fx( hLFE, out ); // Q9
+ ivas_lfe_dec_delay_adjust_fx( hLFE, out, output_lfe_ch ); // Q9
+
+ set32_fx( t_audio, 0, dct_len );
+ Copy32( &lfe_dct[num_dct_pass_bins], t_audio, num_dct_pass_bins ); // Q24
+ q_out = Q24;
+ ivas_imdct_fx( t_audio, out, dct_len, &q_out ); // Q9
+ ivas_lfe_dec_windowing_fx( hLFE, out ); // Q9
+ ivas_lfe_dec_delay_adjust_fx( hLFE, out, output_lfe_ch + dct_len ); // Q9
+
+ Copy32( hLFE->prevsynth_buf_fx + L_FRAME_1k6, hLFE->prevsynth_buf_fx, LFE_PLC_BUFLEN - L_FRAME_1k6 );
+
+ j = 0;
+ FOR( i = 0; i < L_FRAME_1k6; i++ )
+ {
+ hLFE->prevsynth_buf_fx[i + LFE_PLC_BUFLEN - L_FRAME_1k6] = output_lfe_ch[j];
+ j = add( j, shr( output_frame, 5 ) );
+ }
+
+ hLFE->bfi_count = 0;
+ }
+ ELSE
+ {
+ /* note: in BFI branch, buffer 't_audio' is in time-domain ('wtda' signal) */
+ hLFE->bfi_count++;
+#ifdef IVAS_FLOAT_FIXED_TBD
+ ivas_lfe_tdplc_fx( hLFE, hLFE->prevsynth_buf, t_audio, output_frame );
+#else
+ float t_audio_flt[L_FRAME48k];
+ FOR( int k = 0; k < 240; k++ )
+ {
+
+ hLFE->prevsynth_buf[k] = (float) hLFE->prevsynth_buf_fx[k] / ONE_IN_Q9;
+ }
+
+ ivas_lfe_tdplc( hLFE, hLFE->prevsynth_buf, t_audio_flt, output_frame );
+
+ FOR( int k = 0; k < 960; k++ )
+ {
+ if ( k < 240 )
+ {
+ hLFE->prevsynth_buf_fx[k] = (Word32) ( hLFE->prevsynth_buf[k] * ONE_IN_Q9 );
+ }
+ t_audio[k] = (Word32) ( t_audio_flt[k] * ONE_IN_Q9 );
+ }
+#endif // IVAS_FLOAT_FIXED_TBD
+
+ ivas_itda_fx( t_audio, out, dct_len );
+ ivas_lfe_dec_windowing_fx( hLFE, out );
+ ivas_lfe_dec_delay_adjust_fx( hLFE, out, output_lfe_ch );
+
+ ivas_itda_fx( t_audio + dct_len, out, dct_len );
+ ivas_lfe_dec_windowing_fx( hLFE, out );
+ ivas_lfe_dec_delay_adjust_fx( hLFE, out, output_lfe_ch + dct_len );
+
+ Copy32( hLFE->prevsynth_buf_fx + L_FRAME_1k6, hLFE->prevsynth_buf_fx, LFE_PLC_BUFLEN - L_FRAME_1k6 );
+
+ j = 0;
+ FOR( i = 0; i < L_FRAME_1k6; i++ )
+ {
+ hLFE->prevsynth_buf_fx[i + LFE_PLC_BUFLEN - L_FRAME_1k6] = output_lfe_ch[j];
+ j = add( j, shr( output_frame, 5 ) );
+ }
+ }
+
+ IF( GT_16( hLFE->filter_state.order, 0 ) )
+ {
+ /* NOTE: this block is not getting hit by any stream present in pytest test suite */
+ /* Low Pass Filter */
+ ivas_filter_process_fx( &hLFE->filter_state, output_lfe_ch, output_frame, q_out );
+ }
+
+ /* add delay to make overall max(block_offset, 11.5) */
+ IF( GT_16( hLFE->lfe_addl_delay, 0 ) )
+ {
+ delay_signal_fx( output_lfe_ch, output_frame, hLFE->lfe_delay_buf_fx, hLFE->lfe_addl_delay );
+ }
+
+ return;
+}
+
+
+/*-------------------------------------------------------------------------
+ * ivas_create_lfe_dec()
+ *
+ * Create, allocate and initialize IVAS decoder LFE handle
+ *-------------------------------------------------------------------------*/
+
+ivas_error ivas_create_lfe_dec_fx(
+ LFE_DEC_HANDLE *hLFE_out, /* o : IVAS LFE decoder structure */
+ const Word32 output_Fs, /* i : output sampling rate */
+ const Word32 binauralization_delay_ns /* i : additional LFE delay to sync with binaural renderer */
+)
+{
+ Word16 low_pass_delay_dec_out, block_offset_s;
+ Word16 filt_order, output_frame;
+ LFE_DEC_HANDLE hLFE;
+ Word16 lfe_addl_delay_s;
+ Word16 i, j;
+ Word16 add_delay_sa;
+ Word32 output_fs_fx;
+
+ low_pass_delay_dec_out = 0;
+ block_offset_s = 0;
+
+ output_frame = extract_l(Mpy_32_16_1( output_Fs, INV_FRAME_PER_SEC_Q15 ));
+
+ /*-----------------------------------------------------------------*
+ * Allocate LFE handle
+ *-----------------------------------------------------------------*/
+
+ IF( ( hLFE = (LFE_DEC_HANDLE) malloc( sizeof( LFE_DEC_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE\n" ) );
+ }
+
+ /*-----------------------------------------------------------------*
+ * LFE Window: allocate and initialize
+ *-----------------------------------------------------------------*/
+
+ IF( ( hLFE->pWindow_state = (LFE_WINDOW_HANDLE) malloc( sizeof( LFE_WINDOW_DATA ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE window structure\n" ) );
+ }
+
+ ivas_lfe_window_init( hLFE->pWindow_state, output_Fs, output_frame );
+
+ /* Initialization for entropy coding */
+ hLFE->cum_freq_models[0][0] = ivas_str_lfe_freq_models.entropy_coder_model_fine_sg1;
+ hLFE->cum_freq_models[0][1] = ivas_str_lfe_freq_models.entropy_coder_model_fine_sg2;
+ hLFE->cum_freq_models[0][2] = ivas_str_lfe_freq_models.entropy_coder_model_fine_sg3;
+ hLFE->cum_freq_models[0][3] = ivas_str_lfe_freq_models.entropy_coder_model_fine_sg4;
+ hLFE->cum_freq_models[1][0] = ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg1;
+ hLFE->cum_freq_models[1][1] = ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg2;
+ hLFE->cum_freq_models[1][2] = ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg3;
+ hLFE->cum_freq_models[1][3] = &ivas_str_lfe_freq_models.entropy_coder_model_coarse_sg4;
+
+ /* delay calculation */
+ hLFE->lfe_block_delay_s_fx = ( IVAS_LFE_FADE_S_Q15 ) + ivas_lfe_lpf_delay_Q15[IVAS_FILTER_ORDER_4 - 3];
+
+ block_offset_s = BLOCK_OFFSET_S_Q15;
+ filt_order = 0;
+ low_pass_delay_dec_out = 0;
+ hLFE->filter_state.order = filt_order;
+ hLFE->lfe_block_delay_s_fx = hLFE->lfe_block_delay_s_fx + low_pass_delay_dec_out;
+ hLFE->lfe_prior_buf_len = NS2SA_fx2( output_Fs, IVAS_LFE_FADE_NS );
+
+ hLFE->bfi_count = 0;
+
+ output_fs_fx = NE_32( output_Fs, 48000 ) ? ( NE_32( output_Fs, 32000 ) ? FS_16K_IN_NS_Q31 : FS_32K_IN_NS_Q31 ) : FS_48K_IN_NS_Q31;
+
+ lfe_addl_delay_s = block_offset_s - hLFE->lfe_block_delay_s_fx;
+ lfe_addl_delay_s = s_max( 0, lfe_addl_delay_s );
+ add_delay_sa = (Word16) W_round64_L( W_mult0_32_32( L_shl( binauralization_delay_ns, 1 ), output_fs_fx ) );
+ hLFE->lfe_addl_delay = add( (Word16) L_shr( ( (Word32) lfe_addl_delay_s * (Word32) output_Fs ), 15 ), add_delay_sa );
+ hLFE->lfe_block_delay_s_fx = add(hLFE->lfe_block_delay_s_fx, add( lfe_addl_delay_s, add_delay_sa / output_Fs ));
+
+ IF( GT_16( hLFE->lfe_addl_delay, 0 ) )
+ {
+ IF( ( hLFE->lfe_delay_buf_fx = (Word32 *) malloc( hLFE->lfe_addl_delay * sizeof( Word32 ) ) ) == NULL )
+ {
+ return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for LFE additional delay buffer\n" ) );
+ }
+ set32_fx( (Word32 *) hLFE->lfe_delay_buf_fx, 0, hLFE->lfe_addl_delay );
+ }
+ ELSE
+ {
+ hLFE->lfe_delay_buf_fx = NULL;
+ }
+
+ /* Initialization base2 bits for each subgroup for no entropy coding */
+ FOR( i = 0; i < IVAS_MAX_NUM_QUANT_STRATS; i++ )
+ {
+ FOR( j = 0; j < IVAS_MAX_NUM_DCT_COEF_GROUPS; j++ )
+ {
+ hLFE->lfe_dec_indices_coeffs_tbl[i][j] = ivas_lfe_log2_num_ele_in_coder_models_fx[i][j];
+ }
+ }
+
+ *hLFE_out = hLFE;
+
+ return IVAS_ERR_OK;
+}
+
+
+/*-------------------------------------------------------------------------
+ * ivas_lfe_dec_close_fx()
+ *
+ * Destroy IVAS decoder LFE handle
+ *-------------------------------------------------------------------------*/
+
+void ivas_lfe_dec_close_fx(
+ LFE_DEC_HANDLE *hLFE /* i/o: LFE decoder handle */
+)
+{
+ IF( hLFE == NULL || *hLFE == NULL )
+ {
+ return;
+ }
+
+ free( ( *hLFE )->pWindow_state );
+ ( *hLFE )->pWindow_state = NULL;
+
+ IF( ( *hLFE )->lfe_delay_buf_fx != NULL )
+ {
+ free( ( *hLFE )->lfe_delay_buf_fx );
+ ( *hLFE )->lfe_delay_buf_fx = NULL;
+ }
+
+ free( ( *hLFE ) );
+ ( *hLFE ) = NULL;
+
+ return;
+}
+#endif // IVAS_FLOAT_FIXED
diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c
index 91e1dacb17ba8cb1a60a652331def988703aef22..0c819eaad9238a409b0948c700a70dcd61689f1a 100644
--- a/lib_dec/ivas_mct_dec.c
+++ b/lib_dec/ivas_mct_dec.c
@@ -46,7 +46,8 @@
#ifdef IVAS_FLOAT_FIXED
#include "prot_fx1.h"
#include "prot_fx2.h"
-#endif
+#endif // IVAS_FLOAT_FIXED
+
/*-----------------------------------------------------------------------*
* Local function prototypes
@@ -1016,7 +1017,11 @@ static ivas_error ivas_mc_dec_reconfig(
}
/* LFE handle */
+#ifdef IVAS_FLOAT_FIXED_TEST
+ ivas_lfe_dec_close_fx( &( st_ivas->hLFE ) );
+#else
ivas_lfe_dec_close( &( st_ivas->hLFE ) );
+#endif // IVAS_FLOAT_FIXED
}
else if ( st_ivas->mc_mode == MC_MODE_MCMASA )
{
@@ -1055,7 +1060,11 @@ static ivas_error ivas_mc_dec_reconfig(
}
/* LFE handle */
+#ifdef IVAS_FLOAT_FIXED_TEST
+ ivas_lfe_dec_close_fx( &( st_ivas->hLFE ) );
+#else
ivas_lfe_dec_close( &( st_ivas->hLFE ) );
+#endif // IVAS_FLOAT_FIXED
}
if ( st_ivas->mc_mode != MC_MODE_MCMASA )
@@ -1195,13 +1204,21 @@ static ivas_error ivas_mc_dec_reconfig(
}
}
+#ifdef IVAS_FLOAT_FIXED_TEST
+ if ( ( error = ivas_create_lfe_dec_fx( &st_ivas->hLFE, st_ivas->hDecoderConfig->output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK )
+#else
if ( ( error = ivas_create_lfe_dec( &st_ivas->hLFE, st_ivas->hDecoderConfig->output_Fs, binauralization_delay_ns ) ) != IVAS_ERR_OK )
+#endif // IVAS_FLOAT_FIXED
{
return error;
}
set_zero( st_ivas->hLFE->prevsynth_buf, LFE_PLC_BUFLEN );
set_zero( st_ivas->hLFE->prior_out_buffer, L_FRAME48k );
+#ifdef IVAS_FLOAT_FIXED
+ set32_fx(st_ivas->hLFE->prevsynth_buf_fx, 0, LFE_PLC_BUFLEN);
+ set32_fx(st_ivas->hLFE->prior_out_buffer_fx, 0, L_FRAME48k);
+#endif // IVAS_FLOAT_FIXED
}
/*-----------------------------------------------------------------*
diff --git a/lib_dec/ivas_stat_dec.h b/lib_dec/ivas_stat_dec.h
index 46faa1a1590d2adefeda8993f83938fc0e213aa6..f0a8b1809bfc4ccb3e93ca84812313bd4319b1af 100644
--- a/lib_dec/ivas_stat_dec.h
+++ b/lib_dec/ivas_stat_dec.h
@@ -842,6 +842,12 @@ typedef struct ivas_lfe_dec_data_structure
float prevsynth_buf[LFE_PLC_BUFLEN];
float *lfe_delay_buf;
+#ifdef IVAS_FLOAT_FIXED
+ Word16 lfe_block_delay_s_fx;
+ Word32 prior_out_buffer_fx[L_FRAME48k];
+ Word32 prevsynth_buf_fx[LFE_PLC_BUFLEN];
+ Word32 *lfe_delay_buf_fx;
+#endif // IVAS_FLOAT_FIXED
int16_t lfe_addl_delay;
int16_t bfi_count;