From afd282aa8f4ea373ee107a1e97124088fac24a14 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Wed, 24 Jan 2024 12:55:25 +0530 Subject: [PATCH] Functions in ivas_lfe_dec.c converted to fixed point. [x] All the functions in ivas_lfe_dec.c converted to fixed point. --- Workspace_msvc/lib_dec.vcxproj | 1 + Workspace_msvc/lib_dec.vcxproj.filters | 3 + lib_com/ivas_cnst.h | 1 + lib_com/ivas_prot_fx.h | 26 ++ lib_com/ivas_rom_com.c | 6 + lib_com/ivas_rom_com.h | 2 + lib_com/prot_fx1.h | 7 + lib_com/rom_com.c | 8 + lib_com/rom_com.h | 3 + lib_com/tools_fx.c | 22 ++ lib_dec/ivas_init_dec.c | 19 +- lib_dec/ivas_jbm_dec.c | 28 ++ lib_dec/ivas_lfe_dec_fx.c | 503 +++++++++++++++++++++++++ lib_dec/ivas_mct_dec.c | 19 +- lib_dec/ivas_stat_dec.h | 6 + 15 files changed, 652 insertions(+), 2 deletions(-) create mode 100644 lib_dec/ivas_lfe_dec_fx.c diff --git a/Workspace_msvc/lib_dec.vcxproj b/Workspace_msvc/lib_dec.vcxproj index 8f4a7ba25..f4730d4bd 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 61337a076..094beaa56 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 aa3057070..b47dcb65a 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 a0f622c28..8dfa630f5 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 d472f79aa..9ce55d69c 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 8473de40f..e2f1b564e 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 8f69b205e..91b003e18 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 ef622eca1..290647252 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 75a304754..db63ef4f9 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 7343343d8..e05a662fb 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 74702e66f..92525bfd3 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 3c7387b42..9e2080f90 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 000000000..694c68d98 --- /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 91e1dacb1..0c819eaad 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 46faa1a15..f0a8b1809 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; -- GitLab