From ae7628b34b4f34553c67342ab9c13a17ac9e9a76 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Tue, 23 Jan 2024 19:12:14 +0530 Subject: [PATCH] Few functions in ivas_core_dec converted to fixed point. [x] Functions in ivas_core_dec, sub-functions and caller functions converted to fixed point. [x] Few helper functions and floating conversion code to be cleaned up once the call stack is complete. --- lib_com/core_com_config.c | 53 +---- lib_com/ivas_prot_fx.h | 29 +++ lib_com/ivas_sba_config.c | 2 +- lib_com/ivas_stereo_td_bit_alloc.c | 54 +++++ lib_com/prot.h | 8 +- lib_com/prot_fx2.h | 12 ++ lib_com/tools_fx.c | 21 ++ lib_dec/FEC_HQ_core.c | 87 +++++++- lib_dec/evs_dec.c | 105 ++++++++- lib_dec/init_dec.c | 3 + lib_dec/ivas_core_dec.c | 300 +++++++++++++++++++++++++- lib_dec/ivas_mct_dec.c | 106 ++++++++- lib_dec/ivas_stereo_cng_dec.c | 105 ++++++++- lib_dec/ivas_stereo_mdct_stereo_dec.c | 168 ++++++++++++++- lib_dec/stat_dec.h | 12 ++ 15 files changed, 1005 insertions(+), 60 deletions(-) diff --git a/lib_com/core_com_config.c b/lib_com/core_com_config.c index d490b44b4..baa056be7 100644 --- a/lib_com/core_com_config.c +++ b/lib_com/core_com_config.c @@ -477,6 +477,14 @@ Word16 getMdctWindowLength_fx( * * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word16 sr2fscale_fx( + const Word32 sr_core /* i : internal sampling rate */ +) +{ + return (Word16) ( ( FSCALE_DENOM * sr_core ) / 12800 ); +} +#endif int16_t sr2fscale( const int32_t sr_core /* i : internal sampling rate */ @@ -486,51 +494,6 @@ int16_t sr2fscale( return (int16_t) ( ( FSCALE_DENOM * sr_core ) / 12800 ); } -Word16 sr2fscale_fx( - const Word32 sr_core /* i : internal sampling rate */ -) -{ - Word16 fscale; - - SWITCH( sr_core ) - { - case 8000: - fscale = ( FSCALE_DENOM * 8000 ) / 12800; - move16(); - BREAK; - - case 12800: - fscale = FSCALE_DENOM; - move16(); - BREAK; - - case 16000: - fscale = ( FSCALE_DENOM * 16000 ) / 12800; - move16(); - BREAK; - - case 25600: - fscale = ( FSCALE_DENOM * 25600 ) / 12800; - move16(); - BREAK; - - case 32000: - fscale = ( FSCALE_DENOM * 32000 ) / 12800; - move16(); - BREAK; - - case 48000: - fscale = ( FSCALE_DENOM * 48000 ) / 12800; - move16(); - BREAK; - - default: - assert( 0 ); - fscale = 0; /* just to avoid compiler warning */ - BREAK; - } - return fscale; -} /*-------------------------------------------------------------------* * getCoreSamplerateMode2_flt() * diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 081f2ceb6..a0f622c28 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -489,4 +489,33 @@ void ivas_ism_metadata_sid_dec_fx( ISM_METADATA_HANDLE hIsmMeta[], /* i/o: ISM metadata handles */ Word16 nb_bits_metadata[] /* o : number of metadata bits */ ); + +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 */ + const Word16 pitch_buf_PCh[], /* i : primary channel pitch buffer */ + Word16 tdm_lspQ_PCh[], /* o : Q LSPs for primary channel */ + Word16 tdm_lsfQ_PCh[], /* o : Q LSFs for primary channel */ + Word16 tdm_Pri_pitch_buf[], /* o : pitch values for primary channel */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + const Word16 tdm_use_IAWB_Ave_lpc, /* i : flag to indicate the usage of mean inactive LP coefficients */ + Word16 Q_var ); + +void updateBuffersForDmxMdctStereo_fx( + CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ + const Word16 output_frame, /* i : output frame length */ + Word32 output0_fx[], /* i/o: decoder output */ + Word32 output1_fx[], /* i/o: decoder output */ + Word16 synth_fx[CPE_CHANNELS][L_FRAME48k] /* i/o: decoder synthesis */ +); + +void stereo_cng_compute_PScorr_fx( + Word32 output_fx0[], /* i : Output signal */ + Word32 output_fx1[], /* i : Output signal */ + Word16 output_Q, + Word32 *c_PS_LT_fx, /* i/o: Correlation */ + Word16 Q_c_PS_LT_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_sba_config.c b/lib_com/ivas_sba_config.c index 96f0be387..4f9ca5484 100644 --- a/lib_com/ivas_sba_config.c +++ b/lib_com/ivas_sba_config.c @@ -225,7 +225,7 @@ Word16 ivas_sba_get_order_fx( } ELSE { - sba_order = sub( Sqrt16( nb_channels, &exp ), ONE_IN_Q15 ); // 15 - exp + sba_order = sub( Sqrt16( nb_channels, &exp ), MAX16B); // 15 - exp assert( ( EQ_16( mult( add( sba_order, 1 ), add( sba_order, 1 ) ), nb_channels ) ) && "Number of channels not supported in SBA!" ); } diff --git a/lib_com/ivas_stereo_td_bit_alloc.c b/lib_com/ivas_stereo_td_bit_alloc.c index 35bfe9046..e7db2b48b 100644 --- a/lib_com/ivas_stereo_td_bit_alloc.c +++ b/lib_com/ivas_stereo_td_bit_alloc.c @@ -40,6 +40,9 @@ #include "ivas_cnst.h" #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#endif /*-------------------------------------------------------------------* @@ -484,7 +487,58 @@ void td_stereo_param_updt( return; } +#ifdef IVAS_FLOAT_FIXED + +void td_stereo_param_updt_fx( + const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15*/ + const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qx2.56*/ + const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q_var*/ + Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15*/ + Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qx2.56*/ + Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q_var */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + const Word16 tdm_use_IAWB_Ave_lpc, /* i : flag to indicate the usage of mean inactive LP coefficients */ + Word16 Q_var ) +{ + Word16 i; + /* Copy some primary channel information into the secondary channel structure for later usage */ + IF( tdm_use_IAWB_Ave_lpc == 1 ) + { + /*not being assert*/ + Copy( IAWB_Ave_fx, tdm_lsfQ_PCh_fx, M ); + lsf2lsp_fx( tdm_lsfQ_PCh_fx, tdm_lspQ_PCh_fx, M, INT_FS_12k8 ); + } + ELSE IF( flag_ACELP16k == 1 ) + { + Copy( lsp_old_PCh_fx, tdm_lspQ_PCh_fx, M ); + lsp_convert_poly_fx( tdm_lspQ_PCh_fx, L_FRAME, 0 ); + lsp2lsf_fx( tdm_lspQ_PCh_fx, tdm_lsfQ_PCh_fx, M, INT_FS_12k8 ); + } + ELSE + { + Copy( lsp_old_PCh_fx, tdm_lspQ_PCh_fx, M ); + Copy( lsf_old_PCh_fx, tdm_lsfQ_PCh_fx, M ); + } + + /* This is only to keep the buffer up-to-date */ + Word16 mult_factor = float_to_fix16( 0.8f, 15 ); + IF( flag_ACELP16k == 1 ) + { + FOR( i = 0; i < NB_SUBFR; i++ ) + { + tdm_Pri_pitch_buf_fx[i] = mult( pitch_buf_PCh_fx[i], mult_factor ); + tdm_Pri_pitch_buf_fx[i] = max( tdm_Pri_pitch_buf_fx[i], float_to_fix16( PIT_MIN, Q_var ) ); + } + } + ELSE + { + Copy( pitch_buf_PCh_fx, tdm_Pri_pitch_buf_fx, NB_SUBFR ); + } + + return; +} +#endif /*-------------------------------------------------------------------* * tdm_SCh_LSF_intra_pred_zero_bits() * diff --git a/lib_com/prot.h b/lib_com/prot.h index eb6702340..4e1a189b6 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -9752,11 +9752,15 @@ int16_t getRestrictedMode( int16_t getMdctWindowLength( const int16_t fscale ); - +#ifdef IVAS_FLOAT_FIXED +Word16 sr2fscale( + const Word32 sr_core /* i : internal sampling rate */ +); +#else int16_t sr2fscale( const int32_t sr_core /* i : internal sampling rate */ ); - +#endif int32_t getCoreSamplerateMode2_flt( const int16_t element_mode, /* i : IVAS element mode */ const int32_t total_brate, /* i : total bitrate */ diff --git a/lib_com/prot_fx2.h b/lib_com/prot_fx2.h index 82d5afa61..54d1e312f 100644 --- a/lib_com/prot_fx2.h +++ b/lib_com/prot_fx2.h @@ -100,6 +100,11 @@ void f2me_buf_16(const float *x, Word16 *m, Word16 *e, const Word32 n); // 16-bit Mantissa Array and Exponent to Float void me2f_buf_16(const Word16 *m, const Word16 e, float *out, const Word32 n); +void f2fix_16(float *var_flt, Word16 *var_fix, Word32 expo); +void fix2f_16(Word16 *var_fix, float *var_flt, Word32 expo); +void f2fix(float *var_flt, Word32 *var_fix, Word32 expo); +void fix2f(Word32 *var_fix, float *var_flt, Word32 expo); + Word32 Mult_32_16( Word32 a, Word16 b); @@ -8115,4 +8120,11 @@ Word32 ism_dequant_meta_fx( const Word32 q_step_border_fx, /* i : quantization step at the border */ const Word16 cbsize /* i : codebook size */ ); + +void save_synthesis_hq_fec_fx( + Decoder_State *st, /* i/o: decoder state structure */ + const Word32 output_fx[], /* i : decoded synthesis */ + const Word16 output_frame, /* i : decoded synthesis */ + CPE_DEC_HANDLE hCPE /* i : CPE decoder structure */ +); #endif diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 0c02046c5..7343343d8 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -180,6 +180,27 @@ void me2f_buf_16( const Word16 *m, const Word16 e, float *out, const Word32 n ) out[i] = me2f_16( m[i], e ); } } +void f2fix( float *var_flt, Word32 *var_fix, Word32 expo ) +{ + *var_fix = (Word32) ( *var_flt * pow( 2, 31 - expo ) ); +} + +void fix2f( Word32 *var_fix, float *var_flt, Word32 expo ) +{ + float mf = fix_to_float( *var_fix, 31 ); + *var_flt = (float) ldexp( mf, expo ); +} + +void f2fix_16(float *var_flt, Word16 *var_fix, Word32 expo) +{ + *var_fix = (Word16)(*var_flt * pow(2, 15 - expo)); +} + +void fix2f_16(Word16 *var_fix, float *var_flt, Word32 expo) +{ + float mf = fix16_to_float(*var_fix, 15); + *var_flt = (float)ldexp(mf, expo); +} int16_t norm_ul(uint32_t UL_var1) { diff --git a/lib_dec/FEC_HQ_core.c b/lib_dec/FEC_HQ_core.c index edc1c2490..54fd2a326 100644 --- a/lib_dec/FEC_HQ_core.c +++ b/lib_dec/FEC_HQ_core.c @@ -42,7 +42,10 @@ #include "rom_com.h" #include "prot.h" #include "wmc_auto.h" - +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" +#endif /*---------------------------------------------------------------------* * Local prototypes *---------------------------------------------------------------------*/ @@ -1530,3 +1533,85 @@ void save_synthesis_hq_fec( return; } + +#ifdef IVAS_FLOAT_FIXED +void save_synthesis_hq_fec_fx( + Decoder_State *st, /* i/o: decoder state structure */ + const Word32 output_fx[], /* i : decoded synthesis */ + const Word16 output_frame, /* i : decoded synthesis */ + CPE_DEC_HANDLE hCPE /* i : CPE decoder structure */ +) +{ + Word16 post_hq_delay; + + SWITCH( st->element_mode ) + { + case EVS_MONO: + post_hq_delay = NS2SA( st->output_Fs, POST_HQ_DELAY_NS ); + BREAK; + case IVAS_SCE: + post_hq_delay = NS2SA( st->output_Fs, DELAY_CLDFB_NS ); + BREAK; + case IVAS_CPE_DFT: + IF( hCPE->nchan_out == 1 && hCPE->hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) + { + post_hq_delay = NS2SA( st->output_Fs, DELAY_CLDFB_NS ); + } + ELSE + { + post_hq_delay = 0; + } + BREAK; + default: + post_hq_delay = 0; + BREAK; + } + + IF( ( EQ_16( st->codec_mode, MODE1 ) && st->hTcxDec != NULL ) && ( ( EQ_16( st->core, ACELP_CORE ) && !( EQ_16( st->bfi, 1 ) && EQ_16( st->con_tcx, 1 ) ) ) || EQ_16( st->core, HQ_CORE ) ) ) + { + Copy( st->hTcxDec->synth_history_fx + output_frame, st->hTcxDec->synth_history_fx, output_frame - post_hq_delay + NS2SA( st->output_Fs, PH_ECU_MEM_NS ) ); + FOR (int i = 0; i < output_frame; i++) { + st->hTcxDec->old_synthFB_fx[i + output_frame - post_hq_delay] = extract_h(output_fx[i]); + } + + IF( EQ_16( st->element_mode, EVS_MONO ) ) + { + /* reset the remaining buffer, which is read in TCX concealment the necessary samples to fill + this buffer are not available for all cases, the impact on the output is limited */ + + set16_fx( st->hTcxDec->old_synthFB_fx + 2 * output_frame - post_hq_delay, 0, post_hq_delay ); + IF( GE_16( output_frame, L_FRAME16k ) ) + { + Copy( st->prev_synth_buffer_fx, st->hTcxDec->old_synthFB_fx + 2 * output_frame - NS2SA( st->output_Fs, DELAY_BWE_TOTAL_NS ), NS2SA( st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ) ); + } + ELSE + { + Copy( st->hHQ_core->old_out_fx + NS2SA( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + 2 * output_frame, NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ) ); + } + + IF( NE_16( st->core, ACELP_CORE ) ) + { + IF( GE_16( output_frame, L_FRAME16k ) ) + { + Copy( st->delay_buf_out_fx, st->hTcxDec->old_synthFB_fx + 2 * output_frame - NS2SA( st->output_Fs, DELAY_CLDFB_NS ), NS2SA( st->output_Fs, DELAY_CLDFB_NS ) ); + Copy( st->hHQ_core->old_out_fx + NS2SA( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + 2 * output_frame, NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ) ); + } + ELSE + { + Copy( st->delay_buf_out_fx, st->hTcxDec->old_synthFB_fx + 2 * output_frame - NS2SA( st->output_Fs, DELAY_BWE_TOTAL_NS ), NS2SA( st->output_Fs, DELAY_CLDFB_NS ) ); + Copy( st->hHQ_core->old_out_fx + NS2SA( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + 2 * output_frame - NS2SA( st->output_Fs, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ), NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ) ); + } + } + } + ELSE + { + IF( NE_16( st->core, ACELP_CORE ) ) + { + Copy( st->delay_buf_out_fx, st->hTcxDec->old_synthFB_fx + 2 * output_frame - post_hq_delay, post_hq_delay ); + Copy( st->hHQ_core->old_out_fx + NS2SA( st->output_Fs, N_ZERO_MDCT_NS ), st->hTcxDec->old_synthFB_fx + 2 * output_frame, NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ) ); + } + } + } + return; +} +#endif \ No newline at end of file diff --git a/lib_dec/evs_dec.c b/lib_dec/evs_dec.c index b882f8928..4313cece9 100644 --- a/lib_dec/evs_dec.c +++ b/lib_dec/evs_dec.c @@ -41,7 +41,10 @@ #include "rom_com.h" #include "prot.h" #include "wmc_auto.h" - +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" +#endif /*--------------------------------------------------------------------------* * evs_dec_flt() * @@ -897,8 +900,108 @@ ivas_error evs_dec_flt( /*----------------------------------------------------------------* * Save synthesis for HQ FEC *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + Word32 exp_max = 0; + Word32 output_fx[L_FRAME48k]; + if ( ( st->codec_mode == MODE1 && st->hTcxDec != NULL ) && ( ( st->core == ACELP_CORE && !( st->bfi == 1 && st->con_tcx == 1 ) ) || st->core == HQ_CORE ) ) + { + double max_prev_synth_buffer = 0.0f, max_old_out = 0.0f, max_delay_buf_out = 0.0f, max_ouput = 0.0f, max_synth_history = 0.0f; + Word32 exp_prev_synth_buffer = 0, exp_old_out = 0, exp_delay_buf_out = 0, exp_ouput = 0, exp_synth_history = 0; + + /*Find maximum values for all the buffers*/ + for ( i = 0; i < NS2SA( 48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ); i++ ) + { + max_prev_synth_buffer = max( max_prev_synth_buffer, fabs( st->prev_synth_buffer[i] ) ); + } + if ( (Word16) max_prev_synth_buffer != 0 ) + { + frexp( max_prev_synth_buffer, &exp_prev_synth_buffer ); + } + + for ( i = NS2SA( st->output_Fs, N_ZERO_MDCT_NS ); i < NS2SA( st->output_Fs, N_ZERO_MDCT_NS ) + NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ); i++ ) + { + max_old_out = max( max_old_out, fabs( st->hHQ_core->old_out[i] ) ); + } + if ( (Word16) max_old_out != 0 ) + { + frexp( max_old_out, &exp_old_out ); + } + + for ( i = 0; i < NS2SA( st->output_Fs, DELAY_CLDFB_NS ); i++ ) + { + max_delay_buf_out = max( max_delay_buf_out, fabs( st->delay_buf_out[i] ) ); + } + if ( (Word16) max_delay_buf_out != 0 ) + { + frexp( max_delay_buf_out, &exp_delay_buf_out ); + } + + for ( i = 0; i < output_frame; i++ ) + { + max_ouput = max( max_ouput, fabs( output[i] ) ); + } + if ( (Word16) max_ouput != 0 ) + { + frexp( max_ouput, &exp_ouput ); + } + + for ( i = output_frame; i < 2 * output_frame - NS2SA( st->output_Fs, DELAY_CLDFB_NS ) + NS2SA( st->output_Fs, PH_ECU_MEM_NS ); i++ ) + { + max_synth_history = max( max_synth_history, fabs( st->hTcxDec->synth_history[i] ) ); + } + + if ( (Word16) max_synth_history != 0 ) + { + frexp( max_synth_history, &exp_synth_history ); + } + + /*Find a commen maximum exp*/ + exp_max = max( exp_synth_history, exp_ouput ); + exp_max = max( exp_max, exp_prev_synth_buffer ); + exp_max = max( exp_max, exp_old_out ); + exp_max = max( exp_max, exp_delay_buf_out ); + for ( i = 0; i < NS2SA( st->output_Fs, DELAY_CLDFB_NS ); i++ ) + { + f2fix_16( &st->delay_buf_out[i], &st->delay_buf_out_fx[i], exp_max ); + } + for ( i = NS2SA( st->output_Fs, N_ZERO_MDCT_NS ); i < NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ); i++ ) + { + f2fix_16( &st->hHQ_core->old_out[i], &st->hHQ_core->old_out_fx[i], exp_max ); + } + for ( i = 0; i < NS2SA( 48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ); i++ ) + { + f2fix_16( &st->prev_synth_buffer[i], &st->prev_synth_buffer_fx[i], exp_max ); + } + for ( i = output_frame; i < 2 * output_frame - NS2SA( st->output_Fs, DELAY_CLDFB_NS ) + NS2SA( st->output_Fs, PH_ECU_MEM_NS ); i++ ) + { + f2fix_16( &st->hTcxDec->synth_history[i], &st->hTcxDec->synth_history_fx[i], exp_max ); + } + for ( i = 0; i < output_frame; i++ ) + { + f2fix( &output[i], &output_fx[i], exp_max ); + } + } + + save_synthesis_hq_fec_fx( st, output_fx, output_frame, NULL ); + + if ( ( st->codec_mode == MODE1 && st->hTcxDec != NULL ) && ( ( st->core == ACELP_CORE && !( st->bfi == 1 && st->con_tcx == 1 ) ) || st->core == HQ_CORE ) ) + { + /*dumps*/ + float track = 0; + for ( i = 0; i < 2 * output_frame; i++ ) + { + fix2f_16( &st->hTcxDec->synth_history_fx[i], &track, exp_max ); + fix2f_16( &st->hTcxDec->synth_history_fx[i], &st->hTcxDec->synth_history[i], exp_max ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( &track, 1, "Fixed_code_synth_history_fx.txt", NULL ); + dbgwrite_txt( &st->hTcxDec->synth_history[i], 1, "Float_code_synth_history_fx.txt", NULL ); +#endif + } + } +#else save_synthesis_hq_fec( st, output, output_frame, NULL ); +#endif /*----------------------------------------------------------------* * HP filtering diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c index 51098eb58..f4ad599f0 100644 --- a/lib_dec/init_dec.c +++ b/lib_dec/init_dec.c @@ -597,6 +597,9 @@ ivas_error init_decoder( set_f( st->hTcxDec->FBTCXdelayBuf_float, 0.0f, 111 ); st->hTcxDec->old_synthFB = st->hTcxDec->synth_history + NS2SA( st->output_Fs, PH_ECU_MEM_NS ); +#ifdef IVAS_FLOAT_FIXED + st->hTcxDec->old_synthFB_fx = st->hTcxDec->synth_history_fx + NS2SA( st->output_Fs, PH_ECU_MEM_NS ); +#endif st->hTcxDec->prev_good_synth = st->hTcxDec->old_synthFB + NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ); } else diff --git a/lib_dec/ivas_core_dec.c b/lib_dec/ivas_core_dec.c index 747dc755c..db2525a21 100644 --- a/lib_dec/ivas_core_dec.c +++ b/lib_dec/ivas_core_dec.c @@ -41,7 +41,11 @@ #include "ivas_prot_fx.h" #include "ivas_rom_com.h" #include "wmc_auto.h" - +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx2.h" +#include "prot_fx1.h" +#include "ivas_prot_fx.h" +#endif /*-------------------------------------------------------------------* * ivas_core_dec() @@ -367,7 +371,55 @@ ivas_error ivas_core_dec( if ( st->element_mode == IVAS_CPE_TD && n == 0 ) { +#ifdef IVAS_FLOAT_FIXED + /* To be cleaned up once the caller function is converted // These changes are for system testing of fixed changes made */ + Word16 lsp_old_PCh_fx[M], tdm_lspQ_PCh_fx[M]; + Word16 tdm_lsfQ_PCh_fx[M], lsf_old_PCh_fx[M]; + FOR( i = 0; i < M; i++ ) + { + lsp_old_PCh_fx[i] = float_to_fix16( st->lsp_old[i], 15 ); + lsf_old_PCh_fx[i] = (Word16) ( st->lsf_old[i] * 2.56f ); + tdm_lsfQ_PCh_fx[i] = (Word16) ( tdm_lsfQ_PCh[i] * 2.56f ); + } + + float max_val = 0; + Word16 tdm_Pri_pitch_buf_fx[NB_SUBFR], old_pitch_buf_fx[2 * NB_SUBFR16k + 2]; + + FOR( i = 0; i < 2 * NB_SUBFR16k + 2; i++ ) + { + max_val = max( st->old_pitch_buf[i], max_val ); + } + Word16 Q_var = norm_s( (Word16) max_val ); + + for ( i = 0; i < 2 * NB_SUBFR16k + 2; i++ ) + { + old_pitch_buf_fx[i] = float_to_fix16( st->old_pitch_buf[i], Q_var ); + } + td_stereo_param_updt_fx( lsp_old_PCh_fx, lsf_old_PCh_fx, old_pitch_buf_fx + st->nb_subfr, + tdm_lspQ_PCh_fx, tdm_lsfQ_PCh_fx, tdm_Pri_pitch_buf_fx, st->flag_ACELP16k, hStereoTD->tdm_use_IAWB_Ave_lpc, Q_var ); + for ( i = 0; i < M; i++ ) + { + tdm_lspQ_PCh[i] = fix16_to_float( tdm_lspQ_PCh_fx[i], 15 ); + tdm_lsfQ_PCh[i] = (float) tdm_lsfQ_PCh_fx[i] / 2.56f; + } + for ( i = 0; i < NB_SUBFR; i++ ) + { + hStereoTD->tdm_Pri_pitch_buf[i] = fix16_to_float( tdm_Pri_pitch_buf_fx[i], Q_var ); + } + +#ifdef DUMPS_ENABLED + dbgwrite_txt( tdm_lspQ_PCh, M, "Fixed_code_tdm_lspQ_PCh.txt", NULL ); + dbgwrite_txt( tdm_lsfQ_PCh, M, "Fixed_code_tdm_lsfQ_PCh.txt", NULL ); + dbgwrite_txt( hStereoTD->tdm_Pri_pitch_buf, NB_SUBFR, "Fixed_code_tdm_Pri_pitch_buf.txt", NULL ); +#endif +#else td_stereo_param_updt( st->lsp_old, st->lsf_old, st->old_pitch_buf + st->nb_subfr, tdm_lspQ_PCh, tdm_lsfQ_PCh, hStereoTD->tdm_Pri_pitch_buf, st->flag_ACELP16k, hStereoTD->tdm_use_IAWB_Ave_lpc ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( tdm_lspQ_PCh, M, "Float_code_tdm_lspQ_PCh.txt", NULL ); + dbgwrite_txt( tdm_lsfQ_PCh, M, "Float_code_tdm_lsfQ_PCh.txt", NULL ); + dbgwrite_txt( hStereoTD->tdm_Pri_pitch_buf, NB_SUBFR, "Float_code_tdm_Pri_pitch_buf.txt", NULL ); +#endif +#endif } } /* n_channels loop */ @@ -395,7 +447,107 @@ ivas_error ivas_core_dec( /* for inactive frames with mono output, copy and (if necessary) downmix buffers */ else if ( hCPE->nchan_out == 1 ) { +#ifdef IVAS_FLOAT_FIXED + /* To be cleaned up once the caller function is converted // These changes are for system testing of fixed changes made */ + double max_synth = 0.0f; + Word16 Q_syn = 15, synth_fx[CPE_CHANNELS][L_FRAME48k]; + double max_output = 0.0f; + Word16 Q_output = 31; + Word32 output_fx[CPE_CHANNELS][L_FRAME48k]; + + sts[0] = hCPE->hCoreCoder[0]; + sts[1] = hCPE->hCoreCoder[1]; + + if (hCPE->last_element_brate <= IVAS_SID_5k2) + { + for (int j = 0; j < output_frame; j++) + { + max_synth = max(max_synth, fabs(synth[0][j])); + } + if ((Word16)max_synth != 0) + { + Q_syn = norm_s((Word16)max_synth); + } + + for (int j = 0; j < output_frame; j++) + { + synth_fx[0][j] = float_to_fix16(synth[0][j], Q_syn); + } + + for (int j = 0; j < output_frame; j++) + { + max_output = max(max_output, fabs(output[0][j])); + } + if ((Word32)max_output != 0) + { + Q_output = norm_l((Word32)max_output); + } + + for (int j = 0; j < output_frame; j++) + { + output_fx[0][j] = float_to_fix(output[0][j], Q_output); + } + } + + f2me_buf( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst_flt, sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst, &sts[0]->hFdCngDec->hFdCngCom->sidNoiseEstExp, NPART ); + f2me_buf( sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst_flt, sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst, &sts[1]->hFdCngDec->hFdCngCom->sidNoiseEstExp, NPART ); + + if (hCPE->last_element_brate <= IVAS_SID_5k2) { + f2me_buf_16(sts[0]->hTcxLtpDec->tcxltp_mem_in_float, sts[0]->hTcxLtpDec->tcxltp_mem_in, &sts[0]->hTcxLtpDec->exp_tcxltp_mem_in, TCXLTP_MAX_DELAY); + f2me_buf_16(sts[1]->hTcxLtpDec->tcxltp_mem_in_float, sts[1]->hTcxLtpDec->tcxltp_mem_in, &sts[1]->hTcxLtpDec->exp_tcxltp_mem_in, TCXLTP_MAX_DELAY); + f2me_buf_16(sts[0]->hTcxLtpDec->tcxltp_mem_out_float, sts[0]->hTcxLtpDec->tcxltp_mem_out, &sts[0]->hTcxLtpDec->exp_tcxltp_mem_out, L_FRAME48k); + f2me_buf_16(sts[1]->hTcxLtpDec->tcxltp_mem_out_float, sts[1]->hTcxLtpDec->tcxltp_mem_out, &sts[1]->hTcxLtpDec->exp_tcxltp_mem_out, L_FRAME48k); + + f2me_buf_16(sts[0]->delay_buf_out, sts[0]->delay_buf_out_fx, &sts[0]->exp_delay_buf_out, HQ_DELTA_MAX * HQ_DELAY_COMP); /*To remove exp component Q0*/ + f2me_buf_16(sts[1]->delay_buf_out, sts[1]->delay_buf_out_fx, &sts[1]->exp_delay_buf_out, HQ_DELTA_MAX * HQ_DELAY_COMP); + f2me_buf_16(sts[0]->hHQ_core->old_out, sts[0]->hHQ_core->old_out_fx, &sts[0]->hHQ_core->exp_old_out, L_FRAME48k); + f2me_buf_16(sts[1]->hHQ_core->old_out, sts[1]->hHQ_core->old_out_fx, &sts[1]->hHQ_core->exp_old_out, L_FRAME48k); + } + updateBuffersForDmxMdctStereo_fx( hCPE, output_frame, output_fx[0], output_fx[1], synth_fx ); + + me2f_buf( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst, sts[0]->hFdCngDec->hFdCngCom->sidNoiseEstExp, sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst_flt, NPART ); + me2f_buf( sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst, sts[1]->hFdCngDec->hFdCngCom->sidNoiseEstExp, sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst_flt, NPART ); + if (hCPE->last_element_brate <= IVAS_SID_5k2) { + me2f_buf_16(sts[0]->hTcxLtpDec->tcxltp_mem_in, sts[0]->hTcxLtpDec->exp_tcxltp_mem_in, sts[0]->hTcxLtpDec->tcxltp_mem_in_float, TCXLTP_MAX_DELAY); + me2f_buf_16(sts[0]->hTcxLtpDec->tcxltp_mem_out, sts[0]->hTcxLtpDec->exp_tcxltp_mem_out, sts[0]->hTcxLtpDec->tcxltp_mem_out_float, L_FRAME48k); + me2f_buf_16(sts[0]->delay_buf_out_fx, sts[0]->exp_delay_buf_out, sts[0]->delay_buf_out, HQ_DELTA_MAX * HQ_DELAY_COMP); /*To remove exp component Q0*/ + me2f_buf_16(sts[0]->hHQ_core->old_out_fx, sts[0]->hHQ_core->exp_old_out, sts[0]->hHQ_core->old_out, L_FRAME48k); + me2f_buf_16(sts[1]->hHQ_core->old_out_fx, sts[1]->hHQ_core->exp_old_out, sts[1]->hHQ_core->old_out, L_FRAME48k); + } + + for ( i = 1; i < CPE_CHANNELS; i++ ) + { + for ( int j = 0; j < L_FRAME48k; j++ ) + { + output[i][j] = fix_to_float( output_fx[i][j], Q_output ); + } + } + + for ( i = 1; i < CPE_CHANNELS; i++ ) + { + for ( int j = 0; j < output_frame; j++ ) + { + synth[i][j] = fix16_to_float( synth_fx[i][j], Q_syn ); + } + } +#ifdef DUMPS_ENABLED + dbgwrite_txt( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst_flt, NPART, "sidNoiseEst_FIXED.txt", NULL ); + dbgwrite_txt( sts[0]->hTcxLtpDec->tcxltp_mem_in_float, TCXLTP_MAX_DELAY, "tcxltp_mem_in_FIXED.txt", NULL ); + dbgwrite_txt( sts[0]->delay_buf_out, HQ_DELTA_MAX * HQ_DELAY_COMP, "delay_buf_out_FIXED.txt", NULL ); + dbgwrite_txt( sts[0]->hHQ_core->old_out, L_FRAME48k, "old_out_FIXED.txt", NULL ); + dbgwrite_txt( sts[0]->hTcxLtpDec->tcxltp_mem_out_float, L_FRAME48k, "tcxltp_mem_out_FIXED.txt", NULL ); +#endif + +#else updateBuffersForDmxMdctStereo( hCPE, output_frame, output, synth ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst_flt, NPART, "sidNoiseEst_FLOAT.txt", NULL ); + dbgwrite_txt( sts[0]->hTcxLtpDec->tcxltp_mem_in_float, TCXLTP_MAX_DELAY, "tcxltp_mem_in_FLOAT.txt", NULL ); + dbgwrite_txt( sts[0]->delay_buf_out, HQ_DELTA_MAX * HQ_DELAY_COMP, "delay_buf_out_FLOAT.txt", NULL ); + dbgwrite_txt( sts[0]->hHQ_core->old_out, L_FRAME48k, "old_out_FLOAT.txt", NULL ); + dbgwrite_txt( sts[0]->hTcxLtpDec->tcxltp_mem_out_float, L_FRAME48k, "tcxltp_mem_out_FLOAT.txt", NULL ); +#endif +#endif } if ( sts[0]->bfi == 0 && sts[0]->prev_bfi == 1 ) @@ -417,7 +569,50 @@ ivas_error ivas_core_dec( if ( sts[0]->element_mode == IVAS_CPE_TD && hCPE->hStereoCng != NULL ) { +#ifdef IVAS_FLOAT_FIXED + /* To be cleaned up once the caller function is converted // These changes are for system testing of fixed changes made */ + Word32 output_fx[CPE_CHANNELS][L_FRAME16k]; + Word16 Q_c_PS_LT = 31, Q_output = 31; + double max_output_fx = 0; + + for (i = 0; i < CPE_CHANNELS; i++) + { + for (int j = 0; j < L_FRAME16k; j++) + { + max_output_fx = max(max_output_fx, fabs(output[i][j])); + } + } + + if ((Word32)max_output_fx != 0) + { + Q_output = norm_l((Word32)max_output_fx); + } + for (i = 0; i < CPE_CHANNELS; i++) + { + for (int j = 0; j < L_FRAME16k; j++) + { + output_fx[i][j] = float_to_fix(output[i][j], Q_output); + } + } + + if ((Word32)hCPE->hStereoCng->c_PS_LT != 0) + { + Q_c_PS_LT = norm_l((Word32)hCPE->hStereoCng->c_PS_LT); + } + Word32 c_PS_LT_fx = float_to_fix(hCPE->hStereoCng->c_PS_LT, Q_c_PS_LT); + + stereo_cng_compute_PScorr_fx(output_fx[0], output_fx[1], Q_output, &c_PS_LT_fx, Q_c_PS_LT, sts[0]->L_frame, sts[1]->L_frame); + + hCPE->hStereoCng->c_PS_LT = fix_to_float( c_PS_LT_fx, Q_c_PS_LT ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( &( hCPE->hStereoCng->c_PS_LT ), 1, "Fixed_code_c_PS_LT.txt", NULL ); +#endif +#else stereo_cng_compute_PScorr( output, &hCPE->hStereoCng->c_PS_LT, sts[0]->L_frame, sts[1]->L_frame ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( &( hCPE->hStereoCng->c_PS_LT ), 1, "Float_code_c_PS_LT.txt", NULL ); +#endif +#endif } /*---------------------------------------------------------------------* @@ -830,7 +1025,107 @@ ivas_error ivas_core_dec( *--------------------------------------------------------*/ /* Save synthesis for HQ FEC */ +#ifdef IVAS_FLOAT_FIXED + Word32 exp_max = 0; + Word32 output_fx[L_FRAME48k]; + if ( ( st->codec_mode == MODE1 && st->hTcxDec != NULL ) && ( ( st->core == ACELP_CORE && !( st->bfi == 1 && st->con_tcx == 1 ) ) || st->core == HQ_CORE ) ) + { + double max_prev_synth_buffer = 0.0f, max_old_out = 0.0f, max_delay_buf_out = 0.0f, max_ouput = 0.0f, max_synth_history = 0.0f; + Word32 exp_prev_synth_buffer = 0, exp_old_out = 0, exp_delay_buf_out = 0, exp_ouput = 0, exp_synth_history = 0; + + /*Find maximum values for all the buffers*/ + for ( i = 0; i < NS2SA( 48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ); i++ ) + { + max_prev_synth_buffer = max( max_prev_synth_buffer, fabs( st->prev_synth_buffer[i] ) ); + } + if ( (Word16) max_prev_synth_buffer != 0 ) + { + frexp( max_prev_synth_buffer, &exp_prev_synth_buffer ); + } + + for ( i = NS2SA( st->output_Fs, N_ZERO_MDCT_NS ); i < NS2SA( st->output_Fs, N_ZERO_MDCT_NS ) + NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ); i++ ) + { + max_old_out = max( max_old_out, fabs( st->hHQ_core->old_out[i] ) ); + } + if ( (Word16) max_old_out != 0 ) + { + frexp( max_old_out, &exp_old_out ); + } + + for ( i = 0; i < NS2SA( st->output_Fs, DELAY_CLDFB_NS ); i++ ) + { + max_delay_buf_out = max( max_delay_buf_out, fabs( st->delay_buf_out[i] ) ); + } + if ( (Word16) max_delay_buf_out != 0 ) + { + frexp( max_delay_buf_out, &exp_delay_buf_out ); + } + + for ( i = 0; i < output_frame; i++ ) + { + max_ouput = max( max_ouput, fabs( output[n][i] ) ); + } + if ( (Word16) max_ouput != 0 ) + { + frexp( max_ouput, &exp_ouput ); + } + + for ( i = output_frame; i < 2 * output_frame - NS2SA( st->output_Fs, DELAY_CLDFB_NS ) + NS2SA( st->output_Fs, PH_ECU_MEM_NS ); i++ ) + { + max_synth_history = max( max_synth_history, fabs( st->hTcxDec->synth_history[i] ) ); + } + + if ( (Word16) max_synth_history != 0 ) + { + frexp( max_synth_history, &exp_synth_history ); + } + + /*Find a commen maximum exp*/ + exp_max = max( exp_synth_history, exp_ouput ); + exp_max = max( exp_max, exp_prev_synth_buffer ); + exp_max = max( exp_max, exp_old_out ); + exp_max = max( exp_max, exp_delay_buf_out ); + + for ( i = 0; i < NS2SA( st->output_Fs, DELAY_CLDFB_NS ); i++ ) + { + f2fix_16( &st->delay_buf_out[i], &st->delay_buf_out_fx[i], exp_max ); + } + for ( i = NS2SA( st->output_Fs, N_ZERO_MDCT_NS ); i < NS2SA( st->output_Fs, PH_ECU_LOOKAHEAD_NS ); i++ ) + { + f2fix_16( &st->hHQ_core->old_out[i], &st->hHQ_core->old_out_fx[i], exp_max ); + } + for ( i = 0; i < NS2SA( 48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ); i++ ) + { + f2fix_16( &st->prev_synth_buffer[i], &st->prev_synth_buffer_fx[i], exp_max ); + } + for ( i = output_frame; i < 2 * output_frame - NS2SA( st->output_Fs, DELAY_CLDFB_NS ) + NS2SA( st->output_Fs, PH_ECU_MEM_NS ); i++ ) + { + f2fix_16( &st->hTcxDec->synth_history[i], &st->hTcxDec->synth_history_fx[i], exp_max ); + } + for ( i = 0; i < output_frame; i++ ) + { + f2fix( &output[n][i], &output_fx[i], exp_max ); + } + } + save_synthesis_hq_fec_fx( st, output_fx, output_frame, hCPE ); + if ( ( st->codec_mode == MODE1 && st->hTcxDec != NULL ) && ( ( st->core == ACELP_CORE && !( st->bfi == 1 && st->con_tcx == 1 ) ) || st->core == HQ_CORE ) ) + { + /*dumps*/ + float track = 0; + for ( i = 0; i < 2 * output_frame + NS2SA(st->output_Fs, PH_ECU_LOOKAHEAD_NS); i++ ) + { + fix2f_16( &st->hTcxDec->synth_history_fx[i], &track, exp_max ); + fix2f_16( &st->hTcxDec->synth_history_fx[i], &st->hTcxDec->synth_history[i], exp_max ); + +#ifdef DUMPS_ENABLED + dbgwrite_txt( &track, 1, "Fixed_code_synth_history_fx.txt", NULL ); + dbgwrite_txt( &st->hTcxDec->synth_history[i], 1, "Float_code_synth_history_fx.txt", NULL ); +#endif + } + } +#else save_synthesis_hq_fec( st, output[n], output_frame, hCPE ); +#endif /* Updates */ updt_dec_common( st, NORMAL_HQ_CORE, -1, output[n] ); @@ -838,9 +1133,6 @@ ivas_error ivas_core_dec( } /* n_channels loop */ - pop_wmops(); return error; } - - diff --git a/lib_dec/ivas_mct_dec.c b/lib_dec/ivas_mct_dec.c index 006f76b88..91e1dacb1 100644 --- a/lib_dec/ivas_mct_dec.c +++ b/lib_dec/ivas_mct_dec.c @@ -43,7 +43,10 @@ #include "ivas_rom_com.h" #include "wmc_auto.h" #include "ivas_prot_fx.h" - +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" +#endif /*-----------------------------------------------------------------------* * Local function prototypes @@ -250,7 +253,108 @@ ivas_error ivas_mct_dec( mvr2r( synth[n], output[cpe_id * CPE_CHANNELS + n], output_frame ); /* Save synthesis for HQ FEC */ +#ifdef IVAS_FLOAT_FIXED + Word32 exp_max = 0, i; + Word32 output_fx[L_FRAME48k]; + if ( ( sts[n]->codec_mode == MODE1 && sts[n]->hTcxDec != NULL ) && ( ( sts[n]->core == ACELP_CORE && !( sts[n]->bfi == 1 && sts[n]->con_tcx == 1 ) ) || sts[n]->core == HQ_CORE ) ) + { + double max_prev_synth_buffer = 0.0f, max_old_out = 0.0f, max_delay_buf_out = 0.0f, max_ouput = 0.0f, max_synth_history = 0.0f; + Word32 exp_prev_synth_buffer = 0, exp_old_out = 0, exp_delay_buf_out = 0, exp_ouput = 0, exp_synth_history = 0; + + /*Find maximum values for all the buffers*/ + for ( i = 0; i < NS2SA( 48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ); i++ ) + { + max_prev_synth_buffer = max( max_prev_synth_buffer, fabs( sts[n]->prev_synth_buffer[i] ) ); + } + if ( (Word16) max_prev_synth_buffer != 0 ) + { + frexp( max_prev_synth_buffer, &exp_prev_synth_buffer ); + } + + for ( i = NS2SA( sts[n]->output_Fs, N_ZERO_MDCT_NS ); i < NS2SA( sts[n]->output_Fs, N_ZERO_MDCT_NS ) + NS2SA( sts[n]->output_Fs, PH_ECU_LOOKAHEAD_NS ); i++ ) + { + max_old_out = max( max_old_out, fabs( sts[n]->hHQ_core->old_out[i] ) ); + } + if ( (Word16) max_old_out != 0 ) + { + frexp( max_old_out, &exp_old_out ); + } + + for ( i = 0; i < NS2SA( sts[n]->output_Fs, DELAY_CLDFB_NS ); i++ ) + { + max_delay_buf_out = max( max_delay_buf_out, fabs( sts[n]->delay_buf_out[i] ) ); + } + if ( (Word16) max_delay_buf_out != 0 ) + { + frexp( max_delay_buf_out, &exp_delay_buf_out ); + } + + for ( i = 0; i < output_frame; i++ ) + { + max_ouput = max( max_ouput, fabs( output[cpe_id * CPE_CHANNELS + n][i] ) ); + } + if ( (Word16) max_ouput != 0 ) + { + frexp( max_ouput, &exp_ouput ); + } + + for ( i = output_frame; i < 2 * output_frame - NS2SA( sts[n]->output_Fs, DELAY_CLDFB_NS ) + NS2SA( sts[n]->output_Fs, PH_ECU_MEM_NS ); i++ ) + { + max_synth_history = max( max_synth_history, fabs( sts[n]->hTcxDec->synth_history[i] ) ); + } + + if ( (Word16) max_synth_history != 0 ) + { + frexp( max_synth_history, &exp_synth_history ); + } + + /*Find a commen maximum exp*/ + exp_max = max( exp_synth_history, exp_ouput ); + exp_max = max( exp_max, exp_prev_synth_buffer ); + exp_max = max( exp_max, exp_old_out ); + exp_max = max( exp_max, exp_delay_buf_out ); + + for ( i = 0; i < NS2SA( sts[n]->output_Fs, DELAY_CLDFB_NS ); i++ ) + { + f2fix_16( &sts[n]->delay_buf_out[i], &sts[n]->delay_buf_out_fx[i], exp_max ); + } + for ( i = NS2SA( sts[n]->output_Fs, N_ZERO_MDCT_NS ); i < NS2SA( sts[n]->output_Fs, PH_ECU_LOOKAHEAD_NS ); i++ ) + { + f2fix_16( &sts[n]->hHQ_core->old_out[i], &sts[n]->hHQ_core->old_out_fx[i], exp_max ); + } + for ( i = 0; i < NS2SA( 48000, DELAY_BWE_TOTAL_NS - DELAY_CLDFB_NS ); i++ ) + { + f2fix_16( &sts[n]->prev_synth_buffer[i], &sts[n]->prev_synth_buffer_fx[i], exp_max ); + } + for ( i = output_frame; i < 2 * output_frame - NS2SA( sts[n]->output_Fs, DELAY_CLDFB_NS ) + NS2SA( sts[n]->output_Fs, PH_ECU_MEM_NS ); i++ ) + { + f2fix_16( &sts[n]->hTcxDec->synth_history[i], &sts[n]->hTcxDec->synth_history_fx[i], exp_max ); + } + for ( i = 0; i < output_frame; i++ ) + { + f2fix( &output[cpe_id * CPE_CHANNELS + n][i], &output_fx[i], exp_max ); + } + } + + save_synthesis_hq_fec_fx( sts[n], output_fx, output_frame, hCPE ); + + if ( ( sts[n]->codec_mode == MODE1 && sts[n]->hTcxDec != NULL ) && ( ( sts[n]->core == ACELP_CORE && !( sts[n]->bfi == 1 && sts[n]->con_tcx == 1 ) ) || sts[n]->core == HQ_CORE ) ) + { + /*dumps*/ + float track = 0; + for ( i = 0; i < 2 * output_frame; i++ ) + { + fix2f_16( &sts[n]->hTcxDec->synth_history_fx[i], &track, exp_max ); + fix2f_16( &sts[n]->hTcxDec->synth_history_fx[i], &sts[n]->hTcxDec->synth_history[i], exp_max ); +#ifdef DUMPS_ENABLED + dbgwrite_txt( &track, 1, "Fixed_code_synth_history_fx.txt", NULL ); + dbgwrite_txt( &sts[n]->hTcxDec->synth_history[i], 1, "Float_code_synth_history_fx.txt", NULL ); +#endif + } + } +#else save_synthesis_hq_fec( sts[n], output[cpe_id * CPE_CHANNELS + n], output_frame, hCPE ); +#endif /* CoreCoder common updates */ updt_dec_common( sts[n], NORMAL_HQ_CORE, -1, output[cpe_id * CPE_CHANNELS + n] ); diff --git a/lib_dec/ivas_stereo_cng_dec.c b/lib_dec/ivas_stereo_cng_dec.c index 64a163907..ef165175b 100644 --- a/lib_dec/ivas_stereo_cng_dec.c +++ b/lib_dec/ivas_stereo_cng_dec.c @@ -41,8 +41,9 @@ #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" -#endif // IVAS_FLOAT_FIXED - +#include "prot_fx1.h" +#include "prot_fx2.h" +#endif /*------------------------------------------------------------------- * Local constants *-------------------------------------------------------------------*/ @@ -53,6 +54,8 @@ /* DTX/CNG */ #define MAX_K 50.0f #define STEREO_TD_PS_CORR_FILT 0.8f +#define STEREO_TD_PS_CORR_FILT_Q31 1717986944 +#define ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 429496704 #define MAX_XFADE 50.0f #define CM_INIT 50 #define CORR_INIT 8 @@ -741,6 +744,102 @@ void stereo_cng_dec_update( * * CNA for TD stereo, compute PS correlation *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_cng_compute_PScorr_fx( + Word32 output_fx0[], /* i : Output signal Qx = 1/*temp*/ + Word32 output_fx1[], /* i : Output signal Qx*/ + Word16 output_Q, + Word32 *c_PS_LT_fx, + Word16 Q_c_PS_LT_fx, + const Word16 L_frame_0, /* i : L_frame channel 0 */ + const Word16 L_frame_1 /* i : L_frame channel 1 */ +) +{ + Word16 i; + Word32 enrP_fx = 0, enrS_fx = 0, dotPS_fx = 0, c_PS_fx; + Word32 outputResamp_fx[L_FRAME16k]; + Word32 *outputPptr_fx, *outputSptr_fx; + Word16 outputPptr_Q = 0, outputSptr_Q = 0; + Word32 tmp1 = 0, tmp2 = 0, tmp3 = 0; + + IF( GT_16( L_frame_0, L_frame_1 ) ) + { + outputPptr_fx = output_fx0; + outputPptr_Q = output_Q; + L_lerp_fx( output_fx1, outputResamp_fx, L_frame_0, L_frame_1 ); + outputSptr_fx = outputResamp_fx; + outputSptr_Q = 1; + } + ELSE IF( GT_16( L_frame_1, L_frame_0 ) ) + { + outputSptr_fx = output_fx1; + outputSptr_Q = output_Q; + L_lerp_fx( output_fx0, outputResamp_fx, L_frame_1, L_frame_0 ); + outputPptr_fx = outputResamp_fx; + outputPptr_Q = 1; + } + ELSE + { + outputPptr_fx = output_fx0; + outputSptr_fx = output_fx1; + outputPptr_Q = output_Q; + outputSptr_Q = output_Q; + } + + Word16 guard_bits = (Word16) find_guarded_bits_fx( L_frame_0 ); + + FOR( i = 0; i < L_frame_0; i++ ) + { + tmp1 = Mpy_32_32( *outputPptr_fx, *outputPptr_fx ); // 2*outputPptr_Q - 31 + tmp1 = L_shr( tmp1, guard_bits ); // 2*outputPptr_Q - 31 - guard_bits + enrP_fx = L_add( enrP_fx, tmp1 ); + tmp2 = Mpy_32_32( *outputSptr_fx, *outputSptr_fx ); // 2*outputSptr_Q - 31 + tmp2 = L_shr( tmp2, guard_bits ); // 2 * outputSptr_Q - 31 - guard_bits + enrS_fx = L_add( enrS_fx, tmp2 ); + + tmp3 = Mpy_32_32( *outputPptr_fx++, *outputSptr_fx++ ); // outputSptr_Q + outputPptr_Q - 31 + tmp3 = L_shr( tmp3, guard_bits + 1 ); // outputSptr_Q + outputPptr_Q - 31 - guard_bits + dotPS_fx = L_add( dotPS_fx, tmp3 ); + } + + Word32 Var1 = Mpy_32_32( enrP_fx, enrS_fx ); // 2*( outputPptr_Q - 31 - guard_bits + outputSptr_Q - 31 - guard_bits ) + Word32 temp = L_add( Var1, 1 ); /*adding one in order to make temp non-zero*/ + Word16 q = 2 * ( outputPptr_Q - 31 - guard_bits + outputSptr_Q - 31 - guard_bits ); + + Word16 nrm = norm_l( Var1 ); + Word32 frac = L_shl( temp, nrm ); + Word16 exp = 31 - ( q + nrm ); + Word32 Var2 = Isqrt_lc( frac, &exp ); /*Q(31 - exp)*/ + + Word32 Var3 = L_add( dotPS_fx, 1 ); /*adding one in order to make temp non-zero. q = Q_outputSptr + Q_outputPptr - guard_bits*/ + + c_PS_fx = Mpy_32_32( Var3, Var2 ); /* outputSptr_Q + outputPptr_Q - guard_bits - exp */ + Word16 c_PS_fx_Q = outputSptr_Q + outputPptr_Q - guard_bits - exp - 31; + + + Word32 a = 0, b = 0; + a = Mpy_32_32( c_PS_fx, ONE_MINUS_STEREO_TD_PS_CORR_FILT_Q31 ); // Q(c_PS_fx_Q) + Word16 a_q = 0, b_q = 0, ab_q = 0; + a_q = c_PS_fx_Q; + b = Mpy_32_32( STEREO_TD_PS_CORR_FILT_Q31, *c_PS_LT_fx ); // Q(Q_c_PS_LT_fx) + b_q = Q_c_PS_LT_fx; + + if ( a_q > b_q ) + { + ab_q = a_q - b_q; + *c_PS_LT_fx = L_add( L_shr( a, (Word16) ab_q ), b ); + Q_c_PS_LT_fx = b_q; + } + else if ( b_q < a_q ) + { + ab_q = b_q - a_q; + *c_PS_LT_fx = L_add( a, L_shr( b, (Word16) ab_q ) ); + Q_c_PS_LT_fx = a_q; + } + + return; +} +#endif void stereo_cng_compute_PScorr( float *output[CPE_CHANNELS], /* i : Output signal */ @@ -790,8 +889,6 @@ void stereo_cng_compute_PScorr( return; } - - /*-------------------------------------------------------------------* * Function stereo_cng_compute_LRcorr() * diff --git a/lib_dec/ivas_stereo_mdct_stereo_dec.c b/lib_dec/ivas_stereo_mdct_stereo_dec.c index 0bd589273..b41b4520b 100644 --- a/lib_dec/ivas_stereo_mdct_stereo_dec.c +++ b/lib_dec/ivas_stereo_mdct_stereo_dec.c @@ -41,6 +41,8 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" #endif // IVAS_FLOAT_FIXED +#include "prot_fx1.h" +#include "prot_fx2.h" /*-------------------------------------------------------------------* @@ -568,6 +570,171 @@ void synchonize_channels_mdct_sid( * between active/inactive coding in MDCT-Stereo DTX *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +//helper function +static void update_exp( Word16 *a_exp, Word16 *b_exp, Word16 *buff_a, Word16 *buff_b, Word16 legth ); + +static void update_exp( Word16 *a_exp, Word16 *b_exp, Word16 *buff_a, Word16 *buff_b, Word16 legth ) +{ + Word16 diff = 0; + if ( *a_exp > *b_exp ) + { + diff = *a_exp - *b_exp; + for ( int j = 0; j < legth; j++ ) + { + buff_b[j] = shr( buff_b[j], diff ); + } + *b_exp = *a_exp; + } + else if ( *a_exp < *b_exp ) + { + diff = *b_exp - *a_exp; + + for ( int j = 0; j < legth; j++ ) + { + buff_a[j] = shr( buff_a[j], diff ); + } + *a_exp = *b_exp; + } + return; +} + +void updateBuffersForDmxMdctStereo_fx( + CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ + const int16_t output_frame, /* i : output frame length */ + Word32 output0_fx[], + Word32 output1_fx[], + Word16 synth_fx[CPE_CHANNELS][L_FRAME48k] /* i/o: decoder synthesis */ +) +{ + Word16 delay_buf_out_len, tcxltp_mem_in_len, delta, i; + Decoder_State *sts[CPE_CHANNELS]; + + sts[0] = hCPE->hCoreCoder[0]; + sts[1] = hCPE->hCoreCoder[1]; + + /* synch buffers for inactive frames, but not for transition frames */ + IF( LE_32( hCPE->last_element_brate, IVAS_SID_5k2 ) ) + { + Copy32( output0_fx, output1_fx, output_frame ); + Copy( synth_fx[0], synth_fx[1], output_frame ); + } + + Word32 Var1 = 0; + Word16 diff_sidNoiseEst = 0; + Word16 exp_sidNoiseEst0 = sts[0]->hFdCngDec->hFdCngCom->sidNoiseEstExp; + Word16 exp_sidNoiseEst1 = sts[1]->hFdCngDec->hFdCngCom->sidNoiseEstExp; + if ( exp_sidNoiseEst0 > exp_sidNoiseEst1 ) + { + diff_sidNoiseEst = exp_sidNoiseEst0 - exp_sidNoiseEst1; + for ( int j = 0; j < NPART; j++ ) + { + sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst[j] = L_shr( sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst[j], diff_sidNoiseEst ); + } + exp_sidNoiseEst1 = exp_sidNoiseEst0; + } + else if ( exp_sidNoiseEst0 < exp_sidNoiseEst1 ) + { + diff_sidNoiseEst = exp_sidNoiseEst1 - exp_sidNoiseEst0; + for ( int j = 0; j < NPART; j++ ) + { + sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst[j] = L_shr( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst[j], diff_sidNoiseEst ); + } + exp_sidNoiseEst0 = exp_sidNoiseEst1; + } + sts[0]->hFdCngDec->hFdCngCom->sidNoiseEstExp = exp_sidNoiseEst0; + sts[1]->hFdCngDec->hFdCngCom->sidNoiseEstExp = exp_sidNoiseEst1; + IF( EQ_32( hCPE->element_brate, IVAS_SID_5k2 ) && GT_32( hCPE->last_element_brate, IVAS_SID_5k2 ) ) + { + /* in the first SID frame after an active frame, create mid noise shape here, in SID frames that follow inactive frames, it is done directly in the SID decoding since the mid shape is being used in CNG then */ + FOR( int16_t p = 0; p < sts[0]->hFdCngDec->hFdCngCom->npart; p++ ) + { + Var1 = L_add( sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst[p] >> 1, sts[1]->hFdCngDec->hFdCngCom->sidNoiseEst[p] >> 1 ); // exp_sidNoiseEst0 - 1 + sts[0]->hFdCngDec->hFdCngCom->sidNoiseEst[p] = Mpy_32_32( float_to_fix( 0.5f, 31 ), Var1 ); // 31 - exp_sidNoiseEst0 - 1 + 31 - 31 + } + } + + /* for transition of active->inactive frame, apply passive downmix on buffers */ + IF( LE_32( hCPE->last_element_brate, IVAS_SID_5k2 ) ) + { + delta = 1; + IF( EQ_16( output_frame, L_FRAME16k ) ) + { + delta = 2; + } + ELSE IF( EQ_16( output_frame, L_FRAME32k ) ) + { + delta = 4; + } + ELSE IF( EQ_16( output_frame, L_FRAME48k ) ) + { + delta = 6; + } + + delay_buf_out_len = delta * HQ_DELAY_COMP; + tcxltp_mem_in_len = NS2SA( sts[0]->output_Fs, TCXLTP_DELAY_NS ); + + assert( delay_buf_out_len > tcxltp_mem_in_len ); + + Word16 sum_tcx_ltp = 0, sum_delay_buf = 0, sum_tcx_ltp_out = 0, sum_old_out = 0; + + update_exp( &sts[0]->hTcxLtpDec->exp_tcxltp_mem_in, &sts[1]->hTcxLtpDec->exp_tcxltp_mem_in, + sts[0]->hTcxLtpDec->tcxltp_mem_in, sts[1]->hTcxLtpDec->tcxltp_mem_in, TCXLTP_MAX_DELAY ); + + update_exp( &sts[1]->exp_delay_buf_out, &sts[1]->exp_delay_buf_out, + sts[0]->delay_buf_out_fx, sts[1]->delay_buf_out_fx, HQ_DELTA_MAX * HQ_DELAY_COMP ); + + update_exp( &sts[0]->hHQ_core->exp_old_out, &sts[1]->hHQ_core->exp_old_out, + sts[0]->hHQ_core->old_out_fx, sts[1]->hHQ_core->old_out_fx, L_FRAME48k ); + + update_exp( &sts[0]->hTcxLtpDec->exp_tcxltp_mem_out, &sts[1]->hTcxLtpDec->exp_tcxltp_mem_out, + sts[0]->hTcxLtpDec->tcxltp_mem_out, sts[1]->hTcxLtpDec->tcxltp_mem_out, L_FRAME48k ); + + FOR( i = 0; i < tcxltp_mem_in_len; i++ ) + { + sum_tcx_ltp = add( sts[0]->hTcxLtpDec->tcxltp_mem_in[i] >> 1, sts[1]->hTcxLtpDec->tcxltp_mem_in[i] >> 1 ); // exp_tcxltp_mem_in + 1 + sts[0]->hTcxLtpDec->tcxltp_mem_in[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_tcx_ltp ); // 14 - exp_tcxltp_mem_in - 1 + + sum_delay_buf = add( sts[0]->delay_buf_out_fx[i], sts[1]->delay_buf_out_fx[i] ); + sts[0]->delay_buf_out_fx[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_delay_buf ); // exp_delay_buf_sum + + sum_old_out = add( sts[0]->hHQ_core->old_out_fx[i] >> 1, sts[1]->hHQ_core->old_out_fx[i] >> 1 ); + sts[0]->hHQ_core->old_out_fx[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_old_out ); // exp_old_out_sum + + sum_tcx_ltp_out = add( sts[0]->hTcxLtpDec->tcxltp_mem_out[i] >> 1, sts[1]->hTcxLtpDec->tcxltp_mem_out[i] >> 1 ); + sts[0]->hTcxLtpDec->tcxltp_mem_out[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_tcx_ltp_out ); // exp_tcs_ltp_out_sm + } + + + FOR( ; i < delay_buf_out_len; i++ ) + { + sum_delay_buf = add( sts[0]->delay_buf_out_fx[i], sts[1]->delay_buf_out_fx[i] ); + sts[0]->delay_buf_out_fx[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_delay_buf ); // exp_delay_buf_sum + + sum_old_out = add( sts[0]->hHQ_core->old_out_fx[i] >> 1, sts[1]->hHQ_core->old_out_fx[i] >> 1 ); + sts[0]->hHQ_core->old_out_fx[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_old_out ); + + sum_tcx_ltp_out = add( sts[0]->hTcxLtpDec->tcxltp_mem_out[i] >> 1, sts[1]->hTcxLtpDec->tcxltp_mem_out[i] >> 1 ); + sts[0]->hTcxLtpDec->tcxltp_mem_out[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_tcx_ltp_out ); // exp_tcs_ltp_out_sm + } + + FOR( ; i < output_frame; i++ ) + { + sum_old_out = add( sts[0]->hHQ_core->old_out_fx[i] >> 1, sts[1]->hHQ_core->old_out_fx[i] >> 1 ); + sts[0]->hHQ_core->old_out_fx[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_old_out ); // exp_old_out_sum + + sum_tcx_ltp_out = add( sts[0]->hTcxLtpDec->tcxltp_mem_out[i] >> 1, sts[1]->hTcxLtpDec->tcxltp_mem_out[i] >> 1 ); + sts[0]->hTcxLtpDec->tcxltp_mem_out[i] = mult( float_to_fix16( INV_SQRT2, 15 ), sum_tcx_ltp_out ); // 15 + exp_tcs_ltp_out_sm - 15 + } + sts[0]->hTcxLtpDec->exp_tcxltp_mem_in += 1; + sts[0]->hHQ_core->exp_old_out += 1; + sts[0]->hTcxLtpDec->exp_tcxltp_mem_out += 1; + } + + return; +} +#endif + void updateBuffersForDmxMdctStereo( CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ const int16_t output_frame, /* i : output frame length */ @@ -642,7 +809,6 @@ void updateBuffersForDmxMdctStereo( return; } - /*-------------------------------------------------------------------* * applyDmxMdctStereo() * diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 18313c0ba..3968a56da 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -524,9 +524,15 @@ typedef struct tcx_ltp_dec_structure float tcxltp_mem_in_float[TCXLTP_MAX_DELAY]; Word16 tcxltp_mem_in[TCXLTP_MAX_DELAY]; +#ifdef IVAS_FLOAT_FIXED + Word16 exp_tcxltp_mem_in; +#endif float tcxltp_mem_out_float[L_FRAME48k]; Word16 tcxltp_mem_out[L_FRAME48k]; +#ifdef IVAS_FLOAT_FIXED + Word16 exp_tcxltp_mem_out; +#endif int16_t tcxltp_pitch_int_post_prev; @@ -1071,6 +1077,9 @@ typedef struct hq_dec_structure Word32 oldOut_fx[L_FRAME48k]; /* HQ core - previous synthesis for OLA */ #endif Word16 old_out_fx[L_FRAME48k]; /* HQ core - previous synthesis for OLA */ +#ifdef IVAS_FLOAT_FIXED + Word16 exp_old_out; +#endif float old_outLB[L_FRAME32k]; Word16 old_out_LB_fx[L_FRAME32k]; /* HQ core - previous synthesis for OLA for Low Band */ @@ -2155,6 +2164,9 @@ typedef struct Decoder_State float delay_buf_out[HQ_DELTA_MAX * HQ_DELAY_COMP]; Word16 delay_buf_out_fx[HQ_DELTA_MAX * HQ_DELAY_COMP]; /*Q0*/ +#ifdef IVAS_FLOAT_FIXED + Word16 exp_delay_buf_out; +#endif float old_Aq_12_8[M + 1]; /* old Aq[] for core switching */ Word16 old_Aq_12_8_fx[M + 1]; /* Q12 old Aq[] for core switching */ -- GitLab