diff --git a/lib_com/core_com_config.c b/lib_com/core_com_config.c index d490b44b4927718da26ae9bb8271d684c3fee513..baa056be70bd2ee3f7b7c334775286d2440cdaec 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 081f2ceb6565ef24dc1f849227fb6b5a4d7fb1fd..a0f622c28ec56f9227532a5efe905760cae1604a 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 96f0be387563c6221356436c9c773580a8e2e4f4..4f9ca5484a4a5d09449558559c0d722d522284d3 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 35bfe904628c37ea236a8ceb49e63eaf599babe7..e7db2b48b4bf35c62617346068452b6446bcc59e 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 eb6702340a9d84eeddfa8a228c6cc13630df5f81..4e1a189b6839fa64678fde1850694ee5b00031a1 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 82d5afa61b7e979a217a2b22331787f97171ea57..54d1e312f836c48c3059359b438dc3fcd7d42b5c 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 0c02046c53169bdc62c838f92e24fda8f29d73e8..7343343d8321c17918fbfe31cc78b30e2d12c92b 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 edc1c2490b5a9288e6017b5246f143c040de1a4e..54fd2a326d30726e8ffa9642a7532ebd57180a63 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 b882f89288626d3eddc4de073be01d60d2c59760..4313cece946f957124218588f9b44360fd7d5827 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 51098eb58c88ce25b94d40cf9fb6ba1b30a9ee61..f4ad599f031430632a601751184218db32d1cd08 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 747dc755c4dd870794f7e126cee9e61eb43b4fa0..db2525a21d387a43debd8c2b439257167210de68 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 006f76b882ecc871280e4e25df2d01b5965a6bb6..91e1dacb17ba8cb1a60a652331def988703aef22 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 64a1639073cd6d32200c4b0b094f194894437da9..ef165175bf95ac905e1d418d298d2fff631eec0e 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 0bd5892731b8ab4769b5191149bb1b31da56b325..b41b4520b450054e7f518b1d025f47e9006f219e 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 18313c0ba58447f0ef3d76756fc1ed1562bef420..3968a56da72918e42b5c2a8ca800ec1201698a2e 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 */