diff --git a/lib_com/cnst.h b/lib_com/cnst.h index eda4d0f1201e5a04f212bc71167742e95e5fe539..295b9f96a129414aaf9edb22a759eaa879155b58 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -1682,6 +1682,15 @@ enum #define HALF_D_STAB_TBL_FX ( (Word16) 422 ) /* Q13 0.1013138/2.0 */ #define NUM_ENV_STAB_PLC_STATES 2 /* Number of states of markov model */ +#ifdef ENV_STAB_FIX +#define ENV_STAB_EST1 2.93f /* env_stab estimation coefficient 1 */ +#define ENV_STAB_EST2 (-2.20f) /* env_stab estimation coefficient 2 */ +#define ENV_STAB_EST3 0.741f /* env_stab estimation coefficient 3 */ +#define STAB_FAC_EST1 1.093f /* stab_fac HQ estimation coefficient 1 */ +#define STAB_FAC_EST2 (-5.84e-05f) /* stab_fac HQ estimation coefficient 2, including Q12 scaling */ +#define STAB_FAC_EST3 0.125f /* stab_fac HQ estimation coefficient 3 */ +#endif + #define ATT_LIM_HANGOVER 150 /* Number of hangover frames for disabling stability dependent attenuation */ #define DELTA_TH 5.0f /* Delta energy threshold for transient detection for envelope stability */ #define ENERGY_TH 100.0f /* Energy threshold for transient detection */ diff --git a/lib_com/env_stab.c b/lib_com/env_stab.c index d07c74874dffe00f06a5aab66a93b80288683071..38e7eea6c9bd4fc393dd7a72f2a8d4a901835aa0 100644 --- a/lib_com/env_stab.c +++ b/lib_com/env_stab.c @@ -63,10 +63,15 @@ /*--------------------------------------------------------------------------*/ float env_stability( - const int16_t *ynrm, /* i : Norm vector for current frame */ - const int16_t nb_sfm, /* i : Number of sub-bands */ - int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ + const int16_t *ynrm, /* i : Norm vector for current frame */ + const int16_t nb_sfm, /* i : Number of sub-bands */ + int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ +#ifdef ENV_STAB_FIX + int16_t *mem_env_delta, /* i/o: Envelope stability memory for smoothing*/ + const int16_t core_switching_flag /* i : Core switching flag */ +#else int16_t *mem_env_delta /* i/o: Envelope stability memory for smoothing*/ +#endif ) { Word16 env_delta; @@ -82,6 +87,71 @@ float env_stability( Flag Overflow; #endif /* BASOP_NOGLOB */ +#ifdef ENV_STAB_FIX + if ( core_switching_flag ) + { + for ( i = 0; i < nb_sfm; i++ ) + { + mem_norm[i] = ynrm[i]; + } +#ifdef BASOP_NOGLOB + Overflow = 0; + env_delta = shl_o( *mem_env_delta, 1, &Overflow ); +#else + env_delta = shl_o( *mem_env_delta, 1 ); +#endif + } + else + { + /* Calculate envelope stability parameter */ + L_env_delta = L_deposit_l( 0 ); + for ( i = 0; i < nb_sfm; i++ ) + { + tmp = sub( mem_norm[i], ynrm[i] ); + L_env_delta = L_mac0( L_env_delta, tmp, tmp ); + mem_norm[i] = ynrm[i]; + } + +#ifdef DEBUGGING + assert( nb_sfm == 27 || nb_sfm == 26 ); +#endif + inv_nb_sfm = 19418; /* Q19 */ + if ( nb_sfm == 26 ) + { + inv_nb_sfm = 20165; /* Q19 */ + } + exp = norm_l( L_env_delta ); + L_env_delta = Mult_32_16( L_shl( L_env_delta, exp ), inv_nb_sfm ); /* 0+exp+19-15 */ + + L_tmp = Sqrt_l( L_env_delta, &exp2 ); /* exp+4+31+exp2 */ + + exp = add( 35, add( exp, exp2 ) ); + if ( sub( s_and( exp, 1 ), 1 ) == 0 ) + { + L_tmp = Mult_32_16( L_tmp, 23170 ); /* 1/sqrt(2) in Q15 */ + } + exp = shr( exp, 1 ); + +#ifndef BASOP_NOGLOB + env_delta = round_fx( L_shl( L_tmp, sub( 26, exp ) ) ); /* Q10 */ + L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ + L_tmp = L_mac( L_tmp, 29491, *mem_env_delta ); /* 29491 is 0.9 in Q15. Q28 */ + *mem_env_delta = round_fx( L_tmp ); /* Q12 */ +#else /* BASOP_NOGLOB */ + env_delta = round_fx_o( L_shl_o( L_tmp, sub( 26, exp ), &Overflow ), &Overflow ); /* Q10 */ + L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ + L_tmp = L_mac_o( L_tmp, 29491, *mem_env_delta, &Overflow ); /* 29491 is 0.9 in Q15. Q28 */ + *mem_env_delta = round_fx_o( L_tmp, &Overflow ); /* Q12 */ +#endif /* BASOP_NOGLOB */ + Overflow = 0; +#ifndef BASOP_NOGLOB + env_delta = round_fx( L_shl( L_tmp, 1 ) ); /* Q13 */ +#else /* BASOP_NOGLOB */ + env_delta = round_fx_o( L_shl_o( L_tmp, 1, &Overflow ), &Overflow ); /* Q13 */ +#endif /* BASOP_NOGLOB */ + } +#else + /* Calculate envelope stability parameter */ L_env_delta = L_deposit_l( 0 ); for ( i = 0; i < nb_sfm; i++ ) @@ -116,19 +186,20 @@ float env_stability( L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ L_tmp = L_mac( L_tmp, 29491, *mem_env_delta ); /* 29491 is 0.9 in Q15. Q28 */ *mem_env_delta = round_fx( L_tmp ); /* Q12 */ -#else /* BASOP_NOGLOB */ +#else /* BASOP_NOGLOB */ env_delta = round_fx_o( L_shl_o( L_tmp, sub( 26, exp ), &Overflow ), &Overflow ); /* Q10 */ L_tmp = L_mult0( 26214, env_delta ); /* 26214 is 0.1 in Q18. Q28 */ L_tmp = L_mac_o( L_tmp, 29491, *mem_env_delta, &Overflow ); /* 29491 is 0.9 in Q15. Q28 */ *mem_env_delta = round_fx_o( L_tmp, &Overflow ); /* Q12 */ -#endif /* BASOP_NOGLOB */ +#endif /* BASOP_NOGLOB */ Overflow = 0; #ifndef BASOP_NOGLOB env_delta = round_fx( L_shl( L_tmp, 1 ) ); /* Q13 */ -#else /* BASOP_NOGLOB */ +#else /* BASOP_NOGLOB */ env_delta = round_fx_o( L_shl_o( L_tmp, 1, &Overflow ), &Overflow ); /* Q13 */ -#endif /* BASOP_NOGLOB */ - +#endif + /* BASOP_NOGLOB */ +#endif if ( Overflow != 0 ) /* Saturated due to the above up-shifting operation. */ { env_stab = stab_trans_fx[L_STAB_TBL - 1]; /* The highest quantized index. */ diff --git a/lib_com/options.h b/lib_com/options.h old mode 100755 new mode 100644 index 7e8be22b604d99b10d7078d0f7a03162eb53a8ee..af92ab2516aba6717c2305f1b7570560cc6903ec --- a/lib_com/options.h +++ b/lib_com/options.h @@ -155,7 +155,7 @@ #define FIX_245_RANGE_CODER_VOIP_MSAN /* Issue 245: fix use-of-uninitialized-value in range coder in VoIP mode */ #define FIX_272_COV /* Issue 272: Cleanup for code coverage related to calls to ivas_binaural_cldfb() */ #define FIX_235 /* Issue 235: Deallocation of HR filter memory separately for lib_rend (ROM) and lib_util (from file) */ - +#define ENV_STAB_FIX /* Contribution 23: HQ envelope stability memory fix */ /* ################## End DEVELOPMENT switches ######################### */ /* clang-format on */ diff --git a/lib_com/prot.h b/lib_com/prot.h index 1e77780ed4f4d81e81f5eacfdcc8d8c6b8a4ab5d..97882cb3189a8735f4a4a643936877bc22448fd3 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -5414,7 +5414,13 @@ void hq_hr_dec( int16_t *ynrm, /* o : norm quantization index vector */ int16_t *is_transient, /* o : transient flag */ int16_t *hqswb_clas, /* o : HQ SWB class */ - float *SWB_fenv /* o : SWB frequency envelopes */ +#ifdef ENV_STAB_FIX + float *SWB_fenv, /* o : SWB frequency envelopes */ + const int16_t core_switching_flag /* i : Core switching flag */ +#else + float *SWB_fenv /* o : SWB frequency envelopes */ +#endif + ); void hdecnrm_context( @@ -5838,10 +5844,15 @@ void env_adj( ); float env_stability( - const int16_t *ynrm, /* i : Norm vector for current frame */ - const int16_t nb_sfm, /* i : Number of sub-bands */ - int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ + const int16_t *ynrm, /* i : Norm vector for current frame */ + const int16_t nb_sfm, /* i : Number of sub-bands */ + int16_t *mem_norm, /* i/o: Norm vector memory from past frame */ +#ifdef ENV_STAB_FIX + int16_t *mem_env_delta, /* i/o: Envelope stability memory for smoothing*/ + const int16_t core_switching_flag /* i : Core switching flag */ +#else int16_t *mem_env_delta /* i/o: Envelope stability memory for smoothing*/ +#endif ); /*! r: New speech/music state */ diff --git a/lib_dec/core_switching_dec.c b/lib_dec/core_switching_dec.c index b53394e3550aef85642c46c9893f03377a4a64ad..20819ceb272743322dac83d5f8953a15253f3ea3 100644 --- a/lib_dec/core_switching_dec.c +++ b/lib_dec/core_switching_dec.c @@ -70,6 +70,9 @@ ivas_error core_switching_pre_dec( { int16_t i, oldLenClasBuff, newLenClasBuff; ivas_error error; +#ifdef ENV_STAB_FIX + float tmp; +#endif error = IVAS_ERR_OK; @@ -401,7 +404,11 @@ ivas_error core_switching_pre_dec( } } +#ifdef ENV_STAB_FIX + if ( st->core == HQ_CORE && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE || ( ( st->element_mode != EVS_MONO ) && ( st->last_core != HQ_CORE ) ) ) ) +#else if ( st->core == HQ_CORE && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) ) +#endif { set_f( st->hHQ_core->prev_env, 0, SFM_N_WB ); set_f( st->hHQ_core->prev_normq, 0, SFM_N_WB ); @@ -418,8 +425,34 @@ ivas_error core_switching_pre_dec( set_f( st->hHQ_core->prev_coeff_out, 0, L_HQ_WB_BWE ); } +#ifdef ENV_STAB_FIX + if ( st->element_mode != EVS_MONO ) + { + /* Estimate mem_env_delta to reinit env_stab */ + tmp = max( 0, ENV_STAB_EST1 + ( ENV_STAB_EST2 * st->stab_fac_smooth_lt ) + ( ENV_STAB_EST3 * st->log_energy_diff_lt ) ); + st->hHQ_core->mem_env_delta = (int16_t) min( MAX16B, (int32_t) ( tmp * ( 1 << 12 ) ) ); /* Convert to Q12 and handle saturation */ + + if ( st->last_core != TCX_20_CORE && st->last_core != TCX_10_CORE ) + { + set_f( st->hHQ_core->old_out, 0, output_frame ); + set_f( st->hHQ_core->old_outLB, 0, L_FRAME16k ); + } + + st->hHQ_core->no_att_hangover = 0; + st->hHQ_core->energy_lt = 300.0f; + + set_s( st->hHQ_core->old_is_transient, 0, 3 ); + set_f( st->hHQ_core->prev_noise_level, 0.0f, 2 ); + st->hHQ_core->prev_R = 0; + set_s( st->hHQ_core->mem_norm + 1, 39, SFM_N_ENV_STAB - 1 ); + st->hHQ_core->prev_hqswb_clas = HQ_NORMAL; + st->hHQ_core->prev_ni_ratio = 0.5f; + set_f( st->hHQ_core->prev_En_sb, 0.0f, NB_SWB_SUBBANDS ); + } +#else set_f( st->hHQ_core->old_out, 0, output_frame ); set_f( st->hHQ_core->old_outLB, 0, L_FRAME16k ); +#endif } /* handle switching cases where preecho_sb was not called in the last frame (memory not up to date) */ diff --git a/lib_dec/hq_core_dec.c b/lib_dec/hq_core_dec.c index 4920e220ae9e1e22102510c8a456e5cef6f3582b..5fcf85dc8a5f6c8cd202ffccd52fa2744a8dfb8f 100644 --- a/lib_dec/hq_core_dec.c +++ b/lib_dec/hq_core_dec.c @@ -249,7 +249,11 @@ void hq_core_dec( else { /* HQ high rate decoder */ +#ifdef ENV_STAB_FIX + hq_hr_dec( st, t_audio_q, L_spec, num_bits, ynrm, &is_transient, &hqswb_clas, SWB_fenv, core_switching_flag ); +#else hq_hr_dec( st, t_audio_q, L_spec, num_bits, ynrm, &is_transient, &hqswb_clas, SWB_fenv ); +#endif } if ( st->element_mode == EVS_MONO || ( !core_switching_flag && !hq_recovery_flag ) ) diff --git a/lib_dec/hq_hr_dec.c b/lib_dec/hq_hr_dec.c index 24a51bd464569a0a3bde22e4e6f76a8533de510c..980d82886f566486d03abc0938e985af81b54c66 100644 --- a/lib_dec/hq_hr_dec.c +++ b/lib_dec/hq_hr_dec.c @@ -107,7 +107,12 @@ void hq_hr_dec( int16_t *ynrm, /* o : norm quantization index vector */ int16_t *is_transient, /* o : transient flag */ int16_t *hqswb_clas, /* o : HQ SWB class */ - float *SWB_fenv /* o : SWB frequency envelopes */ +#ifdef ENV_STAB_FIX + float *SWB_fenv, /* o : SWB frequency envelopes */ + const int16_t core_switching_flag /* i : Core switching flag */ +#else + float *SWB_fenv /* o : SWB frequency envelopes */ +#endif ) { int16_t nb_sfm; @@ -193,9 +198,17 @@ void hq_hr_dec( { hHQ_core->mem_env_delta = 0; } +#ifdef ENV_STAB_FIX + else if ( length == L_FRAME32k || ( core_switching_flag && ( st->element_mode != EVS_MONO ) && length == L_SPEC32k_EXT ) ) +#else else if ( length == L_FRAME32k ) +#endif { +#ifdef ENV_STAB_FIX + env_stab = env_stability( ynrm, SFM_N_ENV_STAB, hHQ_core->mem_norm, &hHQ_core->mem_env_delta, core_switching_flag && ( st->element_mode != EVS_MONO ) ); +#else env_stab = env_stability( ynrm, SFM_N_ENV_STAB, hHQ_core->mem_norm, &hHQ_core->mem_env_delta ); +#endif } else { @@ -209,13 +222,21 @@ void hq_hr_dec( } else { +#ifdef ENV_STAB_FIX + if ( length == L_FRAME32k || ( core_switching_flag && ( st->element_mode != EVS_MONO ) && length == L_SPEC32k_EXT ) ) +#else if ( length == L_FRAME32k ) +#endif { hHQ_core->env_stab = env_stab; /* calculated stability */ } else { +#ifdef ENV_STAB_FIX + hHQ_core->env_stab = env_stability( ynrm, SFM_N_ENV_STAB_WB, hHQ_core->mem_norm_hqfec, &hHQ_core->mem_env_delta_hqfec, core_switching_flag && ( st->element_mode != EVS_MONO ) ); +#else hHQ_core->env_stab = env_stability( ynrm, SFM_N_ENV_STAB_WB, hHQ_core->mem_norm_hqfec, &hHQ_core->mem_env_delta_hqfec ); +#endif } } hHQ_core->env_stab_plc = env_stab_smo( min( hHQ_core->env_stab, 1.0f - stab_trans[L_STAB_TBL - 1] ), hHQ_core->env_stab_state_p, &hHQ_core->envstabplc_hocnt ); diff --git a/lib_dec/init_dec.c b/lib_dec/init_dec.c index 10f6be89dac57aea978fd618b208d9c55f2fe1d8..c1583eaf2419420c9d82e6a4fa91d195f76f5ee4 100644 --- a/lib_dec/init_dec.c +++ b/lib_dec/init_dec.c @@ -127,6 +127,11 @@ ivas_error init_decoder( st->stab_fac_smooth = 0.0f; set_f( st->agc_mem2, 0, 2 ); set_f( st->mem_syn3, 0, M ); +#ifdef ENV_STAB_FIX + st->stab_fac_smooth_lt = 0.0f; + st->log_energy_diff_lt = 0.0f; + st->log_energy_old = 0.0f; +#endif mvr2r( GEWB_Ave, st->lsf_old, M ); lsf2lsp( st->lsf_old, st->lsp_old, M, INT_FS_12k8 ); diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index d86cd42b720b5b737f58e8f093b9ae6d21c9888a..9a42a00dd6ac04c5307ee157db775e83ba7adea7 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -955,6 +955,11 @@ typedef struct Decoder_State float agc_mem2[2]; /* memory of AGC for saturation control */ int16_t mid_lsf_int; int16_t safety_net; +#ifdef ENV_STAB_FIX + float stab_fac_smooth_lt; + float log_energy_old; + float log_energy_diff_lt; +#endif int16_t GSC_noisy_speech; /* AC mode (GSC) - flag to indicate GSC on SWB noisy speech */ int16_t GSC_IVAS_mode; /* AC mode (GSC) - GSC IVAS mode */ diff --git a/lib_dec/updt_dec.c b/lib_dec/updt_dec.c index cf9705e73e287109a9ac002d3d2b80f285d393a2..22d309512a4f94082157a731166d04219818a708 100644 --- a/lib_dec/updt_dec.c +++ b/lib_dec/updt_dec.c @@ -43,6 +43,9 @@ #include "prot.h" #include "rom_com.h" #include "cnst.h" +#ifdef ENV_STAB_FIX +#include +#endif #include "wmc_auto.h" /*-------------------------------------------------------------------* @@ -413,6 +416,10 @@ void updt_dec_common( ) { int16_t i; +#ifdef ENV_STAB_FIX + float log_energy, log_energy_diff; + int16_t output_frame; +#endif st->last_codec_mode = st->codec_mode; st->last_extl = st->extl; @@ -502,6 +509,24 @@ void updt_dec_common( mvr2r( synth + NS2SA( st->output_Fs, ACELP_LOOK_NS + DELAY_BWE_TOTAL_NS ), st->old_synth_sw, NS2SA( st->output_Fs, FRAME_SIZE_NS - ACELP_LOOK_NS - DELAY_BWE_TOTAL_NS ) ); } +#ifdef ENV_STAB_FIX + /* Store long-term estimates of stab_fac and log energy diff to estimate env_stab in case of core switch ACELP/TCX->HQ */ + if ( st->element_mode != EVS_MONO ) + { + output_frame = NS2SA( st->output_Fs, FRAME_SIZE_NS ); + log_energy = log2f( ( sum2_f( synth, output_frame ) / output_frame ) + 1.0f ); + log_energy_diff = fabsf( st->log_energy_old - log_energy ); + st->log_energy_old = log_energy; + st->log_energy_diff_lt = ENV_SMOOTH_FAC * log_energy_diff + ( 1.0f - ENV_SMOOTH_FAC ) * st->log_energy_diff_lt; + if ( st->core == HQ_CORE ) + { + st->stab_fac = min( 1, ( STAB_FAC_EST1 + ( STAB_FAC_EST2 * st->hHQ_core->mem_env_delta ) + ( STAB_FAC_EST3 * st->log_energy_diff_lt ) ) ); + st->stab_fac = max( 0, st->stab_fac ); + } + st->stab_fac_smooth_lt = ENV_SMOOTH_FAC * st->stab_fac + ( 1.0f - ENV_SMOOTH_FAC ) * st->stab_fac_smooth_lt; + } +#endif + if ( ( st->core_brate <= SID_2k40 && st->cng_type == FD_CNG ) || ( st->tcxonly && st->codec_mode == MODE2 ) ) { /* reset LP memories */