From a8bb5e0d841bad15704bc9a9081f1af228eeeb6b Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Fri, 27 Sep 2024 21:00:04 +0530 Subject: [PATCH 1/2] Core coder and stereo path sub-functions conversion and integration [x] Integration and conversion of core coder sub-functions: acelp_core_enc, swb_pre_proc, swb_tbe_enc, ProcessIGF [x] Stereo path functions conversion and integration: pre_proc_front_ivas, stereo_dft_enc_res_fx, stereo_dft_enc_write_bs_fx --- lib_com/cldfb.c | 40 +- lib_com/cnst.h | 6 + lib_com/ivas_cnst.h | 3 + lib_com/ivas_prot.h | 16 + lib_com/ivas_prot_fx.h | 78 + lib_com/ivas_rom_com.h | 2 + lib_com/modif_fs_fx.c | 297 ++++ lib_com/prot.h | 6 +- lib_com/prot_fx.h | 68 +- lib_com/rom_com.h | 3 + lib_com/swb_tbe_com_fx.c | 298 +++- lib_com/tools.c | 29 + lib_com/tools_fx.c | 72 + lib_enc/acelp_core_enc.c | 97 +- lib_enc/cod4t64_fast.c | 24 +- lib_enc/core_enc_init.c | 2 +- lib_enc/core_enc_ol.c | 363 +++++ lib_enc/core_enc_updt.c | 75 + lib_enc/core_switching_enc.c | 4 + lib_enc/enc_nelp_fx.c | 146 ++ lib_enc/ext_sig_ana.c | 563 +++++++ lib_enc/hq_core_enc.c | 1 - lib_enc/igf_enc.c | 679 +++++++- lib_enc/ivas_core_enc.c | 280 +++- lib_enc/ivas_core_pre_proc.c | 112 ++ lib_enc/ivas_core_pre_proc_front.c | 1276 ++++++++------- lib_enc/ivas_cpe_enc.c | 70 +- lib_enc/ivas_ism_enc.c | 6 +- lib_enc/ivas_mdct_core_enc.c | 650 +++++++- lib_enc/ivas_rom_enc.c | 28 + lib_enc/ivas_rom_enc.h | 9 + lib_enc/ivas_sce_enc.c | 6 +- lib_enc/ivas_stat_enc.h | 13 +- lib_enc/ivas_stereo_cng_enc.c | 394 ++++- lib_enc/ivas_stereo_dft_enc.c | 951 +++++++++-- lib_enc/ivas_stereo_dft_enc_itd.c | 36 +- lib_enc/ivas_stereo_eclvq_enc.c | 816 +++++++++- lib_enc/ivas_stereo_icbwe_enc.c | 2 +- lib_enc/nelp_enc_fx.c | 819 ++++++++++ lib_enc/prot_fx_enc.h | 59 + lib_enc/speech_music_classif_fx.c | 569 +++++-- lib_enc/stat_enc.h | 93 +- lib_enc/swb_pre_proc.c | 709 +++++---- lib_enc/swb_tbe_enc.c | 407 +---- lib_enc/swb_tbe_enc_fx.c | 2386 ++++++++++++++++++++++++++-- lib_enc/tcx_ltp_enc_fx.c | 703 ++++++++ lib_enc/tcx_utils_enc.c | 12 +- lib_enc/transient_detection_fx.c | 204 ++- lib_enc/updt_enc.c | 225 ++- lib_enc/vad_fx.c | 71 +- 50 files changed, 11873 insertions(+), 1905 deletions(-) diff --git a/lib_com/cldfb.c b/lib_com/cldfb.c index 6bbd3e152..6cba0128d 100644 --- a/lib_com/cldfb.c +++ b/lib_com/cldfb.c @@ -1949,8 +1949,10 @@ void analysisCldfbEncoder_ivas( } void analysisCldfbEncoder_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - const Word16 *timeIn, + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 *timeIn, /*q11*/ + Word16 timeInq, + Word16 samplesToProcess, Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], @@ -1965,7 +1967,6 @@ void analysisCldfbEncoder_ivas_fx( Word32 *ppBuf_Imag[CLDFB_NO_COL_MAX]; Word16 *ppBuf_Real16[CLDFB_NO_COL_MAX]; Word16 *ppBuf_Imag16[CLDFB_NO_COL_MAX]; - Word32 workBuffer[256]; FOR( i = 0; i < CLDFB_NO_COL_MAX; i++ ) { @@ -1974,13 +1975,14 @@ void analysisCldfbEncoder_ivas_fx( ppBuf_Real16[i] = &realBuffer16[i][0]; ppBuf_Imag16[i] = &imagBuffer16[i][0]; } + cldfbAnalysis_ivas_fx( timeIn, ppBuf_Real, ppBuf_Imag, samplesToProcess, st->cldfbAnaEnc ); - cldfbAnalysisFiltering( st->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, scale, timeIn, 0, CLDFB_NO_COL_MAX, workBuffer ); - + scale->lb_scale = sub( 16 + 5, timeInq ); enerScale.lb_scale = negate( scale->lb_scale ); enerScale.lb_scale16 = negate( scale->lb_scale ); move16(); move16(); + move16(); AnalysisPostSpectrumScaling_Fx( st->cldfbAnaEnc, ppBuf_Real, ppBuf_Imag, ppBuf_Real16, ppBuf_Imag16, &enerScale.lb_scale16 ); @@ -2793,7 +2795,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17036; hs->scale = cldfb_scale_2_5ms[0]; - hs->p_filter = cldfb_protoFilter_2_5ms[0]; + hs->p_filter = CLDFB80_10_fx; #endif } else if ( hs->prototype == CLDFB_PROTOTYPE_5_00MS ) @@ -2808,7 +2810,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = rot_vec_delay_im_LDQMF; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15388; - hs->p_filter = cldfb_protoFilter_5_0ms[0]; + hs->p_filter = LDQMF_10_fx; hs->scale = cldfb_scale_5_0ms[0]; #endif } @@ -2843,7 +2845,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = NULL; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17051; - hs->p_filter = cldfb_protoFilter_2_5ms[1]; + hs->p_filter = CLDFB80_16_fx; hs->scale = cldfb_scale_2_5ms[1]; #endif } @@ -2859,7 +2861,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = rot_vec_delay_im_LDQMF; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15388; - hs->p_filter = cldfb_protoFilter_5_0ms[1]; + hs->p_filter = LDQMF_16_fx; hs->scale = cldfb_scale_5_0ms[1]; #endif } @@ -2900,7 +2902,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = NULL; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17050; - hs->p_filter = cldfb_protoFilter_2_5ms[2]; + hs->p_filter = CLDFB80_20_fx; hs->scale = cldfb_scale_2_5ms[2]; #endif } @@ -2916,7 +2918,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = rot_vec_delay_im_LDQMF; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15390; - hs->p_filter = cldfb_protoFilter_5_0ms[2]; + hs->p_filter = LDQMF_20_fx; hs->scale = cldfb_scale_5_0ms[2]; #endif } @@ -2958,7 +2960,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17051; hs->scale = cldfb_scale_2_5ms[6]; - hs->p_filter = cldfb_protoFilter_2_5ms[6]; + hs->p_filter = CLDFB80_30_fx; #endif } else if ( hs->prototype == CLDFB_PROTOTYPE_5_00MS ) @@ -2974,7 +2976,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15388; hs->scale = cldfb_scale_5_0ms[6]; - hs->p_filter = cldfb_protoFilter_5_0ms[6]; + hs->p_filter = LDQMF_30_fx; #endif } break; @@ -3008,7 +3010,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_im = NULL; #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 17050; - hs->p_filter = cldfb_protoFilter_2_5ms[3]; + hs->p_filter = CLDFB80_32_fx; hs->scale = cldfb_scale_2_5ms[3]; #endif } @@ -3025,7 +3027,7 @@ static void cldfb_init_proto_and_twiddles_enc( #ifdef IVAS_FLOAT_FIXED hs->p_filter_sf = (Word16) 15392; hs->scale = cldfb_scale_5_0ms[3]; - hs->p_filter = cldfb_protoFilter_5_0ms[3]; + hs->p_filter = LDQMF_32_fx; #endif } break; @@ -3067,7 +3069,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->p_filter_sf = (Word16) 17051; hs->q_scale = norm_s( (Word16) CLDFB80_40_SCALE ); hs->scale = cldfb_scale_2_5ms[4]; - hs->p_filter = cldfb_protoFilter_2_5ms[4]; + hs->p_filter = CLDFB80_40_fx; #endif } else if ( hs->prototype == CLDFB_PROTOTYPE_5_00MS ) @@ -3086,7 +3088,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_syn_delay_im_fx = rot_vec_delay_im_LDQMF_fx; hs->p_filter_sf = (Word16) 15391; - hs->p_filter = cldfb_protoFilter_5_0ms[4]; + hs->p_filter = LDQMF_40_fx; hs->scale = cldfb_scale_5_0ms[4]; #endif } @@ -3131,7 +3133,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_re_fx = NULL; hs->rot_vec_syn_delay_im_fx = NULL; hs->p_filter_sf = (Word16) 17051; - hs->p_filter = cldfb_protoFilter_2_5ms[5]; + hs->p_filter = CLDFB80_60_fx; hs->scale = cldfb_scale_2_5ms[5]; #endif } @@ -3151,7 +3153,7 @@ static void cldfb_init_proto_and_twiddles_enc( hs->rot_vec_syn_delay_re_fx = rot_vec_delay_re_LDQMF_fx; hs->rot_vec_syn_delay_im_fx = rot_vec_delay_im_LDQMF_fx; hs->p_filter_sf = (Word16) 15391; - hs->p_filter = cldfb_protoFilter_5_0ms[5]; + hs->p_filter = LDQMF_60_fx; hs->scale = cldfb_scale_5_0ms[5]; #endif } diff --git a/lib_com/cnst.h b/lib_com/cnst.h index 3543fe64d..f16284aaf 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -745,6 +745,7 @@ enum #define PIT_UP_SAMP6 6 #define PIT_L_INTERPOL6_2 17 #define PIT_FIR_SIZE6_2 ( PIT_UP_SAMP6 * PIT_L_INTERPOL6_2 + 1 ) +#define E_MIN_Q11_FX 7 /* minimum allowable energy in Q11*/ #define E_MIN 0.0035f /* minimum allowable energy */ #define E_MIN_Q11_FX 7 /* minimum allowable energy in Q11*/ #define STEP_DELTA 0.0625f /* quantization step for tilt compensation of gaussian cb. excitation */ @@ -1010,6 +1011,7 @@ typedef enum #define BWD_COUNT_MAX 100 /* maximum value of BWD counter */ #define BWD_N_BINS_MAX 13 /* maximum number of BWD bins */ #define BWS_TRAN_PERIOD 5 /* BWS - number of frames for transition period */ +#define ONE_BY_BWS_TRAN_PERIOD_Q15 6554 #define PREEMPH_FAC_FLT 0.68f /* preemphasis factor at 12.8kHz */ #define PREEMPH_FAC_16k_FLT 0.72f @@ -1953,10 +1955,14 @@ typedef enum _DCTTYPE #define ATT_NSEG 32 /* strong attack detection - number of time blocks */ #define TOD_NSPEC 80 /* number of spectral bins of the tonal detector */ +#define TOD_NSPEC_INV_Q31 26843546 /* inverse of number of spectral bins of the tonal detector */ #define TOD_THR_MASS 0.86f /* initial value for the adaptive threshold of the tonal detector */ #define P2A_FACT 0.9f /* long-term averaging factor for peak-to-average ratio */ +#define P2A_FACT_FX_Q15 29491 /* long-term averaging factor for peak-to-average ratio */ #define THR_P2A_HIGH 95.0f /* higher threshold to detect strongly peaky signals at low bitrates*/ #define THR_P2A 80.0f /* lower threshold to detect strongly peaky signals at higher bitrates */ +#define THR_P2A_HIGH_FX 95 /* Q0, higher threshold to detect strongly peaky signals at low bitrates*/ +#define THR_P2A_FX 80 /* Q0, lower threshold to detect strongly peaky signals at higher bitrates */ /*----------------------------------------------------------------------------------* * LD music post-filter constants diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index d6ac3843e..861e7517a 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -644,7 +644,9 @@ typedef enum #define STEREO_DFT_RES_GAINS_BITS 3 #define STEREO_DFT_RES_COD_SNR_MIN 10 +#define STEREO_DFT_RES_COD_SNR_MIN_Q25 335544320 #define STEREO_DFT_RES_COD_SNR_MAX 40 +#define STEREO_DFT_RES_COD_SNR_MAX_Q25 1342177280 #define STEREO_DFT_L_SUBFR_8k 32 #define STEREO_DFT_NBPSF_PIT_MAX_8k NBPSF_PIT_MAX / 2 @@ -727,6 +729,7 @@ enum #define ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO 127 /* indicates that all values in the vector are zero */ #define ECLVQ_GLOBAL_GAIN_FACTOR ( 20.0f * 127.0f / 90.0f ) +#define ECLVQ_GLOBAL_GAIN_FACTOR_Q26 1893961218 #define ECLVQ_INV_GLOBAL_GAIN_FACTOR ( 1.0f / ( 20.0f * 127.0f / 90.0f ) ) #define ECLVQ_INV_GLOBAL_GAIN_FACTOR_Q24 594468 diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index d746b0ec1..f65fca8e8 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -258,6 +258,7 @@ ivas_error pre_proc_front_ivas_fx( const int16_t nb_bits_metadata, /* i : number of metadata bits */ const int16_t input_frame, /* i : frame length */ const int16_t n, /* i : channel number */ + Word16 old_inp_12k8_fx[], /* o : buffer of old input signal */ float old_inp_12k8[], /* o : buffer of old input signal */ float old_inp_16k[], /* o : buffer of old input signal @16kHz */ float *ener, /* o : residual energy from Levinson-Durbin */ @@ -279,6 +280,7 @@ ivas_error pre_proc_front_ivas_fx( int16_t *vad_flag_dtx, /* o : HE-SAD flag with additional DTX HO */ float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* o : energy buffer */ float fft_buff[2 * L_FFT], /* o : FFT buffer */ + Word16 fft_buff_fx[2 * L_FFT], /* o : FFT buffer */ const float tdm_A_PCh[M + 1], /* i : unq. LP coeff. of primary channel */ const float tdm_lsp_new_PCh[M], /* i : unq. LSPs of primary channel */ const float currFlatness, /* i : flatness parameter */ @@ -1797,6 +1799,7 @@ void stereo_dft_enc_process( ); #endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_res( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ const float *input_8k, /* i : input buffer sampled at 8kHz */ @@ -1804,11 +1807,14 @@ void stereo_dft_enc_res( int16_t *nb_bits, /* o : number of bits written */ const int16_t max_bits ); +#endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_write_BS( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ int16_t *nb_bits /* o : number of bits written */ ); +#endif void stereo_dtf_cng( CPE_DEC_HANDLE hCPE, /* i/o: CPE decoder structure */ @@ -1857,6 +1863,7 @@ void stereo_dft_dequantize_itd( const int32_t output_Fs ); +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_sid_calc_coh( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ float prev_cohBand[2*(STEREO_DFT_BAND_MAX/2)], /* i/o: Previous coherence */ @@ -1864,7 +1871,9 @@ void stereo_dft_enc_sid_calc_coh( int16_t *first_SID, /* i/o: First SID indicator */ float *cohBand /* i/o: Coherence per band */ ); +#endif +#ifndef IVAS_FLOAT_FIXED void stereo_dft_enc_sid_coh( BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ float *mem_cohBand, /* i/o: Coherence memory */ @@ -1872,6 +1881,7 @@ void stereo_dft_enc_sid_coh( int16_t *nb_bits, /* i/o: number of bits written */ float *cohBand /* i/o: Coherence per band */ ); +#endif #ifdef IVAS_FLOAT_FIXED void stereo_dft_dec_sid_coh_fx( Decoder_State *st, /* i/o: decoder state structure */ @@ -2476,18 +2486,22 @@ float ECSQ_dequantize_gain( const int16_t index ); +#ifndef IVAS_FLOAT_FIXED void ECSQ_quantize_vector( const float *input, const float global_gain, const int16_t N, int16_t *output ); +#endif +#ifndef IVAS_FLOAT_FIXED float ECSQ_compute_optimal_gain( const float *input, const int16_t N, const int16_t *output ); +#endif void ECSQ_init_instance( ECSQ_instance *ecsq_inst, @@ -2495,6 +2509,7 @@ void ECSQ_init_instance( void *ac_handle ); +#ifndef IVAS_FLOAT_FIXED int32_t ECSQ_encode_target_SNR( ECSQ_instance *ecsq_inst, const float *input, @@ -2504,6 +2519,7 @@ int32_t ECSQ_encode_target_SNR( float *output, int16_t *global_gain_index_output ); +#endif // IVAS_FLOAT_FIXED #ifndef IVAS_FLOAT_FIXED void ECSQ_decode( diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 285c69eaa..a30457c37 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -849,6 +849,11 @@ void td_stereo_param_updt_fx( #endif ); +void updt_enc_common_ivas_fx( + Encoder_State *st /* i/o: encoder state structure */ +); + + void updateBuffersForDmxMdctStereo_fx( CPE_DEC_HANDLE hCPE, /* i/o: CPE handle */ const Word16 output_frame, /* i : output frame length */ @@ -2741,6 +2746,58 @@ void stereo_cng_upd_counters_fx( Word16 *coh_fade_counter /* i : Coherence fade counter */ ); + +void stereo_dft_enc_sid_calc_coh_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + Word32 prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence Q31 */ + Word16 *td_active, /* i/o: TD stereo mode indicator */ + Word16 *first_SID, /* i/o: First SID indicator */ + Word32 *cohBand /* i/o: Coherence per band Q31 */ +); + +void stereo_dft_enc_sid_coh_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word32 *mem_cohBand, /* i/o: Coherence memory */ + const Word16 nbands, /* i : number of DFT stereo bands */ + Word16 *nb_bits, /* i/o: number of bits written */ + Word32 *cohBand /* i/o: Coherence per band */ +); + +void stereo_dft_enc_write_BS_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + Word16 *nb_bits /* o : number of bits written */ +); + +void stereo_dft_enc_res_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + const Word32 *input_8k, /* i : input buffer sampled at 8kHz Q16 */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word16 *nb_bits, /* o : number of bits written */ + const Word16 max_bits ); + +Word32 ECSQ_encode_target_SNR_fx( + ECSQ_instance *ecsq_inst, + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word32 target_SNR, // Q25 + const Word16 max_bits, + Word32 *output, + Word16 *global_gain_index_output ); + +void ECSQ_quantize_vector_fx( + const Word32 *input, + const Word16 input_e, + const Word32 global_gain, // Q15 + const Word16 N, + Word16 *output ); + +Word32 ECSQ_compute_optimal_gain_fx( // Q15 + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word16 *output ); + void spectral_balancer_fx16( Word16 *signal, /* i/o : signal Qx */ Word16 *mem, /* i/o : mem Qx */ @@ -2863,4 +2920,25 @@ void stereo_tcx_core_enc( const Word16 vad_hover_flag /* i : VAD hangover flag, Q0 */ ); + +Word16 transient_analysis_ivas_fx( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const Word16 cor_map_LT[], /* i : LT correlation map Q_cor_map = Qx */ + Word16 Q_cor_map, + const Word16 multi_harm_limit, /* i : multi harmonic threshold Q_multi_harm_limit = Qx */ + Word16 Q_multi_harm_limit ); + +void ivas_smc_mode_selection_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 element_brate, /* i : element bitrate */ + Word16 smc_dec, /* i : raw decision of the 1st stage classifier*/ + const Word16 relE, /* i : relative frame energy, Q8 */ + const Word16 Etot, /* i : total frame energy, Q8 */ + Word16 *attack_flag, /* i/o: attack flag (GSC or TC) */ + const Word16 *inp, /* i : input signal */ + const Word16 Q_new, /* i : Q of input signal */ + const Word16 S_map[], /* i : short-term correlation map, Q7 */ + const Word16 flag_spitch /* i : flag to indicate very short stable pitch*/ +); + #endif diff --git a/lib_com/ivas_rom_com.h b/lib_com/ivas_rom_com.h index 679dbe800..ff7917019 100644 --- a/lib_com/ivas_rom_com.h +++ b/lib_com/ivas_rom_com.h @@ -159,9 +159,11 @@ extern const float nf_tw_smoothing_coeffs[N_LTP_GAIN_MEMS]; * Stereo DTX ROM tables *----------------------------------------------------------------------------------*/ +extern const Word16 dft_cng_coh_pred_fx[][STEREO_DFT_COH_PRED_COEFFS]; extern const float dft_cng_coh_pred[][STEREO_DFT_COH_PRED_COEFFS]; extern const int16_t dft_cng_coh_u2i[9]; extern const int16_t dft_cng_coh_i2u[9]; +extern const Word16 dft_cng_alpha_bits_fx[STEREO_DFT_N_COH_ALPHA_STEPS][STEREO_DFT_N_COH_ALPHA_LEVELS]; extern const float dft_cng_alpha_bits[STEREO_DFT_N_COH_ALPHA_STEPS][STEREO_DFT_N_COH_ALPHA_LEVELS]; extern const int16_t dft_cng_coh_alpha_start[STEREO_DFT_N_COH_ALPHA_STEPS - 1]; diff --git a/lib_com/modif_fs_fx.c b/lib_com/modif_fs_fx.c index c84dc802a..9c490a012 100644 --- a/lib_com/modif_fs_fx.c +++ b/lib_com/modif_fs_fx.c @@ -39,6 +39,303 @@ /*------------------------------------------------------------------------------*/ /* CALLED FROM : TX/RX */ /*==============================================================================*/ +Word16 modify_Fs_ivas_fx( /* o : length of output Q0 */ + const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ + Word16 lg, /* i : length of input Q0 */ + const Word32 fin, /* i : frequency of input Q0 */ + Word16 sigOut_fx[], /* o : decimated signal Q0 */ + const Word32 fout, /* i : frequency of output Q0 */ + Word16 mem_fx[], /* i/o: filter memory Q0 */ + const Word16 nblp, /* i : flag indicating if NB low-pass is applied */ + Word16 *Q_new_inp, /*scaling added on sigOut_fx */ + Word16 *mem_decim_size /*i: size modified for mem_fx*/ +) +{ + Word16 i; + + Word16 lg_out, fac_num, fac_den, filt_len, frac, temp_n, mem_len; + Word16 num_den; + Word16 datastep, fracstep; + Word16 *sigIn_ptr, *sigPtr; + Word16 signal_tab_fx[3 * L_FILT_MAX + L_FRAME48k], *signal_fx, *signal_ana_fx; /* 3* as 2* for memory and 1* for future prediction */ + Word16 A_fx[M + 1], r_fx_h[M + 1], r_fx_l[M + 1]; + Word16 mem_len_ana; + Word16 plus_sample_in; + Word16 j; + Word16 mu_preemph_fx; + Word16 mem_preemph_fx; + Word16 Q_r; + Word16 mem_lev_fx[18]; + Word32 t0, t1, t2, L_tmp; /* temporary variables */ + Word32 LepsP[M + 1]; + Word16 flag_low_order = 0; + move16(); + Word16 filt_len_tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + const Resampling_cfg *cfg_ptr_fx; + + /*-------------------------------------------------------------------* + * Find the resampling configuration + *-------------------------------------------------------------------*/ + *Q_new_inp = 0; + move16(); + /* check if fin and fout are the same */ + IF( EQ_32( fin, fout ) ) + { + /* just copy the signal_fx and quit */ + Copy( sigIn_fx, sigOut_fx, lg ); + *mem_decim_size = 0; + *Q_new_inp = 0; + move16(); + move16(); + return lg; + } + ELSE + { + /* find the resampling configuration in the lookup table */ + cfg_ptr_fx = &resampling_cfg_tbl[0]; + WHILE( ( cfg_ptr_fx->fin_fx != 0 ) && !( EQ_32( cfg_ptr_fx->fin_fx, fin ) && EQ_32( cfg_ptr_fx->fout_fx, fout ) ) ) + { + test(); + test(); + cfg_ptr_fx++; + } + + + /* find config with NB 4kHz low-pass */ + test(); + test(); + IF( nblp && ( GT_32( fin, 8000 ) ) && ( EQ_32( fout, 12800 ) ) ) + { + flag_low_order = 1; + move16(); + cfg_ptr_fx++; + WHILE( ( cfg_ptr_fx->fin_fx != 0 ) && !( ( EQ_32( cfg_ptr_fx->fin_fx, fin ) ) && ( EQ_32( cfg_ptr_fx->fout_fx, fout ) ) ) ) + { + test(); + test(); + cfg_ptr_fx++; + } + } + + /*-------------------------------------------------------------------* + * Retrieve and/or calculate the resampling parameters + *-------------------------------------------------------------------*/ + fac_num = cfg_ptr_fx->fac_num_fx; + move16(); /*Q0*/ + fac_den = cfg_ptr_fx->fac_den_fx; + move16(); + + lg_out = idiv1616( i_mult2( lg, fac_num ), fac_den ); + filt_len = cfg_ptr_fx->filt_len_fx; + move16(); + plus_sample_in = 0; + move16(); /*default, regular delay*/ + frac = 0; + move16(); + + test(); + IF( ( EQ_32( fin, 8000 ) ) && ( EQ_32( fout, 12800 ) ) ) + { + plus_sample_in = 7; + move16(); + frac = 4; + move16(); + } + + mem_len = shl( filt_len, 1 ); + *mem_decim_size = mem_len; + move16(); + signal_fx = signal_tab_fx + 2 * L_FILT_MAX + sub( L_FRAME48k, add( mem_len, lg ) ); + signal_ana_fx = signal_fx; + mem_len_ana = mem_len; + move16(); + } + + + /*-------------------------------------------------------------------* + * Resample + *-------------------------------------------------------------------*/ + /* append filter memory */ + Copy( mem_fx, signal_fx, mem_len ); + + sigPtr = signal_fx + mem_len; + Copy( sigIn_fx, sigPtr, lg ); + + IF( plus_sample_in > 0 ) + { + autocorr_fx( signal_ana_fx + mem_len_ana + lg - LEN_WIN_SSS, 1, r_fx_h, r_fx_l, &Q_r, LEN_WIN_SSS, wind_sss_fx, 0, 0 ); + + + t1 = L_Comp( r_fx_h[1], r_fx_l[1] ); /* R[1] in Q31 */ + t2 = L_abs( t1 ); /* abs R[1] */ + t0 = L_deposit_l( 0 ); + IF( r_fx_h[0] != 0 ) + { + t0 = Div_32( t2, r_fx_h[0], r_fx_l[0] ); /* R[1]/R[0] in Q31 */ + } + if ( t1 < 0 ) + { + t0 = L_negate( t0 ); /* R[1]/R[0] */ + } + + + mu_preemph_fx = extract_h( t0 ); /*r_fx[1] / r_fx[0]; */ + mem_preemph_fx = signal_ana_fx[mem_len_ana + lg - LEN_WIN_SSS - 1]; + move16(); + PREEMPH_FX( signal_ana_fx + mem_len_ana + lg - LEN_WIN_SSS, mu_preemph_fx, LEN_WIN_SSS, &mem_preemph_fx ); + + + /* Autocorrelations */ + autocorr_fx( signal_ana_fx + mem_len_ana + lg - LEN_WIN_SSS, M, r_fx_h, r_fx_l, &Q_r, + LEN_WIN_SSS, wind_sss_fx, 0, 0 ); + + /* Lag windowing */ + lag_wind( r_fx_h, r_fx_l, M, fin, LAGW_STRONG ); + + /* Levinson-Durbin */ + set16_fx( mem_lev_fx, 0, 18 ); + E_LPC_lev_dur( r_fx_h, r_fx_l, A_fx, LepsP, M, NULL ); + + Copy_Scale_sig( A_fx, A_fx, M + 1, sub( norm_s( A_fx[0] ), 2 ) ); + + FOR( i = 0; i < plus_sample_in; i++ ) + { + sigPtr = signal_fx + add( lg, add( mem_len, i ) ); + L_tmp = syn_kern_16( 0, A_fx, sigPtr ); +#ifdef BASOP_NOGLOB + L_tmp = L_shl_sat( L_tmp, 3 ); + *sigPtr = round_fx_sat( L_tmp ); /* AZ ringing padding */ +#else + L_tmp = L_shl( L_tmp, 3 ); + *sigPtr = round_fx( L_tmp ); /* AZ ringing padding */ +#endif + move16(); + } + mem_preemph_fx = signal_fx[mem_len + lg - LEN_WIN_SSS - 1]; + move16(); + deemph_fx( signal_fx + mem_len + lg - LEN_WIN_SSS, mu_preemph_fx, LEN_WIN_SSS + plus_sample_in, &mem_preemph_fx ); + } + /* interpolation */ + + datastep = shr( div_s( shl( fac_den, 7 ), shl( fac_num, 10 ) ), 12 ); + /* equivalent to 'datastep = fac_den % fac_num' */ + temp_n = i_mult2( datastep, fac_num ); /*Q0*/ + fracstep = sub( fac_den, temp_n ); + + sigIn_ptr = signal_fx + add( filt_len, plus_sample_in ); + + filt_len_tmp = filt_len; + move16(); + IF( flag_low_order ) + { + filt_len_tmp = shr( add( filt_len, 1 ), 1 ); + } + + Word16 norm_cfg_ptr = norm_s( sub( cfg_ptr_fx->filter_fx[0], 1 ) ); + FOR( i = 0; i < lg_out; i++ ) + { +#ifdef BASOP_NOGLOB + sigOut_fx[i] = round_fx_sat( Interpol_lc_fx( sigIn_ptr, cfg_ptr_fx->filter_fx, frac, fac_num, filt_len_tmp ) ); +#else + sigOut_fx[i] = round_fx( Interpol_lc_fx( sigIn_ptr, cfg_ptr_fx->filter_fx, frac, fac_num, filt_len_tmp ) ); +#endif + move16(); + frac = add( frac, fracstep ); + + j = sub( fac_num, frac ); + if ( j < 0 ) + { + frac = sub( frac, fac_num ); + } + sigIn_ptr += add( lshr( j, 15 ), datastep ); + } + *Q_new_inp = negate( norm_cfg_ptr ); + move16(); + /* rescaling */ + test(); + + IF( EQ_32( ( GT_16( fac_num, fac_den ) ), ( ( cfg_ptr_fx->flags_fx & RS_INV_FAC ) != 0 ) ) ) + { + IF( LT_16( fac_num, fac_den ) ) + { + num_den = div_s( fac_num, fac_den ); /*Q15*/ + test(); + IF( GT_32( fin, 16000 ) && EQ_16( lg_out, 512 ) ) + { + + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = round_fx( L_shl( L_mult( sigOut_fx[i], num_den ), 1 ) ); /*Q0*/ + move16(); + } + *Q_new_inp = add( *Q_new_inp, 1 ); + move16(); + } + ELSE + { + test(); + test(); + test(); + if ( GT_32( fin, 16000 ) && ( EQ_16( lg_out, L_FRAME ) || EQ_16( lg_out, L_FRAME16k ) || EQ_16( lg_out, 512 ) ) ) + { +#ifdef BASOP_NOGLOB + num_den = shl_o( num_den, 1, &Overflow ); + *Q_new_inp = add( *Q_new_inp, 1 ); + move16(); +#else + num_den = shl( num_den, 1 ); +#endif + } + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = mult_r( sigOut_fx[i], num_den ); /*Q0*/ + move16(); + } + } + } + ELSE + { + IF( EQ_16( fac_num, 8 ) ) + { + num_den = 26214; + move16(); + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = mult_r( sigOut_fx[i], num_den ); /*Q-1*/ + move16(); + } + } + ELSE + { + num_den = div_s( sub( fac_num, fac_den ), fac_den ); /*Q15*/ + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = round_fx( L_mac( L_deposit_h( sigOut_fx[i] ), sigOut_fx[i], num_den ) ); /*Q0*/ + move16(); + } + *Q_new_inp = add( *Q_new_inp, 1 ); + move16(); + } + } + } + ELSE IF( ( LT_16( fac_num, fac_den ) ) && ( ( cfg_ptr_fx->flags_fx & RS_INV_FAC ) != 0 ) ) + { + FOR( i = 0; i < lg_out; i++ ) + { + sigOut_fx[i] = mult_r( sigOut_fx[i], 16384 ); + move16(); /*Q-1*/ + } + } + /* update the filter memory */ + sigPtr = signal_fx + lg; + Copy( sigPtr, mem_fx, mem_len ); + + return lg_out; +} Word16 modify_Fs_fx( /* o : length of output Q0 */ const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ Word16 lg, /* i : length of input Q0 */ diff --git a/lib_com/prot.h b/lib_com/prot.h index 1383ec487..c64a09f87 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -9197,8 +9197,10 @@ void analysisCldfbEncoder_ivas( float *ppBuf_Ener ); void analysisCldfbEncoder_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - const Word16 *timeIn, + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 *timeIn, /*q11*/ + Word16 timeInq, /*q0*/ + Word16 samplesToProcess, /*q0*/ Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 58f0ea49a..18d1b9266 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -2436,6 +2436,17 @@ Word32 Interpol_lc_fx( /* o : interpolated value const Word16 nb_coef /* i : number of coefficients Q0 */ ); +Word16 modify_Fs_ivas_fx( /* o : length of output Q0 */ + const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ + Word16 lg, /* i : length of input Q0 */ + const Word32 fin, /* i : frequency of input Q0 */ + Word16 sigOut_fx[], /* o : decimated signal Q0 */ + const Word32 fout, /* i : frequency of output Q0 */ + Word16 mem_fx[], /* i/o: filter memory Q0 */ + const Word16 nblp, /* i : flag indicating if NB low-pass is applied */ + Word16 *Q_new_inp, /*scaling added on sigOut_fx */ + Word16 *mem_decim_size /*i: size modified for mem_fx*/ +); // modif_fs_fx.c Word16 modify_Fs_fx( /* o : length of output Q0 */ const Word16 sigIn_fx[], /* i : signal to decimate Q0 */ @@ -2681,6 +2692,13 @@ void save_old_syn_fx( ); // swb_tbe_com_fx.c +void find_td_envelope_fx( + const Word16 inp[], /* i : input signal Qx */ + const Word16 len, /* i : length of the input signal */ + const Word16 len_h, /* i : length of the MA filter */ + Word16 mem_h[], /* i/o: memory of the MA filter, length len_h/2 Qx */ + Word16 out[] /* o : td envelope of the input signal Qx */ +); void swb_tbe_reset_fx( Word32 mem_csfilt[], @@ -3577,6 +3595,13 @@ void nelp_encoder_fx( Word16 *qIn1, Word16 reduce_gains ); +void nelp_encoder_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state */ + Word16 *in_fx, /* i : residual signal */ + Word16 *exc_fx, /* o : NELP quantized excitation signal */ + Word16 *qIn1, + Word16 reduce_gains ); + /*========================================================================================================/ swb_bwe_enc_lr_fx.c /========================================================================================================*/ @@ -9800,6 +9825,11 @@ Word16 mean_fx( /* o : mean of vector const Word16 lvec_fx /* i : length of i vector */ ); +Word16 mean_no_sat_fx( /* o : mean of vector Qx */ + const Word16 *vec_fx, /* i : input vector Qx */ + const Word16 lvec_fx /* i : length of input vector */ +); + void sort( UWord16 *x, /* i/o: Vector to be sorted */ UWord16 len /* i/o: vector length */ @@ -10492,14 +10522,31 @@ Word16 sr2fscale( // pre_proc functions /*full implementation pending*/ + +void Copy_Scale_sig32( + const Word32 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +); + void swb_pre_proc_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - float *new_swb_speech, /* o : original input signal at 32kHz */ - Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz */ - float *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz */ - float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer */ - float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer */ - CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ + Encoder_State *st, /* i/o: encoder state structure */ + Word16 *new_swb_speech, /* o : original input signal at 32kHz - Q0 */ + Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz - Q - q_reImBuffer */ + Word16 *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz- Q0 */ + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer Q - q_reImbuffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer Q - q_reImbuffer */ + Word16 q_reImBuffer, /* i : scale data of real and imag CLDFB buffers */ + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ +); + +void core_encode_update_ivas_fx( + Encoder_State *st /* i/o: Encoder state structure */ +); + +void updt_enc_common_ivas_fx( + Encoder_State *st /* i/o: encoder state structure */ ); // tools.c @@ -10509,6 +10556,13 @@ Word32 sum2_f_32_fx( /* o : Q(2x - 31 - gb) Word16 gb /* i : guard bits */ ); +Word32 sum2_16_exp_fx( + const Word16 *vec, /* i : input vector Q(15 - exp) */ + const Word16 lvec, /* i : length of input vector */ + Word16 *exp, /* i/o: exponent of vector */ + Word16 gb /* i : guard bits */ +); + Word32 sum2_32_exp_fx( const Word32 *vec, /* i : input vector, Qx */ const Word16 lvec, /* i : length of input vector */ diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index 3c2987322..3bf5740f5 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -184,6 +184,9 @@ extern const FrameSizeParams FrameSizeConfig[FRAME_SIZE_NB]; extern const float h_high[]; /* HP filter for filtering random part of excitation in FEC */ extern const Word16 h_high_fx[5]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 crit_bands_fx[]; +#endif // IVAS_FLOAT_FIXED extern const float crit_bands[]; /* Table of critical bands */ extern const float sincos_t[]; /* FFT - sinus and cosinus tables */ extern const Word16 sincos_t_fx[161]; diff --git a/lib_com/swb_tbe_com_fx.c b/lib_com/swb_tbe_com_fx.c index 456ab2bc3..2f66f11ca 100644 --- a/lib_com/swb_tbe_com_fx.c +++ b/lib_com/swb_tbe_com_fx.c @@ -18,6 +18,8 @@ #define POW_EXC16k_WHTND 1.14e11f /* power of random excitation, length 320 samples, uniform distribution */ #define POW_EXC16k_WHTND_FX_INV_SQRT 6360 // Q31 #define POW_EXC16k_WHTND_FX 178125000 // Q-6 +#define THR_ENV_ERROR_PLOSIVE 200.0f /* threshold for envelope error used in plosive detection */ +#define THR_ENV_ERROR_PLOSIVE_FX 200 /* threshold for envelope error used in plosive detection Q0 */ /*-----------------------------------------------------------------* * Local function prototypes @@ -1806,73 +1808,92 @@ void GenWBSynth_fx( return; } -#ifdef ADD_IVAS_TBE_CODE -void find_td_envelope( - const float inp[], /* i : input signal */ - const int16_t len, /* i : length of the input signal */ - const int16_t len_h, /* i : length of the MA filter */ - float mem_h[], /* i/o: memory of the MA filter, length len_h/2 */ - float out[] /* o : td envelope of the input signal */ + + +void find_td_envelope_fx( + const Word16 inp[], /* i : input signal Qx */ + const Word16 len, /* i : length of the input signal */ + const Word16 len_h, /* i : length of the MA filter */ + Word16 mem_h[], /* i/o: memory of the MA filter, length len_h/2 Qx */ + Word16 out[] /* o : td envelope of the input signal Qx */ ) { - int16_t k, K; - float buf_in[L_FRAME16k + MAX_LEN_MA_FILTER], *p_in, *p_out, *p_prev, w; + Word16 k, K; + Word16 buf_in[L_FRAME16k + MAX_LEN_MA_FILTER], *p_in, *p_out, *p_prev, w; + Word16 tmp1, tmp2; assert( len > 0 && len <= L_FRAME16k ); - K = (int16_t) ( len_h / 2 ); /* length of FIR filter memory = half of the total filter length */ - w = 1.0f / len_h; /* MA filtering coefficient */ + // len_h is 20 at all calling locations + K = 10; /* length of FIR filter memory = half of the total filter length */ + move16(); + w = 1639; /* 1 / 20 in Q15 */ /* MA filtering coefficient */ + move16(); /* copy filter memory to the input buffer */ - if ( mem_h != NULL ) + IF( mem_h != NULL ) { - mvr2r( mem_h, buf_in, K ); + Copy( mem_h, buf_in, K ); } - else + ELSE { /* no memory available, use the first len_h/2 samples as memory */ p_in = buf_in; - for ( k = 0; k < K; k++ ) + FOR( k = 0; k < K; k++ ) { - *p_in++ = (float) fabs( inp[k] ) * w; + *p_in++ = mult_r( abs_s( inp[k] ), w ); /* Qx */ + move16(); } } /* take the absolute value of the input signal and copy it to the input buffer */ /* multiply each value by 1 / filter length */ p_in = &buf_in[K]; - for ( k = 0; k < len; k++ ) + FOR( k = 0; k < len; k++ ) { - *p_in++ = (float) fabs( inp[k] ) * w; + *p_in++ = mult_r( abs_s( inp[k] ), w ); /* Qx */ + move16(); } /* update filter memory from the end of the input buffer */ - if ( mem_h != NULL ) + IF( mem_h != NULL ) { - mvr2r( &buf_in[len], mem_h, K ); + Copy( &buf_in[len], mem_h, K ); } /* do MA filtering */ - out[0] = sum_f( buf_in, len_h ); + out[0] = sum16_fx( buf_in, len_h ); + move16(); p_out = &buf_in[0]; /* pointer to leaving sample */ p_in = &buf_in[len_h]; /* pointer to entering sample*/ - for ( k = 1; k < len - K; k++ ) + FOR( k = 1; k < len - K; k++ ) { - out[k] = out[k - 1] - *p_out++ + *p_in++; + tmp1 = *p_out++; + move16(); + tmp2 = *p_in++; + move16(); + out[k] = add( sub( out[k - 1], tmp1 ), tmp2 ); /* Qx */ + move16(); } /* use IIR filtering to extrapolate the last K samples */ p_in = &buf_in[len - K]; p_out = &out[len - K]; p_prev = p_out - 1; - for ( k = 0; k < K; k++ ) + FOR( k = 0; k < K; k++ ) { - *p_out++ = 0.05f * ( *p_in++ ) + 0.95f * ( *p_prev++ ); + tmp1 = *p_in++; + move16(); + tmp2 = *p_prev++; + move16(); + *p_out++ = add( mult_r( 1638 /* 0.05f in Q15 */, ( tmp1 ) ), mult_r( 31130 /* 0.95f in Q15 */, ( tmp2 ) ) ); + move16(); } return; } -#endif + + /*======================================================================================*/ /* FUNCTION : void GenShapedSHBExcitation_fx () */ /*--------------------------------------------------------------------------------------*/ @@ -2762,24 +2783,21 @@ void GenShapedSHBExcitation_ivas_fx( Word16 *Q_bwe_exc, Word16 *Q_bwe_exc_fb, const Word16 Q_shb, - Word16 n_mem2, /* i : n_mem2 scale factor to adjust 24.4/32kbps memories */ - Word16 prev_Q_bwe_syn, /* i : st_fx->prev_Q_bwe_syn */ - const Word32 bitrate, - const Word16 prev_bfi -#if 1 // def ADD_IVAS_TBE_CODE - , /* i : previous frame was concealed */ - const Word16 element_mode, /* i : element mode */ - const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ - Word16 *nlExc16k, /* i/o: NL exc for IC-BWE */ - Word16 *mixExc16k, /* i/o: exc spreading for IC-BWE */ - const Word32 extl_brate, /* i : extension layer bitarte */ - const Word16 MSFlag, /* i : Multi Source flag */ - Word16 EnvSHBres_4k[], /* i/o: TD envelope of the SHB residual signal */ - Word32 *prev_pow_exc16kWhtnd, /* i/o: power of the LB excitation signal in the previous frame */ - Word16 *prev_mix_factor, /* i/o: mixing factor in the previous frame */ - Word16 *Env_error, /* o : error in SHB residual envelope modelling*/ - Word16 Env_error_part[] /* o : per-segment error in SHB residual envelope modelling */ -#endif + Word16 n_mem2, /* i : n_mem2 scale factor to adjust 24.4/32kbps memories */ + Word16 prev_Q_bwe_syn, /* i : st_fx->prev_Q_bwe_syn */ + const Word32 bitrate, /* i : bitrate */ + const Word16 prev_bfi, /* i : previous frame was concealed */ + const Word16 element_mode, /* i : element mode */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + Word16 *nlExc16k, /* i/o: NL exc for IC-BWE */ + Word16 *mixExc16k, /* i/o: exc spreading for IC-BWE */ + const Word32 extl_brate, /* i : extension layer bitarte */ + const Word16 MSFlag, /* i : Multi Source flag */ + Word16 EnvSHBres_4k[], /* i/o: TD envelope of the SHB residual signal */ + Word32 *prev_pow_exc16kWhtnd, /* i/o: power of the LB excitation signal in the previous frame */ + Word16 *prev_mix_factor, /* i/o: mixing factor in the previous frame */ + Word16 *Env_error, /* o : error in SHB residual envelope modelling Q0 */ + Word16 Env_error_part[] /* o : per-segment error in SHB residual envelope modelling Q0 */ ) { Word16 i, j, k; @@ -2791,7 +2809,7 @@ void GenShapedSHBExcitation_ivas_fx( Word32 LepsP[LPC_WHTN_ORDER + 1]; Word16 exc32k[L_FRAME32k], exc16k[L_FRAME16k]; Word32 pow1, pow22; - Word16 scale, temp1, temp2; + Word16 scale, temp1, temp2, temp3; Word16 excTmp2[L_FRAME16k]; Word16 *White_exc16k; @@ -2820,6 +2838,7 @@ void GenShapedSHBExcitation_ivas_fx( Word16 White_exc16k_FB_temp[L_FRAME16k]; Word32 White_exc16k_32[L_FRAME16k]; + Word16 White_exc16k_tmp[L_FRAME16k]; Word16 Q_temp; Word16 prev_Q_bwe_exc_fb; Word16 chk1, chk2; @@ -2830,14 +2849,16 @@ void GenShapedSHBExcitation_ivas_fx( Word16 alpha, step, mem_csfilt_left, mem_csfilt_right, excNoisyEnvLeft[L_FRAME16k], excNoisyEnvRight[L_FRAME16k]; Word16 cbsize; Word16 mix_factor, old_fact, new_fact, fact, old_scale, new_scale, step_scale; - Word16 c0, c1, c2, c3, c4, c5, g1, g2, g, den; + Word32 c0, c1, c2, c3, c4, c5, den; + Word16 g1, g2, g, g1_e, g2_e, g_e, den_e, shift, tmp_e, tmp1_e; Word16 EnvWhiteExc16k[L_FRAME16k], EnvExc16kWhtnd[L_FRAME16k]; Word16 EnvWhiteExc16k_4k[L_FRAME4k] = { 0 }, EnvExc16kWhtnd_4k[L_FRAME4k] = { 0 }; Word16 flag_plosive; Word16 delta; - Word16 c0_part[NUM_SHB_SUBGAINS], c1_part[NUM_SHB_SUBGAINS], c2_part[NUM_SHB_SUBGAINS], c3_part[NUM_SHB_SUBGAINS], c4_part[NUM_SHB_SUBGAINS], c5_part[NUM_SHB_SUBGAINS]; + Word32 c0_part[NUM_SHB_SUBGAINS], c1_part[NUM_SHB_SUBGAINS], c2_part[NUM_SHB_SUBGAINS], c3_part[NUM_SHB_SUBGAINS], c4_part[NUM_SHB_SUBGAINS], c5_part[NUM_SHB_SUBGAINS]; + Word64 W_tmp; - mix_factor = 0; + mix_factor = 0; /* Q15 */ move16(); #endif set16_fx( zero_mem, 0, LPC_SHB_ORDER ); @@ -3185,84 +3206,185 @@ void GenShapedSHBExcitation_ivas_fx( { IF( EQ_16( *vf_ind, 20 ) ) /* encoder side */ { -#ifdef ADD_IVAS_TBE_CODE // BELOW PART WILL NEED TO BE CONVERTED FOR ENCODER!! - if ( extl_brate == SWB_TBE_1k10 || extl_brate == SWB_TBE_1k75 ) +#ifndef ADD_IVAS_TBE_CODE // BELOW PART WILL NEED TO BE CONVERTED FOR ENCODER!! + test(); + IF( EQ_32( extl_brate, SWB_TBE_1k10 ) || EQ_32( extl_brate, SWB_TBE_1k75 ) ) { + FOR( k = 0; k < L_FRAME16k; k++ ) + { + White_exc16k_tmp[k] = round_fx( L_shl( White_exc16k_32[k], *Q_bwe_exc ) ); + move16(); + } + /* calculate TD envelopes of exc16kWhtnd and White_exc16k */ - find_td_envelope( White_exc16k, L_FRAME16k, 20, NULL, EnvWhiteExc16k ); - find_td_envelope( exc16kWhtnd, L_FRAME16k, 20, NULL, EnvExc16kWhtnd ); + find_td_envelope_fx( White_exc16k_tmp, L_FRAME16k, 20, NULL, EnvWhiteExc16k ); /* Q_bwe_exc */ + find_td_envelope_fx( exc16kWhtnd, L_FRAME16k, 20, NULL, EnvExc16kWhtnd ); /* Q_bwe_exc */ - for ( k = 0; k < L_FRAME4k; k++ ) + FOR( k = 0; k < L_FRAME4k; k++ ) { - EnvWhiteExc16k_4k[k] = EnvWhiteExc16k[4 * k]; - EnvExc16kWhtnd_4k[k] = EnvExc16kWhtnd[4 * k]; + EnvWhiteExc16k_4k[k] = EnvWhiteExc16k[4 * k]; /* Q_bwe_exc */ + move16(); + EnvExc16kWhtnd_4k[k] = EnvExc16kWhtnd[4 * k]; /* Q_bwe_exc */ + move16(); } /* calculate the optimal mix factor */ - c0 = c1 = c2 = c3 = c4 = c5 = 0.0f; - for ( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + c0 = c1 = c2 = c3 = c4 = c5 = 0; /* Q0 */ + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + + temp1 = add( shl( *Q_bwe_exc, 1 ), 1 ); + temp2 = add( add( Q_shb, *Q_bwe_exc ), 1 ); + temp3 = add( shl( Q_shb, 1 ), 1 ); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) { - c0_part[i] = sum2_f( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c1_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c2_part[i] = sum2_f( &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c3_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c4_part[i] = 2.0f * dotp( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); - c5_part[i] = sum2_f( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + // c0_part[i] = sum2_f( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c0_part[i] = L_shr( sum2_fx( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), temp1 ); /* Q0 */ + move32(); + // c1_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c1_part[i] = L_shr( L_negate( Dot_product( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ) ), sub( temp2, 1 ) ); /* Q0 */ + move32(); + // c2_part[i] = sum2_f( &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c2_part[i] = L_shr( sum2_fx( &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), temp1 ); /* Q0 */ + move32(); + // c3_part[i] = -2.0f * dotp( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c3_part[i] = L_shr( L_negate( Dot_product( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ) ), sub( temp2, 1 ) ); /* Q0 */ + move32(); + // c4_part[i] = 2.0f * dotp( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c4_part[i] = L_shr( Dot_product( &EnvExc16kWhtnd_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], &EnvWhiteExc16k_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), sub( temp1, 1 ) ); /* Q0 */ + move32(); + // c5_part[i] = sum2_f( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ); + c5_part[i] = L_shr( sum2_fx( &EnvSHBres_4k[i * L_FRAME4k / NUM_SHB_SUBGAINS], L_FRAME4k / NUM_SHB_SUBGAINS ), temp3 ); /* Q0 */ + move32(); + + c0 = L_add( c0, c0_part[i] ); + c1 = L_add( c1, c1_part[i] ); + c2 = L_add( c2, c2_part[i] ); + c3 = L_add( c3, c3_part[i] ); + c4 = L_add( c4, c4_part[i] ); + c5 = L_add( c5, c5_part[i] ); + } - c0 += c0_part[i]; - c1 += c1_part[i]; - c2 += c2_part[i]; - c3 += c3_part[i]; - c4 += c4_part[i]; - c5 += c5_part[i]; + // den = 4.0f * c0 * c2 - c4 * c4; + W_tmp = W_sub( W_shl( W_mult0_32_32( c0, c2 ), 2 ), W_mult0_32_32( c4, c4 ) ); + den_e = 63; + move16(); + shift = W_norm( W_tmp ); + den = W_extract_h( W_shl( W_tmp, shift ) ); + den_e = sub( den_e, shift ); + + IF( den == 0 ) + { + den = 1; + move32(); + den_e = 31; + move16(); } - den = 4.0f * c0 * c2 - c4 * c4; - g1 = ( c3 * c4 - 2 * c1 * c2 ) / den; - g2 = ( c1 * c4 - 2 * c0 * c3 ) / den; + // g1 = ( c3 * c4 - 2 * c1 * c2 ) / den; + W_tmp = W_sub( W_mult0_32_32( c3, c4 ), W_shl( W_mult0_32_32( c1, c2 ), 1 ) ); + g1_e = 63; + move16(); + shift = W_norm( W_tmp ); + L_tmp = W_extract_h( W_shl( W_tmp, shift ) ); + g1_e = sub( g1_e, shift ); - *Env_error = 0.0f; + g1 = BASOP_Util_Divide3232_Scale( L_tmp, den, &tmp_e ); + g1_e = sub( add( tmp_e, g1_e ), den_e ); + + // g2 = ( c1 * c4 - 2 * c0 * c3 ) / den; + W_tmp = W_sub( W_mult0_32_32( c1, c4 ), W_shl( W_mult0_32_32( c0, c3 ), 1 ) ); + g2_e = 63; + move16(); + shift = W_norm( W_tmp ); + L_tmp = W_extract_h( W_shl( W_tmp, shift ) ); + g2_e = sub( g2_e, shift ); + + g2 = BASOP_Util_Divide3232_Scale( L_tmp, den, &tmp_e ); + g2_e = sub( add( tmp_e, g2_e ), den_e ); + + // *Env_error = 0.0f; + *Env_error = 0; + move16(); flag_plosive = 0; - for ( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) { - Env_error_part[i] = c5_part[i] + g1 * g1 * c0_part[i] + g1 * c1_part[i] + g2 * g2 * c2_part[i] + g2 * c3_part[i] + g1 * g2 * c4_part[i]; - *Env_error += Env_error_part[i]; + // Env_error_part[i] = c5_part[i] + g1 * g1 * c0_part[i] + g1 * c1_part[i] + g2 * g2 * c2_part[i] + g2 * c3_part[i] + g1 * g2 * c4_part[i]; + L_tmp = BASOP_Util_Add_Mant32Exp( c5_part[i], 31, Mpy_32_32( L_mult( g1, g1 ), c0_part[i] ), add( shl( g1_e, 1 ), 31 ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_16_1( c1_part[i], g1 ), add( 31, g1_e ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_32( L_mult( g2, g2 ), c2_part[i] ), add( shl( g2_e, 1 ), 31 ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_16_1( c3_part[i], g2 ), add( 31, g2_e ), &tmp_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp, tmp_e, Mpy_32_32( L_mult( g1, g2 ), c4_part[i] ), add( add( g1_e, g2_e ), 31 ), &tmp_e ); + + // Env_error_part[i] = L_shr( L_tmp, 31 - tmp_e ); // Check Exponent + Env_error_part[i] = extract_h( L_shr_sat( L_tmp, sub( Q15, tmp_e ) ) ); /* Q0 */ + move16(); - if ( Env_error_part[i] > THR_ENV_ERROR_PLOSIVE ) + // *Env_error += Env_error_part[i]; + *Env_error = add_sat( *Env_error, Env_error_part[i] ); /* Q0 */ + move16(); + + if ( GT_16( Env_error_part[i], THR_ENV_ERROR_PLOSIVE_FX ) ) // Check which Q { /* envelope error is too high -> likely a plosive */ flag_plosive = 1; + move16(); } } - if ( flag_plosive ) + IF( flag_plosive ) { /* plosive detected -> set the mixing factor to 0 */ *vf_ind = 0; - mix_factor = 0.0f; + move16(); + mix_factor = 0; + move16(); } - else + ELSE { /* normalize gain */ - g = g2 / ( g1 + g2 ); + // g = g2 / ( g1 + g2 ); + tmp1_e = BASOP_Util_Add_MantExp( g1, g1_e, g2, g2_e, &tmp ); + IF( tmp == 0 ) + { + tmp = 1; + move16(); + tmp1_e = 15; + move16(); + } + g = BASOP_Util_Divide1616_Scale( g2, tmp, &tmp_e ); + g_e = sub( add( tmp_e, g2_e ), tmp1_e ); /* quantization of the mixing factor */ cbsize = 1 << NUM_BITS_SHB_VF; - delta = 1.0f / ( cbsize - 1 ); - if ( g > 1.0f ) + move16(); + // delta = 1.0f / ( cbsize - 1 ); + delta = 2341; /* Q14 */ + move16(); + // if ( g > 1.0f ) + IF( BASOP_Util_Cmp_Mant32Exp( g, add( 16, g_e ), ONE_IN_Q31, 0 ) > 0 ) { - g = 1.0f; + // g = 1.0f; + g = MAX16B; /* Q15 */ } - else if ( g < delta ) + // else if ( g < shl( delta, ( 15 - g_e ) - 14 ) ) + ELSE IF( BASOP_Util_Cmp_Mant32Exp( g, add( 16, g_e ), delta, 17 ) < 0 ) { /* prevent low gains to be quantized to 0 as this is reserved for plosives */ - g = delta; + // g = delta; + g = shl( delta, 1 ); /* Q15 */ } - *vf_ind = usquant( g, &mix_factor, 0.0f, 1.0f / ( cbsize - 1 ), cbsize ); + *vf_ind = usquant_fx( g, &mix_factor, 0, delta, cbsize ); + move16(); } } - else + ELSE #else UNUSED_PARAM( Env_error_part ); UNUSED_PARAM( Env_error ); diff --git a/lib_com/tools.c b/lib_com/tools.c index bdaacdf98..0222d6cc4 100644 --- a/lib_com/tools.c +++ b/lib_com/tools.c @@ -250,6 +250,35 @@ float sum2_f( } #ifdef IVAS_FLOAT_FIXED +Word32 sum2_16_exp_fx( + const Word16 *vec, /* i : input vector Q(15 - exp) */ + const Word16 lvec, /* i : length of input vector */ + Word16 *exp, /* i/o: exponent of vector */ + Word16 gb /* i : guard bits */ +) +{ + Word16 i, s; + Word32 L_tmp, var_a; + + L_tmp = 0; + move32(); + var_a = 0; + move32(); + FOR( i = 0; i < lvec; i++ ) + { + var_a = L_mult0( vec[i], vec[i] ); /* 2 * Q(15 - exp) */ + L_tmp = L_add( L_tmp, L_shr( var_a, gb ) ); /* 2 * Q(15 - exp) - gb */ + } + + s = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, s ); /* 2 * Q(15 - exp) - gb + s */ + + *exp = add( sub( add( shl( *exp, 1 ), gb ), s ), 1 ); + move16(); + + return L_tmp; +} + Word32 sum2_32_exp_fx( const Word32 *vec, /* i : input vector, Qx */ const Word16 lvec, /* i : length of input vector */ diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index 088a6037e..e23b7507a 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -958,6 +958,24 @@ Word16 mean_fx( /* o : mean of vector return tmp; } + +Word16 mean_no_sat_fx( /* o : mean of vector Qx */ + const Word16 *vec_fx, /* i : input vector Qx */ + const Word16 lvec_fx /* i : length of input vector */ +) +{ + Word16 i; + Word32 L_tmp = 0; + move32(); + FOR( i = 0; i < lvec_fx; ++i ) + { + L_tmp = L_add( L_tmp, vec_fx[i] ); + } + L_tmp = Mpy_32_16_1( L_tmp, div_s( 1, lvec_fx ) ); /* Qx */ + + return extract_l( L_tmp ); +} + /*-------------------------------------------------------------------* * Vr_add * @@ -2744,6 +2762,60 @@ void pz_filter_dp_fx( } } +/*-------------------------------------------------------------------* + * Copy_Scale_sig + * + * Up/down scale a 16 bits vector x and move it into y + *-------------------------------------------------------------------*/ +void Copy_Scale_sig32( + const Word32 x[], /* i : signal to scale input Qx */ + Word32 y[], /* o : scaled signal output Qx */ + const Word16 lg, /* i : size of x[] Q0 */ + const Word16 exp0 /* i : exponent: x = round(x << exp) Qx ?exp */ +) +{ + Word16 i; + Word32 L_tmp; + Word16 tmp = exp0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + IF( exp0 == 0 ) + { + FOR( i = 0; i < lg; i++ ) + { + y[i] = x[i]; + move32(); + } + return; + } + IF( exp0 < 0 ) + { + FOR( i = 0; i < lg; i++ ) + { +#ifdef BASOP_NOGLOB + y[i] = L_shl_o( x[i], tmp, &Overflow ); +#else + y[i] = L_shl( x[i], tmp ); +#endif + move16(); + } + return; + } +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o( 1, exp0 - 1, &Overflow ); +#else + tmp = shl( 1, exp0 ); +#endif + FOR( i = 0; i < lg; i++ ) + { + y[i] = W_extract_l( W_mult_32_32( L_tmp, x[i] ) ); + move32(); /* saturation can occur here */ + } +} + + /*-------------------------------------------------------------------* * Copy_Scale_sig32_16 * diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index 742be031b..df1191160 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -123,7 +123,7 @@ ivas_error acelp_core_enc( Word16 next_force_sf_bck; Word16 uc_two_stage_flag; Word16 position; - float tmpF; + // float tmpF; Word16 ppp_mode, nelp_mode; Word16 tdm_lp_reuse_flag, tdm_low_rate_mode, tdm_Pitch_reuse_flag; float *tdm_Pri_pitch_buf; @@ -647,20 +647,26 @@ ivas_error acelp_core_enc( { if ( st->hTdCngEnc != NULL ) { + Word16 enr, enr_index; #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 tmpfx /*, CNG_att_fx*/; st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); - Word16 Q_exc_l = Q_factor_arr( exc, st->L_frame ); - floatToFixed_arr( exc, exc_fx, Q_exc_l, st->L_frame ); + // Word16 Q_exc_l = Q_factor_arr( exc, st->L_frame ); + floatToFixed_arr( exc, exc_fx, Q_new, st->L_frame ); #endif // tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); - tmpfx = cng_energy_ivas_fx( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att_fx, exc_fx, st->L_frame, Q_exc_l ); + enr = cng_energy_ivas_fx( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att_fx, exc_fx, st->L_frame, Q_new ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS - tmpF = fix16_to_float( tmpfx, Q8 ); + // tmpF = fix16_to_float( tmpfx, Q8 ); #endif - i = (int16_t) ( ( tmpF + 2.0f ) * STEP_SID ); - i = min( max( i, 0 ), 127 ); - st->hTdCngEnc->old_enr_index = i; + /* calculate the energy quantization index */ + enr_index = add( enr, 512 /* Q8(2.0) */ ); /* enr + 2.0 */ + enr_index = extract_l( L_shr( L_mult0( enr_index, STEP_SID_FX ), 12 + 8 ) ); /* Q0 (8+12-(8+12)) */ + + /* limit the energy quantization index */ + enr_index = s_min( enr_index, 127 ); + enr_index = s_max( enr_index, 0 ); + st->hTdCngEnc->old_enr_index = enr_index; + move16(); } } } @@ -734,8 +740,23 @@ ivas_error acelp_core_enc( #endif } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 /* Q_syn_l, */ Q_lpd_syn_l; + Q_syn_l = Q_factor_arr( syn1, st->L_frame ); + Q_lpd_syn_l = Q_factor_arr( hLPDmem->syn_flt, ( M + 1 ) ); + Q_syn_l = min( Q_syn_l, Q_lpd_syn_l ); + + floatToFixed_arr( syn1, syn1_fx, Q_syn_l, st->L_frame ); + floatToFixed_arr( hLPDmem->syn_flt, hLPDmem->syn, Q_syn_l, ( M + 1 ) ); + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif /*Update MODE2 core switching memory*/ - deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + // deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + deemph_fx( syn1_fx, st->preemph_fac, st->L_frame, &( hLPDmem->syn[M] ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( syn1_fx, syn1, Q_syn_l, st->L_frame ); + fixedToFloat_arr( hLPDmem->syn, hLPDmem->syn_flt, Q_syn_l, ( M + 1 ) ); +#endif mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); } @@ -773,10 +794,12 @@ ivas_error acelp_core_enc( floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); st->clip_var_fx[0] = (Word16) ( st->clip_var[0] * 2.56f ); - for ( i = 1; i < 6; i++ ) - { - st->clip_var_fx[i] = (Word16) ( st->clip_var[i] * ONE_IN_Q14 ); - } + st->clip_var_fx[1] = float_to_fix16( st->clip_var[1], Q14 ); + st->clip_var_fx[2] = float_to_fix16( st->clip_var[2], Q7 ); + st->clip_var_fx[3] = float_to_fix16( st->clip_var[3], 0 ); + st->clip_var_fx[4] = float_to_fix16( st->clip_var[4], Q14 ); + st->clip_var_fx[5] = float_to_fix16( st->clip_var[5], Q14 ); + st->streaklimit_fx = (Word16) floatToFixed( st->streaklimit, Q15 ); FOR( Word16 idx = 0; idx < M; idx++ ) { @@ -990,20 +1013,34 @@ ivas_error acelp_core_enc( encod_gen_2sbfr( st, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf_fx, &Q_exc2 ); } } + ELSE IF( nelp_mode ) + { + /* SC-VBR - NELP frames */ + encod_nelp_ivas_fx( st, inp_fx, Aw_fx, Aq_fx, res_fx, syn_fx, &tmp_noise_fx, exc_fx, exc2_fx, pitch_buf_fx, voice_factors_fx, bwe_exc_fx, Q_new, 0 ); + } #ifdef IVAS_FLOAT_FIXED_CONVERSIONS st->mem_deemp_preQ = fixedToFloat( st->mem_deemp_preQ_fx, -1 ); tilt_code_bck = fix16_to_float( tilt_code_bck_fx, Q15 ); gc_threshold_bck = fix_to_float( gc_threshold_bck_fx, Q16 ); clip_var_bck[0] = (float) clip_var_bck_fx[0] / 2.56f; - for ( i = 1; i < 6; i++ ) - { - clip_var_bck[i] = (float) clip_var_bck_fx[i] / (float) ( ONE_IN_Q14 ); - } + clip_var_bck[1] = fix16_to_float( clip_var_bck_fx[1], Q14 ); + clip_var_bck[2] = fix16_to_float( clip_var_bck_fx[2], Q7 ); + clip_var_bck[3] = fix16_to_float( clip_var_bck_fx[3], 0 ); + clip_var_bck[4] = fix16_to_float( clip_var_bck_fx[4], Q14 ); + clip_var_bck[5] = fix16_to_float( clip_var_bck_fx[5], Q14 ); + + st->clip_var[0] = (float) st->clip_var_fx[0] / 2.56f; + st->clip_var[1] = fix16_to_float( st->clip_var_fx[1], Q14 ); + st->clip_var[2] = fix16_to_float( st->clip_var_fx[2], Q7 ); + st->clip_var[3] = fix16_to_float( st->clip_var_fx[3], 0 ); + st->clip_var[4] = fix16_to_float( st->clip_var_fx[4], Q14 ); + st->clip_var[5] = fix16_to_float( st->clip_var_fx[5], Q14 ); + clip_var = (float) clip_var_fx / 2.56f; for ( int ii = 0; ii < M; ii++ ) { - mem_AR[i] = (float) mem_AR_fx[i] / 2.56f; - mem_MA[i] = (float) mem_MA_fx[i] / 2.56f; + mem_AR[ii] = (float) mem_AR_fx[ii] / 2.56f; + mem_MA[ii] = (float) mem_MA_fx[ii] / 2.56f; } fixedToFloat_arr( lsp_new_bck_fx, lsp_new_bck, Q15, M ); fixedToFloat_arr( lsp_mid_bck_fx, lsp_mid_bck, Q15, M ); @@ -1061,8 +1098,6 @@ ivas_error acelp_core_enc( } else if ( nelp_mode ) { - /* SC-VBR - NELP frames */ - encod_nelp( st, inp, Aw, Aq, res, syn, &tmp_noise, exc, exc2, pitch_buf, voice_factors, bwe_exc ); } else if ( st->coder_type == UNVOICED ) { @@ -1177,7 +1212,23 @@ ivas_error acelp_core_enc( /*Update MODE2 core switching memory*/ mvr2r( syn, syn1, st->L_frame ); - deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_syn_l, Q_lpd_syn_l; + Q_syn_l = Q_factor_arr( syn1, st->L_frame ); + Q_lpd_syn_l = Q_factor_arr( hLPDmem->syn_flt, ( M + 1 ) ); + Q_syn_l = min( Q_syn_l, Q_lpd_syn_l ); + + floatToFixed_arr( syn1, syn1_fx, Q_syn_l, st->L_frame ); + floatToFixed_arr( hLPDmem->syn_flt, hLPDmem->syn, Q_syn_l, ( M + 1 ) ); + st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); +#endif + /*Update MODE2 core switching memory*/ + deemph_fx( syn1_fx, st->preemph_fac, st->L_frame, &( hLPDmem->syn[M] ) ); + // deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( syn1_fx, syn1, Q_syn_l, st->L_frame ); + fixedToFloat_arr( hLPDmem->syn, hLPDmem->syn_flt, Q_syn_l, ( M + 1 ) ); +#endif mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); if ( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) diff --git a/lib_enc/cod4t64_fast.c b/lib_enc/cod4t64_fast.c index 8692bb3d9..e778ca082 100644 --- a/lib_enc/cod4t64_fast.c +++ b/lib_enc/cod4t64_fast.c @@ -60,6 +60,7 @@ *---------------------------------------------------------------------*/ /*! r: return index (N+1 bits) */ +#ifndef IVAS_FLOAT_FIXED static int16_t quant_1p_N1_L_subfr( const int16_t nb_pos, /* i : number of positions */ const int16_t pos, /* i : position of the pulse */ @@ -79,7 +80,27 @@ static int16_t quant_1p_N1_L_subfr( return index; } +#else +static Word16 quant_1p_N1_L_subfr( + const Word16 nb_pos, /* i : number of positions */ + const Word16 pos, /* i : position of the pulse */ + const Word16 N /* i : number of bits for position */ +) +{ + Word16 mask, index; + + mask = extract_l( L_sub( L_shl( 1, N ), 1 ) ); + + index = s_and( pos, mask ); + + if ( s_and( pos, nb_pos ) != 0 ) + { + index = add( index, shl( 1, N ) ); + } + return index; +} +#endif /*-------------------------------------------------------------------* * Function find_best_pulse() * @@ -1000,7 +1021,8 @@ void acelp_fast_fx( FOR( i = 0; i < L_subfr; i++ ) { - bn_orig_fx[i] = add( mult( s_coef_fx, cn[i] ), shr( i_mult( beta1_fx, dn_orig[i] ), tmp ) ); // Q_dn - tmp + bn_orig_fx[i] = add( mult( s_coef_fx, cn[i] ), shr( i_mult_sat( beta1_fx, dn_orig[i] ), tmp ) ); // Q_dn - tmp + move16(); IF( bn_orig_fx[i] >= 0 ) { diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c index 2111560a8..efe5ecbda 100644 --- a/lib_enc/core_enc_init.c +++ b/lib_enc/core_enc_init.c @@ -994,7 +994,7 @@ static void init_sig_buffers_ivas_fx( Encoder_State *st, const Word16 L_frame_ol { set16_fx( hTcxEnc->buf_speech_ltp, 0, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); } - set16_fx( st->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + set16_fx( st->buf_wspeech_enc, 0, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); /* increased by 320 to avoid memory overlap in ivas_find_wsp() and also to accomodate for the wspeech_enc */ } ELSE { diff --git a/lib_enc/core_enc_ol.c b/lib_enc/core_enc_ol.c index a00eb2551..e4a1b3ad2 100644 --- a/lib_enc/core_enc_ol.c +++ b/lib_enc/core_enc_ol.c @@ -43,6 +43,7 @@ #include "basop_proto_func.h" #include "wmc_auto.h" #ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" #include "prot_fx_enc.h" #endif @@ -672,7 +673,368 @@ static void closest_centroid_rf( * * Open-loop ACELP/TCX20 core decision *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void core_acelp_tcx20_switching( + Encoder_State *st, /* i/o: encoder state structure */ + float non_staX, /* i : unbound non-stationarity for sp/mu clas */ + float *pitch_fr, /* i/o: fraction pitch values */ + float *voicing_fr, /* i/o: fractional voicing values */ + const float currFlatness, /* i : flatness */ + const float lsp_mid[M], /* i : LSPs at the middle of the frame */ + const float stab_fac /* i : LP filter stability */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + int16_t i, j; + float A_q_tcx[NB_SUBFR16k * ( M + 1 )]; + float dsnr, snr_tcx, snr_acelp; + int16_t iter; + float xn_buf[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; + float Ap[M + 1]; + float gainlpc[FDNS_NPTS]; + float en[N_MAX / 4]; + float sqGain, ener, tmp, fac, offset; + int16_t L_frame = st->L_frame; + int16_t overlap; + int16_t tcx_offset = st->hTcxCfg->tcx_offset; + float *x = hTcxEnc->spectrum_long; + float target; + int16_t T0; + float gain, noise, scale; + float *pt_ener_sfr, ener_sfr[NB_SUBFR16k]; + Word16 q_fac; + Word16 *speech_fx; + Word16 *speech_ltp_fx; + Word16 A_q_tcx_fx[NB_SUBFR16k * ( M + 1 )]; + Word16 buf_speech_enc_fx[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; + Word16 buf_speech_ltp_fx[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; + Word16 buf_wspeech_enc_fx[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320]; + Word16 *wspeech_fx; + Word16 q_fac_wsp; + + /* Check minimum pitch for quantization */ + for ( i = 0; i < 3; i++ ) + { + /* check minimum pitch for quantization */ + if ( st->pitch[i] < PIT_MIN_SHORTER ) + { + st->pitch[i] *= 2; + } + + /* convert pitch values to 16kHz domain */ + if ( st->L_frame == L_FRAME16k ) + { + st->pitch[i] = (int16_t) ( st->pitch[i] * 1.25f + 0.5f ); + } + } + if ( st->narrowBand == 1 ) + { + pitchDoubling_det( st->wspeech_enc_flt, st->pitch, pitch_fr, voicing_fr ); + } + + lsp2a_stab( lsp_mid, A_q_tcx, M ); + +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + floatToFixed_arr( st->buf_speech_enc_flt, buf_speech_enc_fx, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + speech_fx = buf_speech_enc_fx + st->encoderPastSamples_enc; + + floatToFixed_arr( st->hTcxEnc->buf_speech_ltp_flt, buf_speech_ltp_fx, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + speech_ltp_fx = buf_speech_ltp_fx + st->encoderPastSamples_enc; + + q_fac_wsp = Q_factor_arr( st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + floatToFixed_arr( st->buf_wspeech_enc_flt, buf_wspeech_enc_fx, q_fac_wsp, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + + floatToFixed_arr( A_q_tcx, A_q_tcx_fx, q_fac, NB_SUBFR16k * ( M + 1 ) ); + + Word16 L_subfr = idiv1616( st->L_frame, st->nb_subfr ); + + if ( st->element_mode > EVS_MONO ) + { + wspeech_fx = buf_wspeech_enc_fx + st->L_frame + L_SUBFR; + } + else + { + wspeech_fx = buf_wspeech_enc_fx + st->L_frame + L_subfr; + } + +#endif + + tcx_ltp_encode_ivas_fx( st, TCX_20, st->L_frame, speech_fx + st->encoderLookahead_enc, speech_ltp_fx + st->encoderLookahead_enc, wspeech_fx + st->encoderLookahead_enc, st->pitch, hTcxEnc->tcxltp_param, &hTcxEnc->tcxltp_bits, A_q_tcx_fx, 0, st->element_mode ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( A_q_tcx_fx, A_q_tcx, q_fac, NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( buf_wspeech_enc_fx, st->buf_wspeech_enc_flt, q_fac_wsp, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + fixedToFloat_arr( buf_speech_ltp_fx, st->hTcxEnc->buf_speech_ltp_flt, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); +#endif +#else + tcx_ltp_encode( st, TCX_20, st->L_frame, st->speech_enc_flt + st->encoderLookahead_enc, hTcxEnc->speech_ltp_flt + st->encoderLookahead_enc, st->wspeech_enc_flt + st->encoderLookahead_enc, st->pitch, hTcxEnc->tcxltp_param, &hTcxEnc->tcxltp_bits, A_q_tcx, 0, st->element_mode ); +#endif + + /* Force TCX when TCX20 in MODE1 is selected */ + if ( st->mdct_sw == MODE1 ) + { + st->core = TCX_20_CORE; + } + else + { + /*--------------------------------------------------------------* + * Estimate TCX SNR + *---------------------------------------------------------------*/ + + target = 1000.f; + if ( st->sr_core == INT_FS_16k ) + { + target = 850.f; + } + else if ( st->sr_core == INT_FS_12k8 ) + { + target = 850.f; + } + + if ( st->narrowBand == 1 ) + { + target = 500.f; + } + + if ( st->last_core == ACELP_CORE ) + { + L_frame += tcx_offset; + + if ( st->hTcxCfg->lfacNext < 0 ) + { + L_frame -= st->hTcxCfg->lfacNext; + tcx_offset = st->hTcxCfg->lfacNext; + } + else + { + tcx_offset = 0; + } + } + + overlap = st->hTcxCfg->tcx_mdct_window_delay; + + mvr2r( hTcxEnc->speech_ltp_flt - ( overlap >> 1 ) + tcx_offset, xn_buf, L_frame + overlap ); + + if ( st->last_core == ACELP_CORE ) + { + if ( tcx_offset < 0 ) + { + set_f( xn_buf, 0.0f, overlap >> 1 ); + } + } + else + { + for ( i = 0; i < overlap; i++ ) + { + xn_buf[i] *= st->hTcxCfg->tcx_mdct_window_flt[i]; + } + } + + for ( i = 0; i < overlap; i++ ) + { + xn_buf[L_frame + i] *= st->hTcxCfg->tcx_mdct_window_flt[overlap - 1 - i]; + } + + TCX_MDCT_flt( xn_buf, x, overlap, L_frame - overlap, overlap, st->element_mode ); + + for ( i = 0; i < L_frame; i++ ) + { + x[i] *= (float) ( L_frame / sqrt( 2 * NORM_MDCT_FACTOR ) ); + } + + weight_a( A_q_tcx, Ap, st->gamma_flt, M ); + + lpc2mdct_flt( Ap, M, gainlpc, FDNS_NPTS, 0 ); + + mdct_preShaping( x, L_frame, gainlpc ); + + if ( st->narrowBand == 1 ) + { + j = (int16_t) ( (float) L_frame * 0.625f ); + + set_f( x + j, 0.0f, L_frame - j ); + } + + for ( i = 0; i < L_frame; i += 4 ) + { + ener = 0.01f + x[i] * x[i] + x[i + 1] * x[i + 1] + x[i + 2] * x[i + 2] + x[i + 3] * x[i + 3]; + en[i / 4] = 9.0f + 10.0f * (float) log10( ener ); + } + + fac = 128.0f; + offset = fac; + + for ( iter = 0; iter < 10; iter++ ) + { + fac *= 0.5f; + offset -= fac; + ener = 0.0f; + + for ( i = 0; i < L_frame / 4; i++ ) + { + tmp = en[i] - offset; + + if ( tmp > 3.0f ) + { + ener += tmp; + } + + if ( ener > target ) + { + offset += fac; + break; + } + } + } + + if ( offset <= 32.f ) + { + offset = -128.f; + } + + sqGain = (float) pow( 10.0f, offset / 20.0f ); + ener = sqGain * sqGain / 12.f * (float) sqrt( 2.f ) / (float) L_frame; + + snr_tcx = 0.0f; + pt_ener_sfr = ener_sfr; + + for ( i = 0; i < st->L_frame; i += L_SUBFR ) + { + *pt_ener_sfr = sum2_f( st->wspeech_enc_flt + i, L_SUBFR ) + 1e-6f; + + snr_tcx += (float) log10( *pt_ener_sfr / ( ener * L_SUBFR ) ); + pt_ener_sfr++; + } + snr_tcx *= ( (float) ( 10 * L_SUBFR ) ) / (float) st->L_frame; + + + /*--------------------------------------------------------------* + * Estimate ACELP SNR + *---------------------------------------------------------------*/ + + scale = 0.055f; + if ( st->sr_core == INT_FS_16k ) + { + scale = 0.092f; + } + else if ( st->sr_core == INT_FS_12k8 ) + { + scale = 0.059f; + } + + if ( st->narrowBand ) + { + scale = 0.15f; + } + + snr_acelp = 0.0f; + fac = (float) st->sr_core / (float) INT_FS_12k8; + pt_ener_sfr = ener_sfr; + + for ( i = 0; i < st->L_frame; i += L_SUBFR ) + { + T0 = (int16_t) ( ( fac * pitch_fr[(int16_t) ( (float) ( i / L_SUBFR ) / fac + 0.5f )] ) + 0.5f ); + gain = get_gain_flt( st->wspeech_enc_flt + i, st->wspeech_enc_flt + i - T0, L_SUBFR, NULL ); + + noise = 1e-6f; + for ( j = 0; j < L_SUBFR; j++ ) + { + tmp = st->wspeech_enc_flt[i + j] - gain * st->wspeech_enc_flt[i + j - T0]; + noise += tmp * tmp; + } + + noise *= scale; + snr_acelp += (float) log10( *pt_ener_sfr / noise ); + pt_ener_sfr++; + } + + snr_acelp *= ( (float) ( 10 * L_SUBFR ) ) / (float) st->L_frame; + + + /*--------------------------------------------------------------* + * Switching Decision + *---------------------------------------------------------------*/ + + dsnr = 0.0f; + /* hysteresis for very small SNR differences between ACELP and TCX */ + + /* try to use TCX instead of ACELP on temporally stationary frames */ + if ( ( snr_acelp > snr_tcx ) && + ( snr_acelp < snr_tcx + 2.0f ) && + ( st->prevTempFlatness + currFlatness < 3.25f || stab_fac == 1.0f || ( st->sr_core == INT_FS_12k8 && st->sp_aud_decision0 == 1 && st->prevTempFlatness + currFlatness < 20.f ) ) && + ( st->acelpFramesCount <= 6 ) ) + { + dsnr = -2.0f; + } + + /* try to use ACELP instead of TCX on transient and "buzzy" frames */ + if ( ( snr_acelp < snr_tcx ) && + ( snr_acelp > snr_tcx - 2.0f ) && + ( st->prevTempFlatness + currFlatness > 3.25f ) && + ( st->acelpFramesCount >= 6 ) ) + { + dsnr = 2.0f; + } + + if ( ( st->sr_core == INT_FS_12k8 ) && ( offset < 74.0f ) && ( non_staX > 5.0f ) && ( snr_acelp >= snr_tcx - 4 ) && st->acelpFramesCount >= 1 && ( ( ( st->hSpMusClas->lps > st->hSpMusClas->lpm ) && mean( voicing_fr, 4 ) >= 0.3f ) || ( st->acelpFramesCount >= 6 && ( st->hSpMusClas->lps > st->hSpMusClas->lpm - 1.5f ) ) ) && ( st->sp_aud_decision0 == 0 ) && st->vad_flag ) + { + /* Fine tuned across various databases based on various metrics to detect TCX frames in speech.*/ + dsnr = 4.0f; + } + + if ( st->flag_noisy_speech_snr ) + { + if ( st->vad_flag || st->Opt_DTX_ON ) + { + dsnr += 2.f; + } + else + { + dsnr -= 2.f; + } + } + + if ( st->sr_core == INT_FS_12k8 && ( non_staX < 2.f || ( st->flag_noisy_speech_snr == 0 && st->vad_flag == 1 && offset == -128.f && st->acelpFramesCount >= 6 ) ) && ( st->last_core == ACELP_CORE || st->last_core == TCX_20_CORE ) ) + { + st->core = st->last_core; + } + else if ( snr_acelp + dsnr > snr_tcx ) + { + st->core = ACELP_CORE; + st->acelpFramesCount = min( MAX16B - 1, st->acelpFramesCount + 1 ); + } + else + { + st->core = TCX_20_CORE; + st->acelpFramesCount = 0; + } + } + + /* Fixed Decision (using -C) */ + if ( st->acelpEnabled == 1 && st->tcx20Enabled == 0 ) + { + st->core = ACELP_CORE; + } + + if ( st->acelpEnabled == 0 && st->tcx20Enabled == 1 ) + { + st->core = TCX_20_CORE; + } + + st->prevTempFlatness = currFlatness; + + return; +} +#else void core_acelp_tcx20_switching( Encoder_State *st, /* i/o: encoder state structure */ float non_staX, /* i : unbound non-stationarity for sp/mu clas */ @@ -982,6 +1344,7 @@ void core_acelp_tcx20_switching( return; } +#endif /*-------------------------------------------------------------------* * BITS_ALLOC_ACELP_config_rf() diff --git a/lib_enc/core_enc_updt.c b/lib_enc/core_enc_updt.c index bfd845b49..b0bf893f4 100644 --- a/lib_enc/core_enc_updt.c +++ b/lib_enc/core_enc_updt.c @@ -40,6 +40,9 @@ #include "rom_com.h" #include "cnst.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif /*-------------------------------------------------------------------* * core_encode_update() @@ -104,6 +107,78 @@ void core_encode_update( } +#ifdef IVAS_FLOAT_FIXED +void core_encode_update_ivas_fx( + Encoder_State *st /* i/o: Encoder state structure */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 n; + + /* Update Input Signal Buffers */ + n = add( st->encoderPastSamples_enc, st->encoderLookahead_enc ); + + Copy( st->buf_speech_enc_pe + st->L_frame, st->buf_speech_enc_pe, n ); + Copy( st->buf_speech_enc + st->L_frame, st->buf_speech_enc, n ); + + IF( !st->tcxonly ) + { + n = add( st->L_frame, shr( st->L_frame, 2 ) ); + Copy( st->buf_wspeech_enc + st->L_frame, st->buf_wspeech_enc, n ); + } + + IF( hTcxEnc != NULL ) + { + test(); + test(); + test(); + IF( EQ_16( st->core, ACELP_CORE ) || EQ_16( st->core, AMR_WB_CORE ) || EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, FRAME_NO_DATA ) ) + { + Word16 max_e = s_max( st->hTcxEnc->exp_buf_speech_ltp, hTcxEnc->exp_buf_speech_ltp ); + Scale_sig( hTcxEnc->buf_speech_ltp, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k, -( max_e - st->hTcxEnc->exp_buf_speech_ltp ) ); + Copy_Scale_sig( st->buf_speech_enc + st->L_frame, hTcxEnc->buf_speech_ltp + st->L_frame, st->L_frame, -( max_e - st->exp_buf_speech_enc ) ); + st->hTcxEnc->exp_buf_speech_ltp = max_e; + } + } + + n = add( st->encoderPastSamples_enc, st->encoderLookahead_enc ); + Copy( st->buf_synth + st->L_frame, st->buf_synth, st->L_frame + L_SUBFR ); + IF( hTcxEnc != NULL ) + { + Copy( hTcxEnc->buf_speech_ltp + st->L_frame, hTcxEnc->buf_speech_ltp, n ); + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + st->hTcxEnc->kernel_switch_corr_past = 0; + st->hTcxEnc->kernel_type[0] = MDCT_IV; + st->hTcxEnc->kernel_symmetry_past = 0; + st->hTcxEnc->enc_ste_pre_corr_past = 0; + + move16(); + move16(); + move16(); + move16(); + } + } + +#ifdef NON_BE_1055_RESET_LP_MEMORIES + test(); + test(); + test(); + test(); + IF( ( st->Opt_DTX_ON && LE_32( st->core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) ) || ( st->tcxonly && ( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) ) ) +#else + if ( ( st->Opt_DTX_ON && st->core_brate <= SID_2k40 && st->cng_type == FD_CNG ) || ( st->tcxonly && st->codec_mode == MODE2 ) ) +#endif + { + /* reset LP memories */ + set16_fx( st->mem_MA_fx, 0, M ); + Copy( GEWB_Ave_fx, st->mem_AR_fx, M ); // 2.56 scaling + } + return; +} +#endif + /*-------------------------------------------------------------------* * core_encode_update_cng() * diff --git a/lib_enc/core_switching_enc.c b/lib_enc/core_switching_enc.c index b03654caa..9b234099b 100644 --- a/lib_enc/core_switching_enc.c +++ b/lib_enc/core_switching_enc.c @@ -828,6 +828,10 @@ void core_switching_post_enc( #endif set_f( st->hBWE_TD->dec_2_over_3_mem, 0.0f, L_FILT_2OVER3 ); set_f( st->hBWE_TD->dec_2_over_3_mem_lp, 0.0f, L_FILT_2OVER3_LP ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( st->hBWE_TD->dec_2_over_3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( st->hBWE_TD->dec_2_over_3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); +#endif } else if ( ( st->extl == SWB_TBE || st->extl == FB_TBE ) && ( ( st->element_mode == IVAS_CPE_TD && st->last_extl != SWB_TBE && st->last_extl != FB_TBE ) || ( st->element_mode != IVAS_CPE_TD && st->last_total_brate != st->total_brate ) || ( st->last_bwidth != st->bwidth ) || ( st->last_codec_mode != MODE1 ) || ( st->rf_mode_last != st->rf_mode ) ) ) { diff --git a/lib_enc/enc_nelp_fx.c b/lib_enc/enc_nelp_fx.c index 4be45c7e9..cbc8c02ab 100644 --- a/lib_enc/enc_nelp_fx.c +++ b/lib_enc/enc_nelp_fx.c @@ -174,3 +174,149 @@ void encod_nelp_fx( return; } + +#ifdef IVAS_FLOAT_FIXED +void encod_nelp_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word16 *speech_fx, + /* i : input speech */ /* Q_new-1 */ + const Word16 Aw_fx[], + /* i : weighted A(z) unquantized for subframes */ /*exp(norm_s(Aw_fx[0])+1)*/ + const Word16 Aq_fx[], + /* i : 12k8 Lp coefficient */ /*exp(norm_s(Aw_fx[0])+1)*/ + Word16 *res_fx, + /* o : residual signal */ /* Q_new */ + Word16 *synth_fx, + /* o : core synthesis */ /* Q_new */ + Word16 *tmp_noise_fx, + /* o : long-term noise energy */ /* Q8 */ + Word16 *exc_fx, + /* i/o: current non-enhanced excitation */ /* Q_new */ + Word16 *exc2_fx, + /* i/o: current enhanced excitation */ /* Q_new */ + Word16 *pitch_buf_fx, + /* o : floating pitch values for each subframe */ /* Q6 */ + Word16 *voice_factors_fx, + /* o : voicing factors */ /* Q15 */ + Word16 *bwe_exc_fx, + /* o : excitation for SWB TBE */ /* Q_new */ + Word16 Q_new, + Word16 shift ) +{ + Word16 xn_fx[L_SUBFR]; /* Target vector for pitch search */ + Word16 h1_fx[L_SUBFR]; /* Impulse response vector */ + Word16 exc_nelp_fx[L_FRAME]; + + Word16 i_subfr, j; + + const Word16 *p_Aw_fx, *p_Aq_fx; /* pointer to LP filter coeff. vector */ + Word16 saved_Q_new = Q_new; + move16(); + + Word16 reduce_gains = 0; + move16(); + LPD_state_HANDLE hLPDmem = st_fx->hLPDmem; + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; + + test(); + IF( EQ_16( st_fx->bwidth, NB ) && GE_32( st_fx->input_Fs, 16000 ) ) + { + IF( hSC_VBR->last_nelp_mode == 0 ) + { + set16_fx( hSC_VBR->nelp_lp_fit_mem, 0, NELP_LP_ORDER * 2 ); + } + Scale_sig( hSC_VBR->nelp_lp_fit_mem, NELP_LP_ORDER * 2, sub( Q_new, st_fx->prev_Q_new ) ); + + pz_filter_sp_fx( num_nelp_lp_fx, den_nelp_lp_fx, res_fx, res_fx, hSC_VBR->nelp_lp_fit_mem, NELP_LP_ORDER, NELP_LP_ORDER, L_FRAME, 3 ); /*16-Q of filter coeff*/ + } + + p_Aw_fx = Aw_fx; + p_Aq_fx = Aq_fx; + + + FOR( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + /*----------------------------------------------------------------* + * - Bandwidth expansion of A(z) filter coefficients + * - Find the excitation search target "xn" and innovation + * target in residual domain "cn" + * - Compute impulse response, h1[], of weighted synthesis filter + *----------------------------------------------------------------*/ + Copy( &res_fx[i_subfr], &exc_fx[i_subfr], L_SUBFR ); + + find_targets_ivas_fx( speech_fx, hLPDmem->mem_syn, i_subfr, &hLPDmem->mem_w0, p_Aq_fx, + res_fx, L_SUBFR, p_Aw_fx, TILT_FAC_FX, xn_fx, NULL, h1_fx ); + + /* scale xn[] and h1[] to avoid overflow in dot_product12() */ + Scale_sig( xn_fx, L_SUBFR, shift ); /* scaling of xn[] to limit dynamic at 12 bits */ + + IF( i_subfr == 0 ) + { + test(); + IF( EQ_16( hSC_VBR->Local_VAD, 1 ) && EQ_16( st_fx->bwidth, NB ) ) + { + reduce_gains = 1; + move16(); + } + + nelp_encoder_ivas_fx( st_fx, res_fx, exc_nelp_fx, &Q_new, reduce_gains ); + + Scale_sig( exc_nelp_fx, L_FRAME, ( saved_Q_new - Q_new ) ); + } + + + *tmp_noise_fx = 0; + move16(); + + /*-----------------------------------------------------------------* + * Synthesize speech to update mem_syn[]. + * Update A(z) filters + *-----------------------------------------------------------------*/ + Syn_filt_s( 1, p_Aq_fx, M, &exc_nelp_fx[i_subfr], &synth_fx[i_subfr], L_SUBFR, hLPDmem->mem_syn, 1 ); + + p_Aw_fx += ( M + 1 ); + p_Aq_fx += ( M + 1 ); + *pitch_buf_fx = L_SUBFR_Q6; + move16(); + + pitch_buf_fx++; + } + + Copy( exc_nelp_fx, exc_fx, L_FRAME ); + + /*-----------------------------------------------------------------* + * Updates: last value of new target is stored in mem_w0 + *-----------------------------------------------------------------*/ + +#ifdef BASOP_NOGLOB + hLPDmem->mem_w0 = sub_sat( shr_sat( xn_fx[L_SUBFR - 1], shift ), shr( exc_fx[L_FRAME - 1], 1 ) ); +#else + hLPDmem->mem_w0 = sub( shr( xn_fx[L_SUBFR - 1], shift ), shr( exc_fx[L_FRAME - 1], 1 ) ); +#endif + move16(); /*Q_new-1 */ + hLPDmem->tilt_code = 0; + move16(); /* purely unvoiced */ + hSC_VBR->prev_tilt_code_fx = hLPDmem->tilt_code; + move16(); + + Copy( exc_fx, exc2_fx, L_FRAME ); + + hSC_VBR->prev_ppp_gain_pit_fx = 0; + move16(); + + hLPDmem->dm_fx.prev_state = 0; + move16(); + hLPDmem->dm_fx.prev_gain_pit[0] = hSC_VBR->prev_ppp_gain_pit_fx; + move16(); + + FOR( j = 1; j < 5; j++ ) + { + hLPDmem->dm_fx.prev_gain_pit[j] = hLPDmem->dm_fx.prev_gain_pit[j - 1]; + move16(); + } + interp_code_5over2_fx( exc2_fx, bwe_exc_fx, L_FRAME ); + set16_fx( voice_factors_fx, 0, NB_SUBFR16k ); + + return; +} +#endif diff --git a/lib_enc/ext_sig_ana.c b/lib_enc/ext_sig_ana.c index 2c4374e40..e7688dfba 100644 --- a/lib_enc/ext_sig_ana.c +++ b/lib_enc/ext_sig_ana.c @@ -52,6 +52,7 @@ * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void core_signal_analysis_high_bitrate( const float *new_samples, const int16_t T_op[3], /* i : open-loop pitch values for quantiz. */ @@ -96,6 +97,17 @@ void core_signal_analysis_high_bitrate( int16_t alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc = -1; float alw_voicing[2], alw_voicing_wc = -1; int16_t disable_ltp = 0; +#ifdef IVAS_FLOAT_FIXED + Word16 q_fac; + Word16 buf_speech_enc_fx[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; + Word16 buf_wspeech_enc_fx[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320]; + Word16 buf_speech_ltp_fx[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; + Word16 *speech_ltp_fx = NULL; + Word16 *wspeech_fx = NULL; + Word16 *speech_fx = NULL; + q_fac = 0; + move16(); +#endif if ( last_element_mode != st->element_mode ) { @@ -117,7 +129,65 @@ void core_signal_analysis_high_bitrate( /*--------------------------------------------------------------* * TCX-LTP *---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->element_mode == IVAS_CPE_DFT ) + { + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, Q7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + floatToFixed_arr( st->buf_wspeech_enc_flt, buf_wspeech_enc_fx, q_fac, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + + if ( st->element_mode > EVS_MONO ) + { + wspeech_fx = buf_wspeech_enc_fx + st->L_frame + L_SUBFR; + } + else + { + wspeech_fx = buf_wspeech_enc_fx + st->L_frame + idiv1616( st->L_frame, st->nb_subfr ); + } + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, Q7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + floatToFixed_arr( st->buf_speech_enc_flt, buf_speech_enc_fx, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + speech_fx = buf_speech_enc_fx + +st->encoderPastSamples_enc; + + floatToFixed_arr( st->hTcxEnc->buf_speech_ltp_flt, buf_speech_ltp_fx, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + speech_ltp_fx = buf_speech_ltp_fx + st->encoderPastSamples_enc; + } +#endif + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + tcx_ltp_encode_ivas_fx( st, hTcxEnc->tcxMode, L_frame, wspeech_fx, NULL, wspeech_fx, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + ELSE IF( st->element_mode != IVAS_CPE_MDCT ) + { + tcx_ltp_encode_ivas_fx( st, hTcxEnc->tcxMode, L_frame, speech_fx + st->encoderLookahead_enc, speech_ltp_fx + st->encoderLookahead_enc, speech_fx + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->element_mode == IVAS_CPE_DFT ) + { + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); + fixedToFloat_arr( buf_wspeech_enc_fx, st->buf_wspeech_enc_flt, q_fac, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320 ); + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); + fixedToFloat_arr( buf_speech_ltp_fx, st->hTcxEnc->buf_speech_ltp_flt, q_fac, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } +#endif +#else if ( st->element_mode == IVAS_CPE_DFT ) { tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->wspeech_enc_flt, NULL, st->wspeech_enc_flt, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); @@ -126,6 +196,7 @@ void core_signal_analysis_high_bitrate( { tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->speech_enc_flt + st->encoderLookahead_enc, hTcxEnc->speech_ltp_flt + st->encoderLookahead_enc, st->speech_enc_flt + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); } +#endif if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) { @@ -427,6 +498,13 @@ void core_signal_analysis_high_bitrate( if ( st->hTcxCfg->fIsTNSAllowed ) { // conv params to float // avgSqrCoef_flt = float(avgSqrCoef, Q 15) + hTcxEnc->tnsData[frameno].filter[0].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[0].avgSqrCoef, 15 ); + hTcxEnc->tnsData[frameno].filter[1].avgSqrCoef_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[1].avgSqrCoef, 15 ); + + // avgSqrCoef_flt = float(avgSqrCoef, Q 15) + hTcxEnc->tnsData[frameno].filter[0].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[0].predictionGain, 7 ); + hTcxEnc->tnsData[frameno].filter[1].predictionGain_flt = fix16_to_float( hTcxEnc->tnsData[frameno].filter[1].predictionGain, 7 ); + // spectrum[]=float( (fix)spectrum_fx[]) , Q=q_factor_spectrum fixedToFloat_arrL( hTcxEnc->spectrum_long_fx, hTcxEnc->spectrum_long, q_factor_spectrum, N_MAX ); @@ -495,6 +573,65 @@ void core_signal_analysis_high_bitrate( { st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); } + + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData = &st->hIGFEnc->igfData; + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); + } + + float max_sb = 0; + float max_tb = 0; + Word16 max_sb_fx = 0; + Word16 max_tb_fx = 0; + + float max_fir_tb = 0; + float max_iir_tb = 0; + float max_fir_sb = 0; + float max_iir_sb = 0; + + Word16 max_fir_tb_fx = 0; + Word16 max_iir_tb_fx = 0; + Word16 max_fir_sb_fx = 0; + Word16 max_iir_sb_fx = 0; + FOR( Word16 sfb = 0; sfb < 23; sfb++ ) + { + f2me_16( hPrivateData->prevDampingFactor_IIR[sfb], &hPrivateData->prevDampingFactor_IIR_fx[sfb], &hPrivateData->prevDampingFactor_IIR_e[sfb] ); + + max_fir_tb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_TB[sfb] ), max_fir_tb ); + f2me_16( max_fir_tb, &max_fir_tb_fx, &hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_FIR_TB_e[sfb] ) ); + + max_iir_tb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_TB[sfb] ), max_iir_tb ); + f2me_16( max_iir_tb, &max_iir_tb_fx, &hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_TB[sfb], sub( 15, hPrivateData->prevSFB_IIR_TB_e[sfb] ) ); + + max_fir_sb = max( fabsf( hPrivateData->prevSFM_FIR_SFB_SB[sfb] ), max_fir_sb ); + f2me_16( max_fir_sb, &max_fir_sb_fx, &hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_FIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_FIR_SB_e[sfb] ) ); + + max_iir_sb = max( fabsf( hPrivateData->prevSFM_IIR_SFB_SB[sfb] ), max_iir_sb ); + f2me_16( max_iir_sb, &max_iir_sb_fx, &hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = float_to_fix16( hPrivateData->prevSFM_IIR_SFB_SB[sfb], sub( 15, hPrivateData->prevSFB_IIR_SB_e[sfb] ) ); + + max_tb = max( fabsf( hPrivateData->SFM_tb[sfb] ), max_tb ); + f2me_16( max_tb, &max_tb_fx, &hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_tb_fx[sfb] = float_to_fix16( hPrivateData->SFM_tb[sfb], sub( 15, hPrivateData->sfb_tb_e[sfb] ) ); + + max_sb = max( fabsf( hPrivateData->SFM_sb[sfb] ), max_sb ); + f2me_16( max_sb, &max_sb_fx, &hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->SFM_sb_fx[sfb] = float_to_fix16( hPrivateData->SFM_sb[sfb], sub( 15, hPrivateData->sfb_sb_e[sfb] ) ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR[i] = float_to_fix( hPrivateData->prevSFM_FIR_flt[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR[i] = float_to_fix16( hPrivateData->prevSFM_IIR_flt[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM_fx[i][j] = float_to_fix16( hPrivateData->igfPastSFM[i][j], 13 ); + } + } #endif ProcessIGF_ivas_fx( st, hTcxEnc->spectrum_fx[frameno], hTcxEnc->spectrum_fx[frameno], &q_spectrum, powerSpec_fx, &q_powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS @@ -506,6 +643,32 @@ void core_signal_analysis_high_bitrate( st->hIGFEnc->tns_predictionGain_flt = fix16_to_float( st->hIGFEnc->tns_predictionGain, Q23 ); me2f_buf( st->hIGFEnc->spec_be_igf, st->hIGFEnc->spec_be_igf_e, st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->infoStopLine - IGF_START_MN ); } + + for ( Word16 sfb = 0; sfb < 23; sfb++ ) + { + hPrivateData->prevSFM_FIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_FIR_TB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_TB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], hPrivateData->prevSFB_IIR_TB_e[sfb] ); + hPrivateData->prevSFM_FIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_FIR_SB_e[sfb] ); + hPrivateData->prevSFM_IIR_SFB_SB[sfb] = me2f_16( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], hPrivateData->prevSFB_IIR_SB_e[sfb] ); + hPrivateData->SFM_tb[sfb] = me2f_16( hPrivateData->SFM_tb_fx[sfb], hPrivateData->sfb_tb_e[sfb] ); + hPrivateData->SFM_sb[sfb] = me2f_16( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb] ); + hPrivateData->prevDampingFactor_IIR[sfb] = me2f_16( hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb] ); + } + + for ( i = 0; i < IGF_MAX_TILES; i++ ) + { + hPrivateData->prevSFM_FIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_FIR[i], 16 ); /*15Q16*/ + hPrivateData->prevSFM_IIR_flt[i] = fixedToFloat( hPrivateData->prevSFM_IIR[i], 13 ); /*2Q13*/ + for ( int j = 0; j < IGF_PAST_SFM_LEN; j++ ) + { + hPrivateData->igfPastSFM[i][j] = fixedToFloat( hPrivateData->igfPastSFM_fx[i][j], 13 ); + } + } + + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } #endif #else ProcessIGF( st, hTcxEnc->spectrum[frameno], hTcxEnc->spectrum[frameno], powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); @@ -521,3 +684,403 @@ void core_signal_analysis_high_bitrate( return; } +#else +void core_signal_analysis_high_bitrate( + const float *new_samples, + const int16_t T_op[3], /* i : open-loop pitch values for quantiz. */ + float lsp_new[], + float lsp_mid[], + Encoder_State *st, + float *mdst_spectrum[2], + int16_t pTnsSize[], + int16_t pTnsBits[], + int16_t param_core[], + int16_t *ltpBits, + float *windowed_samples, /* i/o: backup of windowed time signal */ + const int16_t L_frame, + const int16_t L_frameTCX, + const int16_t last_element_mode, + const int16_t vad_hover_flag /* i : VAD hangover flag */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + const int16_t last_overlap = st->hTcxCfg->tcx_last_overlap_mode; + const int16_t curr_overlap = st->hTcxCfg->tcx_curr_overlap_mode; + const int16_t minWindowLen = st->hTcxCfg->tcx_mdct_window_min_lengthFB - 1; + int16_t i, frameno; + int16_t L_subframe; + int16_t left_overlap = -1, right_overlap = -1, folding_offset; + float buf[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + float mdstWin[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for MDST windowing */ + float *powerSpec; + float *tcx20Win; + float tcx5Win[N_TCX10_MAX / 2 + L_MDCT_OVLP_MAX]; /* Buffer for TCX5 windowing and interleaving. */ + float *interleaveBuf = tcx5Win; + int16_t nSubframes; + int16_t overlap_mode[3]; + int16_t *transform_type = hTcxEnc->transform_type; + float r[M + 1]; + float A[M + 1]; + float *lsp[2]; + const int16_t tcx10SizeFB = 2 * st->hTcxCfg->tcx5SizeFB; + const int16_t tcx5SizeFB = st->hTcxCfg->tcx5SizeFB; + const int16_t tcx10Size = 2 * st->hTcxCfg->tcx5Size; + int16_t alw_pitch_lag_12k8[2], alw_pitch_lag_12k8_wc = -1; + float alw_voicing[2], alw_voicing_wc = -1; + int16_t disable_ltp = 0; + + if ( last_element_mode != st->element_mode ) + { + disable_ltp = 1; /* disable TCX-LTP in stereo switching to avoid discontinuities in synthesis */ + } + + powerSpec = tcx20Win = buf; /* Share memory for windowed TD signal and for the power spectrum */ + + /*--------------------------------------------------------------* + * Input Signal Processing: copy, HP filter, pre-emphasis + *---------------------------------------------------------------*/ + + if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) + { + /* Copy Samples */ + mvr2r( new_samples, st->new_speech_enc, L_frame ); + } + + /*--------------------------------------------------------------* + * TCX-LTP + *---------------------------------------------------------------*/ + + if ( st->element_mode == IVAS_CPE_DFT ) + { + tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->wspeech_enc, NULL, st->wspeech_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + else if ( st->element_mode != IVAS_CPE_MDCT ) + { + tcx_ltp_encode( st, hTcxEnc->tcxMode, L_frame, st->speech_enc + st->encoderLookahead_enc, hTcxEnc->speech_ltp + st->encoderLookahead_enc, st->speech_enc + st->encoderLookahead_enc, T_op, ¶m_core[1 + NOISE_FILL_RANGES], ltpBits, NULL, disable_ltp, st->element_mode ); + } + + if ( st->tcxonly && st->element_mode != IVAS_CPE_MDCT ) + { + mvr2r( st->speech_enc + st->encoderLookahead_enc, st->new_speech_enc_pe, L_frame ); + + preemph( st->new_speech_enc_pe, st->preemph_fac, L_frame, &( st->mem_preemph_enc ) ); + } + + if ( hTcxEnc->tcxMode == TCX_10 ) + { + mvs2s( ¶m_core[1 + NOISE_FILL_RANGES], ¶m_core[NPRM_DIV + 1 + NOISE_FILL_RANGES], LTPSIZE ); + } + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + lsp[0] = lsp_new; + lsp[1] = lsp_mid; + } + + /*-------------------------------------------------------------------------* + * Decision matrix for the transform and overlap length + *--------------------------------------------------------------------------*/ + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + alw_pitch_lag_12k8[0] = st->pitch[0]; + alw_pitch_lag_12k8[1] = st->pitch[1]; + alw_voicing[0] = st->voicing[0]; + alw_voicing[1] = st->voicing[1]; + alw_pitch_lag_12k8_wc = min( alw_pitch_lag_12k8[0], alw_pitch_lag_12k8[1] ); + alw_voicing_wc = max( alw_voicing[0], alw_voicing[1] ); + } + + overlap_mode[0] = last_overlap; /* Overlap between the last and the current frame */ + + if ( hTcxEnc->tcxMode == TCX_20 ) + { + nSubframes = 1; + transform_type[0] = TCX_20; + transform_type[1] = TCX_20; + overlap_mode[1] = curr_overlap; /* Overlap between the current and the next frame */ + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + alw_pitch_lag_12k8[0] = alw_pitch_lag_12k8_wc; + alw_voicing[0] = alw_voicing_wc; + } + } + else + { + nSubframes = 2; + if ( curr_overlap == FULL_OVERLAP ) + { + transform_type[0] = TCX_5; + transform_type[1] = TCX_10; + overlap_mode[1] = ( last_overlap == HALF_OVERLAP ) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + } + else if ( last_overlap == FULL_OVERLAP ) + { + transform_type[0] = TCX_10; + transform_type[1] = TCX_5; + overlap_mode[1] = ( curr_overlap == HALF_OVERLAP ) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 1st and 2nd sub-frame */ + } + else + { + transform_type[0] = transform_type[1] = TCX_5; + overlap_mode[1] = ( last_overlap == HALF_OVERLAP && curr_overlap == HALF_OVERLAP ) ? HALF_OVERLAP : MIN_OVERLAP; /* Overlap between 2nd and 3rd sub-frame */ + } + overlap_mode[2] = curr_overlap; /* Overlap between the current and the next frame */ + } + + if ( st->igf && transform_type[0] != TCX_20 ) + { + IGFEncResetTCX10BitCounter( st->hIGFEnc ); + } + + for ( frameno = 0; frameno < nSubframes; frameno++ ) + { + /*-------------------------------------------------------------------------* + * Get MDCT output and TNS parameters. Apply TNS in the spectrum if needed + *--------------------------------------------------------------------------*/ + + L_subframe = L_frameTCX / nSubframes; + + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + wtda( hTcxEnc->new_speech_TCX, tcx20Win, NULL, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX ); + + if ( windowed_samples != NULL ) /* store overlap data for later */ + { + assert( frameno == 0 ); + windowed_samples[0] = (float) overlap_mode[frameno]; + windowed_samples[1] = (float) overlap_mode[frameno + 1]; + } + if ( st->element_mode != IVAS_CPE_MDCT ) + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 1, 1 ); + } + } + else + { + /* Windowing of the 2xTCX5 subframes or 1xTCX10 or 1xTCX20 */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno], overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, tcx20Win, st->element_mode != IVAS_CPE_MDCT, 1 ); + + if ( windowed_samples != NULL ) /* save windowed speech_TCX samples */ + { + assert( L_subframe + ( left_overlap + right_overlap ) / 2 < 2 * L_FRAME_MAX / nSubframes - L_FRAME_MAX / 8 ); + windowed_samples[frameno * L_FRAME_MAX + 0] = (float) overlap_mode[frameno]; + windowed_samples[frameno * L_FRAME_MAX + 1] = (float) overlap_mode[frameno + 1]; + mvr2r( tcx20Win, windowed_samples + frameno * L_FRAME_MAX + 2, L_subframe + ( left_overlap + right_overlap ) / 2 ); + } + } + + if ( transform_type[frameno] == TCX_5 ) + { + /* Outer left folding */ + for ( i = 0; i < left_overlap / 2; i++ ) + { + tcx20Win[left_overlap / 2 + i] -= tcx20Win[left_overlap / 2 - 1 - i]; + } + + if ( st->element_mode == IVAS_CPE_MDCT && frameno == 0 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + tcx20Win[left_overlap + i] -= hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + /* Outer right folding */ + for ( i = 0; i < right_overlap / 2; i++ ) + { + tcx20Win[L_subframe + left_overlap / 2 - 1 - i] += tcx20Win[L_subframe + left_overlap / 2 + i]; + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + folding_offset = left_overlap / 2; + + for ( i = 0; i < 2; i++ ) + { + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, tcx20Win + i * tcx5SizeFB, &L_subframe, tcx5Win, st->element_mode != IVAS_CPE_MDCT, 1 ); + + TCX_MDCT( tcx5Win, hTcxEnc->spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( hTcxEnc->spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), L_subframe - L_FRAME16k / ( 2 * nSubframes ) ); + } + } + } + else /* transform_type[frameno] != TCX_5 */ + { + assert( transform_type[frameno] == TCX_10 || transform_type[frameno] == TCX_20 ); + + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + edct( tcx20Win, hTcxEnc->spectrum[frameno], L_subframe, st->element_mode ); + + v_multc( hTcxEnc->spectrum[frameno], (float) sqrt( (float) NORM_MDCT_FACTOR / L_subframe ), hTcxEnc->spectrum[frameno], L_subframe ); + } + else + { + /* TCX20/TCX10 */ + if ( st->element_mode == IVAS_CPE_MDCT && frameno == 0 && transform_type[0] == TCX_10 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + tcx20Win[left_overlap + i] -= hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + TCX_MDCT( tcx20Win, hTcxEnc->spectrum[frameno], left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + } + + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, hTcxEnc->spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); + } + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + /* For TCX20 at bitrates up to 64 kbps we need the power spectrum */ + if ( hTcxEnc->tcxMode == TCX_20 && ( st->total_brate < HQ_96k || st->igf ) ) + { + /* Compute noise-measure flags for spectrum filling and quantization */ + AnalyzePowerSpectrum( st, L_subframe * st->L_frame / hTcxEnc->L_frameTCX, L_subframe, left_overlap, right_overlap, hTcxEnc->spectrum[frameno], ( ( hTcxEnc->tcxMode == TCX_20 ) && ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) ) ? mdstWin : tcx20Win, powerSpec ); + } + } + } + + if ( st->element_mode == IVAS_CPE_MDCT ) + { + L_subframe = L_frameTCX / nSubframes; + + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + wtda_ext( hTcxEnc->new_speech_TCX, mdstWin, overlap_mode[frameno], overlap_mode[frameno + 1], L_frameTCX, 3 ); + } + else + { + /* Windowing for the MDST */ + WindowSignal( st->hTcxCfg, st->hTcxCfg->tcx_offsetFB, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &left_overlap, &right_overlap, &hTcxEnc->speech_TCX[frameno * tcx10SizeFB], &L_subframe, mdstWin, 0, 1 ); + } + + if ( transform_type[frameno] == TCX_5 ) + { + /* Outer left folding */ + for ( i = 0; i < left_overlap / 2; i++ ) + { + mdstWin[left_overlap / 2 + i] += mdstWin[left_overlap / 2 - 1 - i]; + } + + if ( frameno == 0 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + mdstWin[left_overlap + i] += hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + /* Outer right folding */ + for ( i = 0; i < right_overlap / 2; i++ ) + { + mdstWin[L_subframe + left_overlap / 2 - 1 - i] -= mdstWin[L_subframe + left_overlap / 2 + i]; + } + + /* 2xTCX5 */ + L_subframe = tcx5SizeFB; + folding_offset = left_overlap / 2; + + for ( i = 0; i < 2; i++ ) + { + WindowSignal( st->hTcxCfg, folding_offset, i == 0 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, i == 1 ? RECTANGULAR_OVERLAP : MIN_OVERLAP, &left_overlap, &right_overlap, mdstWin + i * tcx5SizeFB, &L_subframe, tcx5Win, 0, 1 ); + + TCX_MDST( tcx5Win, mdst_spectrum[frameno] + i * tcx5SizeFB, left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( mdst_spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, mdst_spectrum[frameno] + i * tcx5SizeFB + L_FRAME16k / ( 2 * nSubframes ), L_subframe - L_FRAME16k / ( 2 * nSubframes ) ); + } + } + } + else /* transform_type[frameno] != TCX_5 */ + { + if ( transform_type[frameno] == TCX_20 && st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + edst( mdstWin, mdst_spectrum[frameno], L_subframe, st->element_mode ); + + v_multc( mdst_spectrum[frameno], (float) sqrt( (float) NORM_MDCT_FACTOR / L_subframe ), mdst_spectrum[frameno], L_subframe ); + } + else + { + if ( frameno == 0 && transform_type[0] == TCX_10 && overlap_mode[0] == FULL_OVERLAP && L_subframe - left_overlap > minWindowLen ) + { + for ( i = minWindowLen; i >= 0; i-- ) /* outer left folding of shortened long ALDO slope */ + { + mdstWin[left_overlap + i] += hTcxEnc->speech_TCX[-1 - i] * st->hTcxCfg->tcx_aldo_window_1_FB[left_overlap / 2 + minWindowLen - i] * st->hTcxCfg->tcx_mdct_window_minimumFB[minWindowLen - i]; + } + } + + TCX_MDST( mdstWin, mdst_spectrum[frameno], left_overlap, L_subframe - ( left_overlap + right_overlap ) / 2, right_overlap, st->element_mode ); + } + + /* high-band gain control in case of BWS */ + if ( st->bwidth_sw_cnt > 0 ) + { + v_multc( mdst_spectrum[frameno] + L_FRAME16k / nSubframes, (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD, mdst_spectrum[frameno] + L_FRAME16k / nSubframes, L_subframe - L_FRAME16k / nSubframes ); + } + } + } + + if ( st->element_mode != IVAS_CPE_MDCT ) + { + TNSAnalysis( st->hTcxCfg, L_frameTCX, st->hTcxCfg->tcx_coded_lines, transform_type[frameno], ( frameno == 0 ) && ( st->last_core == ACELP_CORE ), hTcxEnc->spectrum[frameno], st->hTranDet, -1, &hTcxEnc->tnsData[frameno], &hTcxEnc->fUseTns[frameno], NULL ); + + if ( st->hTcxCfg->fIsTNSAllowed ) + { + EncodeTnsData( st->hTcxCfg->pCurrentTnsConfig, &hTcxEnc->tnsData[frameno], param_core + frameno * NPRM_DIV + 1 + NOISE_FILL_RANGES + LTPSIZE, pTnsSize + frameno, pTnsBits + frameno ); + } + + if ( transform_type[frameno] == TCX_5 ) + { + /* group sub-windows: interleave bins according to their frequencies */ + for ( i = 0; i < tcx5SizeFB; i++ ) + { + interleaveBuf[2 * i] = hTcxEnc->spectrum[frameno][i]; + interleaveBuf[2 * i + 1] = hTcxEnc->spectrum[frameno][tcx5SizeFB + i]; + } + mvr2r( interleaveBuf, hTcxEnc->spectrum[frameno], tcx10SizeFB ); + } + + /*--------------------------------------------------------------* + * LPC analysis + *---------------------------------------------------------------*/ + + if ( st->tcxonly ) + { + HBAutocorrelation( st->hTcxCfg, overlap_mode[frameno] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno], overlap_mode[frameno + 1] == ALDO_WINDOW ? FULL_OVERLAP : overlap_mode[frameno + 1], &st->speech_enc_pe[frameno * tcx10Size], L_frame / nSubframes, r ); + + adapt_lag_wind( r, M, alw_pitch_lag_12k8[frameno], alw_voicing[frameno], st->sr_core ); + + lev_dur( A, r, M, NULL ); + + a2lsp_stab( A, lsp[nSubframes - 1 - frameno], st->lspold_enc ); + } + + if ( st->igf ) + { + ProcessIGF( st, hTcxEnc->spectrum[frameno], hTcxEnc->spectrum[frameno], powerSpec, transform_type[frameno] == TCX_20, frameno, 0, vad_hover_flag ); + } + } + } + if ( st->element_mode != IVAS_CPE_MDCT ) + { + /* Copy memory */ + mvr2r( lsp_new, st->lspold_enc, M ); + } + + return; +} +#endif diff --git a/lib_enc/hq_core_enc.c b/lib_enc/hq_core_enc.c index 277fdaaad..b2e599e1d 100644 --- a/lib_enc/hq_core_enc.c +++ b/lib_enc/hq_core_enc.c @@ -240,7 +240,6 @@ void hq_core_enc_ivas_fx( IF( st->bwidth_sw_cnt > 0 ) { - Word16 exp; Word32 L_tmp; tmp = BASOP_Util_Divide1616_Scale( 3, BWS_TRAN_PERIOD, &exp ); shr( tmp, exp ); diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 93e1c658a..928295720 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -186,8 +186,12 @@ static Word16 IGF_getCrest_new_fx( x_eff = BASOP_Util_Divide3216_Scale( x_eff, sub( stop, start ), &temp_e ); temp_e = add( temp_e, 16 ); /*exp += 31 - 15 + 16(because x_eff is word32)*/ + x_eff = L_shr( x_eff, sub( 15, temp_e ) ); + temp_e = 15; + move16(); temp = Sqrt16( extract_l( x_eff ), &temp_e ); + test(); IF( x_eff > 0 && x_max > 0 ) { temp = BASOP_Util_Divide1616_Scale( x_max, temp, &exp ); @@ -268,9 +272,9 @@ static Word16 IGF_getSFM_new_fx( Word16 tmp_e; num = 0; - denom = 1; - denom_e = 31; - sfm = 1; + denom = ONE_IN_Q30; + denom_e = 1; + sfm = MAX16B; // Q15 move16(); move32(); move16(); @@ -292,10 +296,10 @@ static Word16 IGF_getSFM_new_fx( IF( denom != 0 ) { - tmp = BASOP_util_Pow2( L_add( numf, shl_sat( 1, sub( 14, numf_e ) ) ), 16 + numf_e, &tmp_e ); + tmp = BASOP_util_Pow2( L_add( numf, shl_sat( 1, sub( 14, numf_e ) ) ), add( 16, numf_e ), &tmp_e ); sfm = BASOP_Util_Divide3232_Scale( tmp, denom, &sfm_e ); sfm_e = add( sfm_e, sub( tmp_e, denom_e ) ); - sfm = shl_sat( extract_l( L_min( sfm, L_shl( 1, 15 - sfm_e ) ) ), sfm_e ); + sfm = shl_sat( extract_l( L_min( sfm, L_shl( 1, sub( 15, sfm_e ) ) ) ), sfm_e ); } return sfm; @@ -441,7 +445,6 @@ static float IGF_getTilt( return slope; } - /*-------------------------------------------------------------------* * IGF_getTNR() * @@ -517,17 +520,25 @@ static Word32 IGF_getTNR_fx( } } - /*tonalToNoise=20.f * log10f( max( 1e-018f, tonal / noise ) )*/ - Word16 temp = BASOP_Util_Divide3232_Scale( tonal, noise, &tmp_e ); /*tonal / noise*/ - tmp_e = add( tmp_e, sub( tonal_e, noise_e ) ); - IF( GE_16( temp, 1 ) ) + /*tonalToNoise = 20.f * log10f( max( 1e-018f, tonal / noise ) )*/ + IF( noise == 0 ) // To handle condition if denom = 0 { - tonalToNoise = L_shr( imult3216( Mult_32_16( L_add( BASOP_Util_Log2( temp ), L_shl( add( 16, tmp_e ), Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*25+15-15*/, 20 ) /*25*/, 3 ); /*Q22*/ + tonalToNoise = imult3216( L_shr( L_add( L_shl( 18 /* log10f(1e-018f) */, Q25 ), Mpy_32_16_1( L_add( BASOP_Util_Log2( tonal ), L_shl( tonal_e, Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*25+15-15*/ ), 3 ) /*Q22*/, 20 ); + move32(); } ELSE { - tonalToNoise = -1509949440; /*-360.f Q22*/ - move32(); + Word16 temp = BASOP_Util_Divide3232_Scale( tonal, noise, &tmp_e ); /*tonal / noise*/ + tmp_e = add( tmp_e, sub( tonal_e, noise_e ) ); + IF( GE_16( temp, 1 ) ) + { + tonalToNoise = L_shr( imult3216( Mult_32_16( L_add( BASOP_Util_Log2( temp ), L_shl( add( 16, tmp_e ), Q25 ) ) /*Q25*/, INV_Log2_10_Q15 ) /*25+15-15*/, 20 ) /*25*/, 3 ); /*Q22*/ + } + ELSE + { + tonalToNoise = -1509949440; /*-360.f Q22*/ + move32(); + } } return tonalToNoise; @@ -898,6 +909,540 @@ static void IGF_CalculateEnvelope( return; } +#ifdef IVAS_FLOAT_FIXED +static void IGF_CalculateEnvelope_ivas_fx( + const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ + Word32 *pMDCTSpectrum_fx, /* i : MDCT spectrum */ + Word16 e_mdct, /* i : exp of MDCT spectrum */ + Word32 *pPowerSpectrum_fx, /* i : MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 e_ps, /* i : exp of power spectrum */ + const Word16 igfGridIdx, /* i : IGF grid index */ + const Word16 isTransient, /* i : flag indicating if transient is detected */ + const Word16 last_core_acelp, /* i : indicator if last frame was ACELP core */ + const Word16 element_mode, /* i : IVAS element_mode */ + const Word16 att /* i : attenuation */ +) +{ + IGF_ENC_PRIVATE_DATA_HANDLE hPrivateData; + H_IGF_GRID hGrid; + Word16 *swb_offset; + Word16 sfb; /* this is the actual scalefactor band */ + Word16 width; /* this is width in subbands of the actual scalefactor band */ + Word16 tile_idx; + Word16 strt_cpy; + Word32 gain; /* the gain which has to be applied to the source tile to get the destination energy */ + Word16 sb; + Word32 sfbEnergyR; + Word32 sfbEnergyC; /* the energy of the destination region of the tile */ + Word32 sfbEnergyTileR; + Word32 sfbEnergyTileC; /* the energy of the destination region of the tile */ + Word16 tmp, x, y; + Word16 mean_x_fx, mean_y_fx; + Word32 mean_xy_fx, mean_x2_fx; + Word16 tmp_tb; + Word16 tmp_sb; + Word16 sfbCnt; + Word16 sfm; + Word16 crest; + Word16 temp; + Word16 mean_x_e, mean_y_e; /*Stores exponent for mean_x and mean_y respectively*/ + Word16 mean_xy_e, mean_x2_e; /*stores exponent for mean_xy and mean_x2 respectively*/ + Word16 sfbEnergyTileR_e; /*Exponent for sfbEnergyTileR*/ + Word16 sfbEnergyTileC_e; /*Exponent for sfbEnergyTileC*/ + Word16 sfbEnergyC_e; /*Exponent for sfbEnergyC*/ + Word16 sfbEnergyR_e; + Word16 gain_e; /*exponent for gain*/ + Word16 tmp_tb_e; /*Stores exponent for tmp_tb*/ + Word16 tmp_sb_e; /*stores exponent for tmp_sb*/ + Word16 crest_exp; /*Stores the exponent of the result(return value)*/ + Word16 sfm_exp; /*stores exponent for ouput from sfm*/ + Word16 tmp_e; + + hPrivateData = &hIGFEnc->igfData; + hGrid = &hPrivateData->igfInfo.grid[(int16_t) igfGridIdx]; + swb_offset = hGrid->swb_offset; + + IF( element_mode > EVS_MONO ) + { + IF( igfGridIdx != IGF_GRID_LB_NORM ) + { + FOR( sfbCnt = 0; sfbCnt < sub( hGrid->sfbWrap[hGrid->nTiles], hGrid->sfbWrap[0] ); sfbCnt++ ) + { + /* reset filter */ + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_FIR_TB_e[sfbCnt] + hPrivateData->prevSFB_FIR_TB_e[sfbCnt] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_IIR_TB_e[sfbCnt] + hPrivateData->prevSFB_IIR_TB_e[sfbCnt] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_FIR_SB_e[sfbCnt] + hPrivateData->prevSFB_FIR_SB_e[sfbCnt] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfbCnt] = 0; // exponent : hPrivateData->prevSFB_IIR_SB_e[sfbCnt] + hPrivateData->prevSFB_IIR_SB_e[sfbCnt] = 0; + hPrivateData->prevDampingFactor_IIR_fx[sfbCnt] = MIN16B; /* -1.f in Q15*/ + hPrivateData->prevDampingFactor_IIR_e[sfbCnt] = 0; + hPrivateData->dampingFactorSmoothing[sfbCnt] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + } + + IF( pPowerSpectrum_fx ) + { + FOR( sb = hGrid->sbWrap[0]; sb < swb_offset[hGrid->sfbWrap[hGrid->nTiles]]; sb++ ) + { + IF( LT_32( 1, pPowerSpectrum_fx[sb] ) ) + { + hPrivateData->logSpec[sb] = s_max( 0, (Word16) L_shr( L_add( BASOP_Util_Log2( pPowerSpectrum_fx[sb] ), L_shl( e_ps, Q25 ) ), Q25 ) ); + move16(); + } + ELSE + { + hPrivateData->logSpec[sb] = 0; + move16(); + } + } + } + + FOR( tile_idx = 0; tile_idx < hGrid->nTiles; tile_idx++ ) + { + strt_cpy = hGrid->sbWrap[tile_idx]; + move16(); + + FOR( sfb = hGrid->sfbWrap[tile_idx]; sfb < hGrid->sfbWrap[tile_idx + 1]; sfb++ ) + { + width = sub( swb_offset[sfb + 1], swb_offset[sfb] ); + sfbEnergyTileR = EPSILON_FIX; + sfbEnergyTileC = EPSILON_FIX; + sfbEnergyC = EPSILON_FX; + sfbEnergyTileR_e = 0; + sfbEnergyTileC_e = 0; + sfbEnergyC_e = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + IF( pPowerSpectrum_fx != NULL ) + { + tmp = strt_cpy; + move16(); + FOR( sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++ ) + { + sfbEnergyC = BASOP_Util_Add_Mant32Exp( sfbEnergyC, sfbEnergyC_e, pPowerSpectrum_fx[sb], e_ps, &sfbEnergyC_e ); + sfbEnergyTileR = BASOP_Util_Add_Mant32Exp( sfbEnergyTileR, sfbEnergyTileR_e, Mult_32_32( pMDCTSpectrum_fx[strt_cpy], pMDCTSpectrum_fx[strt_cpy] ), shl( e_mdct, 1 ), &sfbEnergyTileR_e ); + sfbEnergyTileC = BASOP_Util_Add_Mant32Exp( sfbEnergyTileC, sfbEnergyTileC_e, pPowerSpectrum_fx[strt_cpy], e_ps, &sfbEnergyTileC_e ); + + strt_cpy = add( strt_cpy, 1 ); + } + + sfbEnergyTileR = L_deposit_l( BASOP_Util_Divide3232_Scale( sfbEnergyTileR, width, &tmp_e ) ); + sfbEnergyTileR_e = add( sub( sfbEnergyTileR_e, Q15 ), tmp_e ); + + IF( sfbEnergyTileR == 0 ) + { + sfbEnergyTileR = EPSILON_FX; + sfbEnergyTileR_e = 0; + move32(); + move16(); + } + IF( sfbEnergyC == 0 ) + { + sfbEnergyC = EPSILON_FX; + sfbEnergyC_e = 0; + move32(); + move16(); + } + IF( sfbEnergyTileC == 0 ) + { + sfbEnergyTileC = EPSILON_FX; + sfbEnergyTileC_e = 0; + temp = BASOP_Util_Divide3232_Scale( sfbEnergyC, sfbEnergyTileC, &tmp_e ); + tmp_e = add( tmp_e, sub( sfbEnergyC_e, sfbEnergyTileC_e ) ); + move32(); + move16(); + } + ELSE + { + /*gain = (float) ( sfbEnergyTileR * ( sfbEnergyC / sfbEnergyTileC ) );*/ + temp = BASOP_Util_Divide3232_Scale( sfbEnergyC, sfbEnergyTileC, &tmp_e ); + tmp_e = add( tmp_e, sub( sfbEnergyC_e, sfbEnergyTileC_e ) ); + } + + gain = Mult_32_16( sfbEnergyTileR, temp ); // gain_e + gain_e = add( tmp_e, sfbEnergyTileR_e ); + + test(); + IF( element_mode > EVS_MONO ) + { + test(); + IF( !isTransient ) + { + Word16 diffSFM; + Word16 shiftedSFM = 0; + Word16 shiftedSFM_e = 0; + move16(); + move16(); + + // tmp_tb = IGF_getSFM_new( pPowerSpectrum, hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1] ) / IGF_getCrest_new( hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1] ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1], e_ps ); + sfm_exp = 0; + move16(); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb], swb_offset[sfb + 1], &crest_exp ); + tmp_tb = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); // tmp_tb_e + tmp_tb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); + + // tmp_sb = IGF_getSFM_new( pPowerSpectrum, hPrivateData->logSpec, tmp, strt_cpy ) / IGF_getCrest_new( hPrivateData->logSpec, tmp, strt_cpy ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, tmp, strt_cpy, e_ps ); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, tmp, strt_cpy, &crest_exp ); + tmp_sb = BASOP_Util_Divide1616_Scale( sfm, crest, &tmp_e ); // tmp_sb_e + tmp_sb_e = add( tmp_e, sub( sfm_exp, crest_exp ) ); + + test(); + IF( last_core_acelp || hPrivateData->wasTransient ) + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = tmp_tb; /*Exponent for hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] : hPrivateData->prevSFB_FIR_TB_e[sfb] and hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] : hPrivateData->prevSFB_IIR_TB_e[sfb] */ + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = tmp_sb; /*Exponent for hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] : hPrivateData->prevSFB_FIR_SB_e[sfb] and hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] : hPrivateData->prevSFB_IIR_SB_e[sfb] */ + hPrivateData->prevSFB_FIR_TB_e[sfb] = hPrivateData->prevSFB_IIR_TB_e[sfb] = tmp_tb_e; + hPrivateData->prevSFB_FIR_SB_e[sfb] = hPrivateData->prevSFB_IIR_SB_e[sfb] = tmp_sb_e; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + + tmp_tb = shr( tmp_tb, 2 ); /*taking 2 guard bits so it's exponent tmp_sb_e=+2*/ + tmp_sb = shr( tmp_sb, 2 ); /*taking 2 guard bits so it's exponent tmp_tb_e=+2 */ + tmp_sb_e = add( tmp_sb_e, 2 ); + tmp_tb_e = add( tmp_tb_e, 2 ); + + Word16 tmp0, tmp2, tmp3, tmp4; + Word16 tmp0_e, tmp2_e, tmp3_e, tmp4_e; + tmp0 = shr( hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb], 2 ); + tmp0_e = hPrivateData->prevSFB_FIR_TB_e[sfb] + 2; + tmp2 = shr( hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb], 2 ); + tmp2_e = hPrivateData->prevSFB_IIR_TB_e[sfb] + 2; + tmp3 = shr( hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb], 2 ); + tmp3_e = hPrivateData->prevSFB_FIR_SB_e[sfb] + 2; + tmp4 = shr( hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb], 2 ); + tmp4_e = hPrivateData->prevSFB_IIR_SB_e[sfb] + 2; + + Word16 x1, x2; + + Word16 x1_e = BASOP_Util_Add_MantExp( tmp0, tmp0_e, tmp2, tmp2_e - 1, &x1 ); + Word16 x2_e = BASOP_Util_Add_MantExp( tmp3, tmp3_e, tmp4, tmp4_e - 1, &x2 ); + + hPrivateData->sfb_tb_e[sfb] = BASOP_Util_Add_MantExp( tmp_tb, tmp_tb_e, x1, x1_e, &hPrivateData->SFM_tb_fx[sfb] ); // hPrivateData->sfb_sb_e[sfb] + hPrivateData->SFM_tb_fx[sfb] = extract_l( L_min( L_shl( 22118 /*2.7f Q13*/, sub( 2, hPrivateData->sfb_tb_e[sfb] ) ), hPrivateData->SFM_tb_fx[sfb] ) ); + hPrivateData->sfb_sb_e[sfb] = BASOP_Util_Add_MantExp( tmp_sb, tmp_sb_e, x2, x2_e, &hPrivateData->SFM_sb_fx[sfb] ); // hPrivateData->sfb_tb_e[sfb] + hPrivateData->SFM_sb_fx[sfb] = extract_l( L_min( L_shl( 22118 /*2.7f Q13*/, sub( 2, hPrivateData->sfb_sb_e[sfb] ) ), hPrivateData->SFM_sb_fx[sfb] ) ); + move16(); + move16(); + move16(); + move16(); + + BASOP_Util_Add_MantExp( hPrivateData->SFM_sb_fx[sfb], hPrivateData->sfb_sb_e[sfb], negate( hPrivateData->SFM_tb_fx[sfb] ), hPrivateData->sfb_tb_e[sfb], &diffSFM ); + + test(); + IF( diffSFM > 0 && LT_32( hPrivateData->SFM_tb_fx[sfb], L_shr( 3277 /*0.1 Q15*/, tmp_tb_e ) ) ) /* check whether target SFB is more tonal than source SFB */ + { + Word16 currDampingFactor, dampingFactor; + Word16 slope, threshold; + Word16 alpha; + Word16 slope_e, threshold_e, currDampingFactor_e, dampingFactor_e, alpha_e; + + /* calculate spectral tilt to detect sudden drops (or increases) in energy in the current SFB */ + // slope = IGF_getTilt_fx( pPowerSpectrum, swb_offset[sfb], swb_offset[sfb + 1], e_ps, &slope_e ); + + x = 1; + mean_x_fx = mean_y_fx = 0; + mean_xy_fx = mean_x2_fx = 0; + mean_x_e = mean_y_e = 15; + mean_xy_e = mean_x2_e = 31; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + + test(); + FOR( sb = swb_offset[sfb]; sb < swb_offset[sfb + 1]; sb++ ) + { + mean_x_fx = add( mean_x_fx, x ); /*Q0*/ + mean_x2_fx = L_add( mean_x2_fx, L_mult0( x, x ) ); /*Q0*/ + + test(); + /*y = 20 * (int16_t) log10f( max( 1e-018f, pPowerSpectrum[sb] ) );*/ + IF( LT_32( pPowerSpectrum_fx[sb], 1 ) ) + { + y = imult1616( 20, ( -18 /* log10f(1e-018f) */ ) ); + } + ELSE + { + y = imult1616( 20, extract_l( L_shr( Mult_32_16( ( L_add( BASOP_Util_Log2( pPowerSpectrum_fx[sb] ), L_shl( e_ps, Q25 ) ) ), INV_Log2_10_Q15 ), Q25 ) ) ); /*Q0*/ + } + mean_y_fx = add( mean_y_fx, y ); /*Q0*/ + mean_xy_fx = L_add( mean_xy_fx, L_mult0( y, x ) ); /*Q0*/ + + x = add( x, 1 ); + } + mean_y_fx = BASOP_Util_Divide1616_Scale( mean_y_fx, width, &tmp_e ); /* mean_y_e*/ + mean_y_e = add( mean_y_e, sub( tmp_e, 15 ) ); + mean_x_fx = BASOP_Util_Divide1616_Scale( mean_x_fx, width, &tmp_e ); /* mean_x_e*/ + mean_x_e = add( mean_x_e, sub( tmp_e, 15 ) ); + mean_xy_fx = BASOP_Util_Divide3216_Scale( mean_xy_fx, width, &tmp_e ); /* mean_xy_e*/ + mean_xy_e = add( mean_xy_e, sub( tmp_e, 15 ) ); + mean_x2_fx = BASOP_Util_Divide3216_Scale( mean_x2_fx, width, &tmp_e ); /* mean_x2_e*/ + mean_x2_e = add( mean_x2_e, sub( tmp_e, 15 ) ); + + /*slope = ( mean_xy - mean_x * mean_y ) / ( mean_x2 - mean_x * mean_x );*/ + slope = BASOP_Util_Divide3232_Scale( ( L_sub( mean_xy_fx, L_shl( mult( mean_x_fx, mean_y_fx ), sub( add( mean_x_e, mean_y_e ), mean_xy_e ) ) ) ), ( L_sub( mean_x2_fx, L_shl( mult( mean_x_fx, mean_x_fx ), sub( add( mean_x_e, mean_x_e ), mean_x2_e ) ) ) ), &slope_e ); + slope_e = add( slope_e, sub( mean_xy_e, mean_x2_e ) ); + + /* determine whether strong tilt is due to a step in the spectrum (e.g. band limitation, no damping) + or a tonal component close the band border (apply damping) by calculating SFM for a shift of 1/2 SFB width*/ + threshold = BASOP_Util_Divide1616_Scale( 60, width, &threshold_e ); + + test(); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( slope, add( slope_e, 16 ), negate( threshold ), add( threshold_e, 16 ) ), -1 ) ) + { + Word16 shift = shr( width, 1 ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift, e_ps ); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb] - shift, swb_offset[sfb + 1] - shift, &crest_exp ); + shiftedSFM = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); + } + ELSE IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( slope, add( slope_e, 16 ), threshold, add( threshold_e, 16 ) ), 1 ) && ( NE_16( sfb, sub( hGrid->sfbWrap[hGrid->nTiles], 1 ) ) ) ) + { + Word16 shift = shr( width, 1 ); + shiftedSFM = BASOP_Util_Divide1616_Scale( IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, e_ps ), IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, &crest_exp ), &tmp_e ); + sfm = IGF_getSFM_new_fx( pPowerSpectrum_fx, hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, e_ps ); + crest = IGF_getCrest_new_fx( hPrivateData->logSpec, swb_offset[sfb] + shift, swb_offset[sfb + 1] + shift, &crest_exp ); + shiftedSFM = BASOP_Util_Divide1616_Scale( sfm, crest, &shiftedSFM_e ); + } + shiftedSFM_e = add( shiftedSFM_e, sub( sfm_exp, crest_exp ) ); + + IF( GT_32( shiftedSFM, L_shl( 1311 /*0.04f Q15*/, negate( shiftedSFM_e ) ) ) ) + { + currDampingFactor = 32767; /*1.f Q15*/ + currDampingFactor_e = 0; + move16(); + move16(); + } + ELSE + { + // alpha = min( 320.f / (float) swb_offset[sfb + 1], 1.25f ); + temp = BASOP_Util_Divide1616_Scale( 320, swb_offset[sfb + 1], &alpha_e ); + alpha = extract_l( L_min( temp, L_shl( 20480 /*1.25 Q14*/, sub( 1, alpha_e ) ) ) ); // alpha_e + + // currDampingFactor = expf( 1.25f * alpha * logf( hPrivateData->SFM_tb[sfb] / hPrivateData->SFM_sb[sfb] ) ); + temp = BASOP_Util_Divide1616_Scale( hPrivateData->SFM_tb_fx[sfb], hPrivateData->SFM_sb_fx[sfb], &tmp_e ); // tmp_e + tmp_e = add( tmp_e, sub( hPrivateData->sfb_tb_e[sfb], hPrivateData->sfb_sb_e[sfb] ) ); + Word16 temp1 = mult( 20480 /* 1.25f in Q14 */, alpha ); + Word16 tmp1_e = add( 1, alpha_e ); + currDampingFactor = round_fx( BASOP_util_Pow2( Mpy_32_16_1( L_add( BASOP_Util_Log2( temp ), L_shl_sat( add( 16, tmp_e ), 25 ) ), temp1 ), add( tmp1_e, 6 ), &currDampingFactor_e ) ); // currDampingFactor_e + + /* calculate tonal-to-noise ratio and reduce damping for low values*/ + + Word32 tonalToNoise; + Word16 adap; + Word16 adap_e; /*stores exp for adap*/ + Word16 tonalToNoise_e; /*stores exponent for tonalToNoise*/ + tonalToNoise_e = 9; + move16(); + adap = BASOP_Util_Divide1616_Scale( width, 40, &adap_e ); + tonalToNoise = IGF_getTNR_fx( pPowerSpectrum_fx, swb_offset[sfb], swb_offset[sfb + 1], adap, e_ps, adap_e ); /*Q22*/ + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tonalToNoise, tonalToNoise_e, L_add( L_shl( 10, sub( 15, adap_e ) ), adap ), add( 16, adap_e ) ), -1 ) ) + { + // currDampingFactor += 0.03f * ( ( 10 + adap ) - tonalToNoise ); + Word32 temp2 = BASOP_Util_Add_Mant32Exp( L_add( L_shl( 10, sub( 15, adap_e ) ) /*exp:adap_e*/, adap ), add( adap_e, 16 ), L_negate( tonalToNoise ), tonalToNoise_e, &tmp_e ); // tmp_e + currDampingFactor_e = BASOP_Util_Add_MantExp( currDampingFactor, currDampingFactor_e, extract_l( Mult_32_32( 983 /*0.03f Q15*/, temp2 ) ), tmp_e, &currDampingFactor ); // currDampingFactor_e + } + } + + Word32 L_tmp = hPrivateData->prevDampingFactor_IIR_fx[sfb]; + move32(); + L_tmp = L_shl( L_tmp, hPrivateData->prevDampingFactor_IIR_e[sfb] ); + test(); + test(); + IF( last_core_acelp || hPrivateData->wasTransient || EQ_32( L_tmp, MIN16B ) ) + { + tmp = BASOP_Util_Cmp_Mant32Exp( currDampingFactor, currDampingFactor_e, 3277 /* 0.1f in Q15 */, 0 ); + IF( tmp >= 0 ) + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = currDampingFactor; + hPrivateData->prevDampingFactor_IIR_e[sfb] = currDampingFactor_e; + move16(); + move16(); + } + ELSE + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = 3277; /* 0.1 in Q15 */ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + move16(); + move16(); + } + } + IF( last_core_acelp ) + { + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + } + + dampingFactor_e = BASOP_Util_Add_MantExp( currDampingFactor, currDampingFactor_e, hPrivateData->prevDampingFactor_IIR_fx[sfb], hPrivateData->prevDampingFactor_IIR_e[sfb], &dampingFactor ); // dampingFactor_e + dampingFactor = shr( dampingFactor, 1 ); + + gain = Mult_32_16( gain, shl_sat( extract_l( L_min( L_add( dampingFactor, Mult_32_16( L_shl( hPrivateData->dampingFactorSmoothing[sfb], sub( 15, dampingFactor_e ) ) /*Q:15-dampingFactor_e*/, 3277 /*0.1f Q15*/ ) /*Q:15-dampingFactor_e*/ ), shl_sat( 1, sub( 15, dampingFactor_e ) ) ) ), dampingFactor_e ) /*Q15*/ ); + + hPrivateData->prevDampingFactor_IIR_fx[sfb] = dampingFactor; + move16(); + hPrivateData->prevDampingFactor_IIR_e[sfb] = dampingFactor_e; + move16(); + test(); + IF( hPrivateData->dampingFactorSmoothing[sfb] > 0 ) + { + hPrivateData->dampingFactorSmoothing[sfb] = sub( hPrivateData->dampingFactorSmoothing[sfb], 1 ); + move16(); + } + } + ELSE + { + hPrivateData->prevDampingFactor_IIR_fx[sfb] = MIN16B; // exponent : hPrivateData->prevDampingFactor_IIR_e[sfb] + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 1; + move16(); + move16(); + move16(); + } + + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = tmp_tb; // hPrivateData->prevSFB_FIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_TB_e[sfb] = tmp_tb_e; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = hPrivateData->SFM_tb_fx[sfb]; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_IIR_TB_e[sfb] = hPrivateData->sfb_tb_e[sfb]; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = tmp_sb; // hPrivateData->prevSFB_FIR_SB_e[sfb] + hPrivateData->prevSFB_FIR_SB_e[sfb] = tmp_sb_e; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = hPrivateData->SFM_sb_fx[sfb]; // hPrivateData->prevSFB_IIR_SB_e[sfb] + hPrivateData->prevSFB_IIR_SB_e[sfb] = hPrivateData->sfb_sb_e[sfb]; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + ELSE + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_FIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_IIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_SB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_SB_e[sfb] + hPrivateData->prevSFB_IIR_SB_e[sfb] = 0; + hPrivateData->prevDampingFactor_IIR_fx[sfb] = MIN16B; /* hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + } + ELSE + { + tmp_e = e_mdct; + sfbEnergyR = add_sat( EPSILON_FX, BASOP_Util_Divide3216_Scale( sum2_32_fx( pMDCTSpectrum_fx + swb_offset[sfb], width, &tmp_e ) /*exp: tmp_e*/, width, &sfbEnergyR_e ) ); // sfbEnergyR_e + sfbEnergyR_e = add( sfbEnergyR_e, add( tmp_e, -15 ) ); + gain = sfbEnergyR; // gain_e + move32(); + gain_e = add( sfbEnergyR_e, 16 ); + + IF( element_mode > EVS_MONO ) + { + hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_FIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_IIR_TB_e[sfb] = 0; + hPrivateData->prevSFM_FIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_TB_e[sfb] + hPrivateData->prevSFB_FIR_SB_e[sfb] = 0; + hPrivateData->prevSFM_IIR_SFB_SB_fx[sfb] = 0; // hPrivateData->prevSFB_IIR_SB_e[sfb] + hPrivateData->prevSFB_IIR_SB_e[sfb] = 0; + hPrivateData->prevDampingFactor_IIR_fx[sfb] = MIN16B; /* hPrivateData->prevDampingFactor_IIR_e[sfb]*/ + hPrivateData->prevDampingFactor_IIR_e[sfb] = 0; + hPrivateData->dampingFactorSmoothing[sfb] = 2; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + } + } + + gain = Mult_32_16( gain, att ); // gain_e + gain_e = add( gain_e, 0 ); + + /*gain=0.5f+log2f(gain)*2+16 becuase 2.885390081777927f=2*1/loge(2) so 2*1/loge(2)*loge(x) can be written as 2*log2(x)*/ + gain = L_add( ONE_IN_Q22, L_add( L_add( L_shr( BASOP_Util_Log2( gain ), 1 ), L_shl( gain_e, Q24 ) ), L_shl( 16, Q23 ) ) ); /*Q23*/ + test(); + test(); + IF( !isTransient && ( EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_48000_CPE ) || EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_FB_48000_CPE ) ) ) + { + gain = L_add( gain, ONE_IN_Q21 ); /* better preservation of original HF band energy */ + } + test(); + test(); + IF( !isTransient && ( EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_SWB_64000_CPE ) || EQ_16( hPrivateData->igfInfo.bitRateIndex, IGF_BITRATE_FB_64000_CPE ) ) ) + { + gain = L_add( gain, ONE_IN_Q20 ); + } + gain = L_min( gain, 91 << Q23 ); /* 13+15+63, see arithcode encode residual */ + gain = L_max( gain, 0 ); + gain_e = 8; /* stores exponent for gain_fx*/ + move16(); + hPrivateData->igfScfQuantized[sfb] = extract_l( L_shr( gain, Q23 ) ); /*Q0*/ + move16(); + } + } + + return; +} +#endif /*-------------------------------------------------------------------* * IGF_CalculateStereoEnvelope_fx() @@ -1359,7 +1904,8 @@ static void IGF_CalculateStereoEnvelope_fx( sfbEnergyR_fx = add_sat( EPSILON_FX, BASOP_Util_Divide3216_Scale( sum2_32_fx( pMDCTSpectrum_fx + swb_offset[sfb], width, &tmp_e ) /*exp: tmp_e*/, width, &sfbEnergyR_e ) ); sfbEnergyR_e = add( sfbEnergyR_e, add( tmp_e, -15 ) ); /* stores resultant exponent for sfbEnergyR_fx*/ gain_fx = sfbEnergyR_fx; /*resultant exponent stored in gain_e=sfbEnergyR_e*/ - gain_e = add( sfbEnergyR_e, 16 ); /* because gain_fx is word32;only after adding 16 q of gain_fx is 15-sfbEnergyR_e*/ + move32(); + gain_e = add( sfbEnergyR_e, 16 ); /* because gain_fx is word32;only after adding 16 q of gain_fx is 15-sfbEnergyR_e*/ hPrivateData->prevSFM_FIR_SFB_TB_fx[sfb] = 0; hPrivateData->prevSFM_IIR_SFB_TB_fx[sfb] = 0; @@ -1385,6 +1931,7 @@ static void IGF_CalculateStereoEnvelope_fx( gain_e = 8; /* stores exponent for gain_fx*/ move16(); hPrivateData->igfScfQuantized[sfb] = (Word16) ( L_shr( gain_fx, 23 ) ); /*Q0*/ + move16(); } } @@ -2291,8 +2838,8 @@ static void IGF_Whitening_ivas_fx( test(); test(); test(); - IF( ( EQ_16( hPrivateData->igfPrevWhiteningLevel[p], IGF_WHITENING_OFF ) && NE_16( hPrivateData->igfCurrWhiteningLevel[p], IGF_WHITENING_OFF ) ) || - ( EQ_16( hPrivateData->igfPrevWhiteningLevel[p + 1], IGF_WHITENING_OFF ) && NE_16( hPrivateData->igfCurrWhiteningLevel[p + 1], IGF_WHITENING_OFF ) ) ) + IF( ( hPrivateData->igfPrevWhiteningLevel[p] == IGF_WHITENING_OFF && hPrivateData->igfCurrWhiteningLevel[p] != IGF_WHITENING_OFF ) || + ( hPrivateData->igfPrevWhiteningLevel[p + 1] == IGF_WHITENING_OFF && hPrivateData->igfCurrWhiteningLevel[p + 1] != IGF_WHITENING_OFF ) ) { Word16 i; Word16 pastSfm_a[4], pastSfm_b[4]; @@ -2324,7 +2871,7 @@ static void IGF_Whitening_ivas_fx( /* if tonality oscillates between two tiles, turn whitening off in both */ IF( ( ( pastSfmDiffSum_a > 0 && pastSfmDiffSum_b < 0 ) || ( pastSfmDiffSum_a < 0 && pastSfmDiffSum_b > 0 ) ) && - ( GT_16( abs_s( sub( pastSfmDiffSum_a, pastSfmDiffSum_b ) ), ONE_IN_Q13 ) ) ) + ( GT_32( L_abs( L_sub( pastSfmDiffSum_a, pastSfmDiffSum_b ) ), ONE_IN_Q12 /* 0.5 in Q13 */ ) ) ) { hPrivateData->igfCurrWhiteningLevel[p] = hPrivateData->igfCurrWhiteningLevel[p + 1] = IGF_WHITENING_OFF; move16(); @@ -2741,7 +3288,7 @@ static Word16 IGF_WriteWhiteningTile( /**< out: Q0 | numb ELSE { IGF_write_bits( hBstr, pBitOffset, 1, 1 ); - IF( EQ_32( whiteningLevel, IGF_WHITENING_OFF ) ) + IF( whiteningLevel == IGF_WHITENING_OFF ) { IGF_write_bits( hBstr, pBitOffset, 0, 1 ); } @@ -3208,6 +3755,10 @@ void IGFEncSetMode( set_f( hPrivateData->prevSFM_FIR_SFB_TB, 0, IGF_MAX_SFB ); set_f( hPrivateData->prevSFM_IIR_SFB_TB, 0, IGF_MAX_SFB ); set_f( hPrivateData->prevDampingFactor_IIR, -1, IGF_MAX_SFB ); +#ifdef IVAS_FLOAT_FIXED + set_s( hPrivateData->prevDampingFactor_IIR_fx, MIN16B, IGF_MAX_SFB ); + set_s( hPrivateData->prevDampingFactor_IIR_e, 0, IGF_MAX_SFB ); +#endif set_s( hPrivateData->logSpec, 0, L_FRAME_PLUS ); set_f( hPrivateData->SFM_sb, 0.f, IGF_MAX_SFB ); set_f( hPrivateData->SFM_tb, 0.f, IGF_MAX_SFB ); @@ -3551,6 +4102,80 @@ int16_t IGFEncWriteConcatenatedBitstream( * * apply the IGF encoder, main encoder interface *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void IGFEncApplyMono_ivas_fx( + Encoder_State *st, /* i : Encoder state */ + const Word16 igfGridIdx, /* i : IGF grid index */ + Word32 *pMDCTSpectrum_fx, /* i/o: MDCT spectrum */ + Word16 e_mdct, /* i : exponent of pMDCTspectrum */ + Word32 *pPowerSpectrum_fx, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 e_ps, /* i : exponent of pPowerSpectrum */ + const Word16 isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + const Word8 isTNSActive, /* i : flag indicating if the TNS is active */ + const Word16 sp_aud_decision0, /* i : first stage switching decision */ + const Word16 vad_hover_flag /* i : VAD hangover flag */ +) +{ + Word32 *pPowerSpectrumParameter_fx; + Word16 att_fx = MAX16B; + Word16 last_core_acelp; + Word16 highPassEner_exp; + move16(); + + test(); + IF( st->last_core == ACELP_CORE ) + { + last_core_acelp = 1; + move16(); + } + ELSE + { + last_core_acelp = 0; + move16(); + } + + test(); + IF( !isTNSActive && isTCX20 ) + { + pPowerSpectrumParameter_fx = pPowerSpectrum_fx; + } + ELSE + { + pPowerSpectrumParameter_fx = NULL; + } + + IGF_UpdateInfo( st->hIGFEnc, igfGridIdx ); + + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); + } + + IGF_CalculateEnvelope_ivas_fx( st->hIGFEnc, pMDCTSpectrum_fx, e_mdct, pPowerSpectrumParameter_fx, e_ps, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, st->element_mode, att_fx ); + + test(); + IF( isTCX20 ) + { + pPowerSpectrumParameter_fx = pPowerSpectrum_fx; + } + ELSE + { + pPowerSpectrumParameter_fx = NULL; + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IGF_Whitening_ivas_fx( st->hIGFEnc, pPowerSpectrumParameter_fx, &e_ps, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, isTNSActive, sp_aud_decision0, st->element_brate, st->element_mode ); + } + ELSE + { + IGF_Whitening_ivas_fx( st->hIGFEnc, pPowerSpectrumParameter_fx, &e_ps, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, isTNSActive, sp_aud_decision0, st->total_brate, st->element_mode ); + } + + IGF_ErodeSpectrum( &highPassEner_exp, st->hIGFEnc, pMDCTSpectrum_fx, pPowerSpectrumParameter_fx, e_ps, igfGridIdx ); +} +#endif void IGFEncApplyMono( Encoder_State *st, /* i : Encoder state */ @@ -3565,34 +4190,20 @@ void IGFEncApplyMono( { float *pPowerSpectrumParameter; /* If it is NULL it informs a function that specific handling is needed */ float att = 1.0f; - Word16 att_fx; int16_t last_core_acelp; last_core_acelp = ( st->last_core == ACELP_CORE ); pPowerSpectrumParameter = !isTNSActive && isTCX20 ? pPowerSpectrum : NULL; - IGF_UpdateInfo_ivas( st->hIGFEnc, igfGridIdx ); + IGF_UpdateInfo( st->hIGFEnc, igfGridIdx ); if ( st->element_mode == IVAS_CPE_DFT || st->element_mode == IVAS_CPE_TD ) { -#ifndef IVAS_FLOAT_FIXED calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); -#else -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - if ( st->hTdCngEnc != NULL ) - { - st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q7 ); - } -#endif - calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - att = fix16_to_float( att_fx, Q15 ); -#endif -#endif } + IGF_CalculateEnvelope( st->hIGFEnc, pMDCTSpectrum, pPowerSpectrumParameter, igfGridIdx, st->hTranDet->transientDetector.bIsAttackPresent, last_core_acelp, st->element_mode, att ); pPowerSpectrumParameter = isTCX20 ? pPowerSpectrum : NULL; diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index 93d90dbcd..a77a88a33 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -97,6 +97,7 @@ ivas_error ivas_core_enc( float *new_swb_speech; float new_swb_speech_buffer[L_FRAME48k + STEREO_DFT_OVL_MAX]; float bwe_exc_extended[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; + Word16 Q_new[CPE_CHANNELS]; #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float fixed conversions float voice_factors[CPE_CHANNELS][NB_SUBFR16k] = { 0 }; #else @@ -104,13 +105,14 @@ ivas_error ivas_core_enc( #endif #ifdef IVAS_FLOAT_FIXED Word32 *new_swb_speech_fx; - Word16 shb_speech_fx[L_FRAME16k]; + Word16 shb_speech_fx[L_FRAME16k]; // Q_shb_spch + Word16 Q_shb_spch; Word32 new_swb_speech_buffer_fx[L_FRAME48k + STEREO_DFT_OVL_MAX]; Word16 new_inp_resamp16k_fx[CPE_CHANNELS][L_FRAME16k]; Word16 hb_speech_fx[L_FRAME16k / 4]; - Word32 bwe_exc_extended_fx[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; - Word16 voice_factors_fx[CPE_CHANNELS][NB_SUBFR16k]; /* Q15 */ - Word16 old_syn_12k8_16k_fx[CPE_CHANNELS][L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + Word32 bwe_exc_extended_fx[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; /* 2 * Q_new */ + Word16 voice_factors_fx[CPE_CHANNELS][NB_SUBFR16k]; /* Q15 */ + Word16 old_syn_12k8_16k_fx[CPE_CHANNELS][L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ Word16 *new_swb_speech_fx1; Word16 new_swb_speech_buffer_fx1[L_FRAME48k + STEREO_DFT_OVL_MAX]; #endif @@ -134,7 +136,7 @@ ivas_error ivas_core_enc( ivas_error error; int16_t max_num_indices_BWE; #ifdef IVAS_FLOAT_FIXED - Word16 i, Q_new; + Word16 i; #endif push_wmops( "ivas_core_enc" ); @@ -446,7 +448,7 @@ ivas_error ivas_core_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS PWord16 *p; Word16 q = 0; - Word16 overlap, tmp, i; + Word16 overlap, tmp; Word16 left_overlap, right_overlap; IF( st->element_mode > EVS_MONO && ( st->last_core == ACELP_CORE || st->last_core == AMR_WB_CORE ) ) { @@ -567,7 +569,7 @@ ivas_error ivas_core_enc( } ELSE { - FOR( Word16 i = 0; i < L_FRAME32k; i++ ) + FOR( i = 0; i < L_FRAME32k; i++ ) { st->hTcxEnc->old_out_fx[i] = float_to_fix16( st->hTcxEnc->old_out[i], 0 ); } @@ -729,8 +731,8 @@ ivas_error ivas_core_enc( #else #ifdef IVAS_FLOAT_FIXED_CONVERSIONS /* Temporarily calculating variable Q. Will get Q values from core processing */ - Q_new = Q_factor_arrL( bwe_exc_extended[n], L_FRAME32k + NL_BUFF_OFFSET ); - Q_new = Q_new / 2; + Q_new[n] = Q_factor_arrL( bwe_exc_extended[n], L_FRAME32k + NL_BUFF_OFFSET ); + Q_new[n] = Q_new[n] / 2; if ( st->hBWE_TD != NULL ) { Word16 tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb, 2 * ALLPASSSECTIONS_STEEP + 1 ); @@ -746,7 +748,7 @@ ivas_error ivas_core_enc( floatToFixed_arr16( new_inp_resamp16k[n], new_inp_resamp16k_fx[n], -1, L_FRAME16k ); floatToFixed_arr( voice_factors[n], voice_factors_fx[n], Q15, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float floatToFixed_arr( pitch_buf[n], pitch_buf_fx[n], Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float - floatToFixed_arr32( bwe_exc_extended[n], bwe_exc_extended_fx[n], 2 * Q_new, L_FRAME32k + NL_BUFF_OFFSET ); + floatToFixed_arr32( bwe_exc_extended[n], bwe_exc_extended_fx[n], 2 * Q_new[n], L_FRAME32k + NL_BUFF_OFFSET ); // prev_lsp_wb_temp_fx, prev_lsp_wb_fx and prev_lpc_wb_fx in Q15. No float counterparts floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); @@ -788,7 +790,7 @@ ivas_error ivas_core_enc( IF( EQ_16( st->extl, WB_TBE ) ) { /* WB TBE encoder */ - wb_tbe_enc_ivas_fx( st, hb_speech_fx, bwe_exc_extended_fx[n], Q_new, voice_factors_fx[n], pitch_buf_fx[n] ); + wb_tbe_enc_ivas_fx( st, hb_speech_fx, bwe_exc_extended_fx[n], Q_new[n], voice_factors_fx[n], pitch_buf_fx[n] ); } ELSE IF( EQ_16( st->extl, WB_BWE ) && n == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) { @@ -799,7 +801,7 @@ ivas_error ivas_core_enc( fixedToFloat_arr( hb_speech_fx, hb_speech, -1, L_FRAME16k / 4 ); fixedToFloat_arr( voice_factors_fx[n], voice_factors[n], Q15, NB_SUBFR16k ); fixedToFloat_arr( pitch_buf_fx[n], pitch_buf[n], Q6, NB_SUBFR16k ); - fixedToFloat_arrL( bwe_exc_extended_fx[n], bwe_exc_extended[n], 2 * Q_new, L_FRAME32k + NL_BUFF_OFFSET ); + fixedToFloat_arrL( bwe_exc_extended_fx[n], bwe_exc_extended[n], 2 * Q_new[n], L_FRAME32k + NL_BUFF_OFFSET ); if ( st->hBWE_TD != NULL ) { @@ -841,7 +843,87 @@ ivas_error ivas_core_enc( { /* Common pre-processing for SWB(FB) TBE and SWB(FB) BWE */ #ifdef IVAS_FLOAT_FIXED - swb_pre_proc_ivas_fx( st, new_swb_speech, new_swb_speech_fx, shb_speech, realBuffer[n], imagBuffer[n], hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 realBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word32 imagBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; + Word16 new_swb_speech_16_fx[L_FRAME48k] = { 0 }; + Word16 q_realImagBuffer = Q_factor_arrL( (float *) &realBuffer[n][0][0], CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + q_realImagBuffer = s_min( q_realImagBuffer, Q_factor_arrL( (float *) &imagBuffer[n][0][0], CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ) ); + floatToFixed_arrL32( (float *) &realBuffer[n][0][0], (Word32 *) &realBuffer_fx[0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL32( (float *) &imagBuffer[n][0][0], (Word32 *) &imagBuffer_fx[0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + floatToFixed_arrL32( (float *) &st->cldfbSynTd->cldfb_state[0], (Word32 *) &st->cldfbSynTd->cldfb_state_fx[0], q_realImagBuffer, st->cldfbSynTd->p_filter_length ); + +#if 0 + floatToFixed_arr( &st->hSignalBuf->input_buff_flt[0], &st->hSignalBuf->input_buff[0], 0, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); +#else + for ( Word32 idx = 0; idx < ( L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); idx++ ) + { + st->hSignalBuf->input_buff[idx] = (Word16) st->hSignalBuf->input_buff_flt[0]; + } +#endif + if ( st->element_mode == IVAS_CPE_DFT ) + { + f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); + f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); + f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); + f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); + f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); + floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); + } + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input_fx[ii] = (Word16) st->hBWE_FD->old_input[ii]; + } +#if 0 + floatToFixed_arr( (float *) &st->hBWE_FD->old_wtda_swb[0], (Word16 *) &st->hBWE_FD->L_old_wtda_swb_fx[0], 0, L_FRAME48k ); + floatToFixed_arr( (float *) &st->hBWE_FD->old_fdbwe_speech[0], (Word16 *) &st->hBWE_FD->old_fdbwe_speech_fx[0], 0, L_FRAME48k ); + floatToFixed_arr( (float *) &st->hBWE_TD->old_speech_shb[0], (Word16 *) &st->hBWE_TD->old_speech_shb_fx[0], 0, L_LOOK_16k + L_SUBFR16k ); +#else + for ( Word32 idx = 0; idx < ( L_FRAME48k ); idx++ ) + { + st->hBWE_FD->L_old_wtda_swb_fx[idx] = (Word16) st->hBWE_FD->old_wtda_swb[idx]; + st->hBWE_FD->old_fdbwe_speech_fx[idx] = (Word16) st->hBWE_FD->old_fdbwe_speech[idx]; + } + for ( Word32 idx = 0; idx < ( L_LOOK_16k + L_SUBFR16k ); idx++ ) + { + st->hBWE_TD->old_speech_shb_fx[idx] = (Word16) st->hBWE_TD->old_speech_shb[idx]; + } +#endif +#endif + swb_pre_proc_ivas_fx( st, new_swb_speech_16_fx, new_swb_speech_fx, shb_speech_fx, realBuffer_fx, imagBuffer_fx, q_realImagBuffer, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( (Word16 *) &st->hBWE_TD->old_speech_shb_fx[0], (float *) &st->hBWE_TD->old_speech_shb[0], 0, L_LOOK_16k + L_SUBFR16k ); + fixedToFloat_arr( (Word16 *) &st->hBWE_FD->old_fdbwe_speech_fx[0], (float *) &st->hBWE_FD->old_fdbwe_speech[0], 0, L_FRAME48k ); + fixedToFloat_arr( (Word16 *) &st->hBWE_FD->L_old_wtda_swb_fx[0], (float *) &st->hBWE_FD->old_wtda_swb[0], 0, L_FRAME48k ); + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input[ii] = (Word16) st->hBWE_FD->old_input_fx[ii]; + } + fixedToFloat_arrL32( (Word32 *) &st->cldfbSynTd->cldfb_state_fx[0], (float *) &st->cldfbSynTd->cldfb_state[0], q_realImagBuffer, st->cldfbSynTd->p_filter_length ); + fixedToFloat_arr( new_swb_speech_16_fx, new_swb_speech, 0, L_FRAME48k ); + fixedToFloat_arr( shb_speech_fx, shb_speech, 0, L_FRAME16k ); + fixedToFloat_arrL32( (Word32 *) &realBuffer_fx[0][0], (float *) &realBuffer[n][0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + fixedToFloat_arrL32( (Word32 *) &imagBuffer_fx[0][0], (float *) &imagBuffer[n][0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); + st->hBWE_TD->cldfbHBLT_flt = fix16_to_float( st->hBWE_TD->cldfbHBLT, Q13 ); + + if ( st->element_mode == IVAS_CPE_DFT ) + { + hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); + hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); + hCPE->hStereoICBWE->icbweRefEner = me2f( hCPE->hStereoICBWE->icbweRefEner_fx, hCPE->hStereoICBWE->icbweRefEner_fx_e ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_res_8k_fx, hCPE->hStereoDft->output_mem_res_8k, 16, STEREO_DFT_OVL_8k ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx, 16, STEREO_DFT_OVL_MAX ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_12k8_fx, hCPE->hStereoDft->output_mem_dmx_12k8, 16, STEREO_DFT_OVL_12k8 ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); + fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); + } +#endif #else swb_pre_proc( st, new_swb_speech, shb_speech, realBuffer[n], imagBuffer[n], hCPE ); #endif @@ -868,7 +950,98 @@ ivas_error ivas_core_enc( { float fb_exc[L_FRAME16k]; +#ifdef IVAS_FLOAT_FIXED + Word16 fb_exc_fx[L_FRAME16k]; + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_fb_exc; + + /* Temporarily calculating variable Q. Will get Q values from core processing */ + Q_new[n] = Q_factor_arrL( bwe_exc_extended[n], L_FRAME32k + NL_BUFF_OFFSET ); + Q_new[n] = Q_new[n] / 2; + + Q_shb_spch = Q_factor_arr( shb_speech, L_FRAME16k ); + Q_shb_spch = min( Q_shb_spch, Q_factor_arr( st->hBWE_TD->old_speech_shb, L_LOOK_16k + L_SUBFR16k ) ); + Q_shb_spch = min( Q_shb_spch, Q_factor_arr( st->hBWE_TD->shb_inv_filt_mem, LPC_SHB_ORDER ) ); + + if ( st->hBWE_TD != NULL ) + { + Word16 tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb, 2 * ALLPASSSECTIONS_STEEP + 1 ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_syn_shbexc, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_lpc_syn, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->old_bwe_exc_extended, NL_BUFF_OFFSET ) ); + Word16 tmp_q_2 = Q_factor_arrL( st->hBWE_TD->mem_csfilt, 2 ); + st->prev_Q_bwe_exc = min( tmp_q_2, tmp_q_1 + 16 ) - 2 /* Guard bits */; /* This reset need to be looked into once core processing is complete */ + + tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_stp_swb, LPC_SHB_ORDER ); + st->prev_Q_bwe_syn = tmp_q_1; /* This reset need to be looked into once core processing is complete */ + } + + floatToFixed_arr( voice_factors[n], voice_factors_fx[n], Q15, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr( pitch_buf[n], pitch_buf_fx[n], Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr32( bwe_exc_extended[n], bwe_exc_extended_fx[n], 2 * Q_new[n], L_FRAME32k + NL_BUFF_OFFSET ); + + // prev_lsp_wb_temp_fx, prev_lsp_wb_fx and prev_lpc_wb_fx in Q15. No float counterparts + floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); + floatToFixed_arr( shb_speech, shb_speech_fx, Q_shb_spch, L_FRAME16k ); + + if ( st->hBWE_TD != NULL ) + { + floatToFixed_arr16( st->hBWE_TD->old_speech_shb, st->hBWE_TD->old_speech_shb_fx, Q_shb_spch, L_LOOK_16k + L_SUBFR16k ); + floatToFixed_arr16( st->hBWE_TD->shb_inv_filt_mem, st->hBWE_TD->shb_inv_filt_mem_fx, Q_shb_spch, LPC_SHB_ORDER ); // Check + floatToFixed_arr16( st->hBWE_TD->prev_lsp_shb, st->hBWE_TD->prev_lsp_shb_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->lsp_shb_spacing, st->hBWE_TD->lsp_shb_spacing_fx, Q15, 3 ); + floatToFixed_arr16( st->hBWE_TD->lsp_shb_slow_interpl, st->hBWE_TD->lsp_shb_slow_interpl_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->lsp_shb_fast_interpl, st->hBWE_TD->lsp_shb_fast_interpl_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->swb_lsp_prev_interp, st->hBWE_TD->swb_lsp_prev_interp_fx, Q15, LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->prev_lsf_diff, st->hBWE_TD->prev_lsf_diff_fx, Q15, LPC_SHB_ORDER - 2 ); + floatToFixed_arr16( st->hBWE_TD->cur_sub_Aq, st->hBWE_TD->cur_sub_Aq_fx, Q12, M + 1 ); + st->hBWE_TD->prev_tilt_para_fx = float_to_fix16( st->hBWE_TD->prev_tilt_para, Q10 ); + st->hBWE_TD->prev_pow_exc16kWhtnd_fx32 = floatToFixed( st->hBWE_TD->prev_pow_exc16kWhtnd, 0 ); + floatToFixed_arr16( st->hBWE_TD->state_lpc_syn, st->hBWE_TD->state_lpc_syn_fx, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + floatToFixed_arr32( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_csfilt_fx, st->prev_Q_bwe_exc, 2 ); + st->hBWE_TD->gain_prec_swb_fx = float_to_fix16( st->hBWE_TD->gain_prec_swb, Q14 ); + st->hBWE_TD->cldfbHBLT = float_to_fix16( st->hBWE_TD->cldfbHBLT_flt, Q13 ); + st->hBWE_TD->prev_mix_factor_fx = float_to_fix16( st->hBWE_TD->prev_mix_factor, Q15 ); + st->hBWE_TD->prev_gainFr_SHB_fx = floatToFixed( st->hBWE_TD->prev_gainFr_SHB, Q18 ); // Satruation conversion used. Need to look into this + st->hBWE_TD->old_mean_EnvSHBres_fx = float_to_fix16( st->hBWE_TD->old_mean_EnvSHBres, Q15 ); + floatToFixed_arr16( st->hBWE_TD->mem_stp_swb, st->hBWE_TD->mem_stp_swb_fx, st->prev_Q_bwe_syn, LPC_SHB_ORDER ); + st->hBWE_TD->prev_swb_GainShape_fx = float_to_fix16( st->hBWE_TD->prev_swb_GainShape, Q15 ); + floatToFixed_arr( &st->hBWE_TD->tbe_demph, &st->hBWE_TD->tbe_demph_fx, st->prev_Q_bwe_exc - 16 - NOISE_QADJ, 1 ); // Satruation conversion used as -ve Q not handled + floatToFixed_arr( &st->hBWE_TD->tbe_premph, &st->hBWE_TD->tbe_premph_fx, st->prev_Q_bwe_exc - 16, 1 ); // Satruation conversion used as -ve Q not handled + } +#endif + swb_tbe_enc_ivas_fx( st, hStereoICBWE, shb_speech_fx, bwe_exc_extended_fx[n], voice_factors_fx[n], fb_exc_fx, &Q_fb_exc, Q_new[n], Q_shb_spch, st->voicing_fx, pitch_buf_fx[n] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->hBWE_TD != NULL ) + { + fixedToFloat_arr( st->hBWE_TD->old_speech_shb_fx, st->hBWE_TD->old_speech_shb, Q_shb_spch, L_LOOK_16k + L_SUBFR16k ); + fixedToFloat_arr( st->hBWE_TD->shb_inv_filt_mem_fx, st->hBWE_TD->shb_inv_filt_mem, Q_shb_spch, LPC_SHB_ORDER ); // Check + fixedToFloat_arr( st->hBWE_TD->prev_lsp_shb_fx, st->hBWE_TD->prev_lsp_shb, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->lsp_shb_spacing_fx, st->hBWE_TD->lsp_shb_spacing, Q15, 3 ); + fixedToFloat_arr( st->hBWE_TD->lsp_shb_slow_interpl_fx, st->hBWE_TD->lsp_shb_slow_interpl, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->lsp_shb_fast_interpl_fx, st->hBWE_TD->lsp_shb_fast_interpl, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->swb_lsp_prev_interp_fx, st->hBWE_TD->swb_lsp_prev_interp, Q15, LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->prev_lsf_diff_fx, st->hBWE_TD->prev_lsf_diff, Q15, LPC_SHB_ORDER - 2 ); + fixedToFloat_arr( st->hBWE_TD->cur_sub_Aq_fx, st->hBWE_TD->cur_sub_Aq, Q12, M + 1 ); + st->hBWE_TD->prev_tilt_para = fixedToFloat( st->hBWE_TD->prev_tilt_para_fx, Q10 ); + st->hBWE_TD->prev_pow_exc16kWhtnd = fixedToFloat( st->hBWE_TD->prev_pow_exc16kWhtnd_fx32, 0 ); + fixedToFloat_arr( st->hBWE_TD->state_lpc_syn_fx, st->hBWE_TD->state_lpc_syn, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + fixedToFloat_arrL( st->hBWE_TD->mem_csfilt_fx, st->hBWE_TD->mem_csfilt, st->prev_Q_bwe_exc, 2 ); + st->hBWE_TD->gain_prec_swb = fixedToFloat( st->hBWE_TD->gain_prec_swb_fx, Q14 ); + st->hBWE_TD->cldfbHBLT_flt = fixedToFloat( st->hBWE_TD->cldfbHBLT, Q13 ); + st->hBWE_TD->prev_mix_factor = fixedToFloat( st->hBWE_TD->prev_mix_factor_fx, Q15 ); + st->hBWE_TD->prev_gainFr_SHB = fixedToFloat( st->hBWE_TD->prev_gainFr_SHB_fx, Q18 ); + st->hBWE_TD->old_mean_EnvSHBres = fixedToFloat( st->hBWE_TD->old_mean_EnvSHBres_fx, Q15 ); + fixedToFloat_arr( st->hBWE_TD->mem_stp_swb_fx, st->hBWE_TD->mem_stp_swb, st->prev_Q_bwe_syn, LPC_SHB_ORDER ); + st->hBWE_TD->prev_swb_GainShape = fixedToFloat( st->hBWE_TD->prev_swb_GainShape_fx, Q15 ); + st->hBWE_TD->tbe_demph = fixedToFloat( st->hBWE_TD->tbe_demph_fx, st->prev_Q_bwe_exc - 16 - NOISE_QADJ ); + st->hBWE_TD->tbe_premph = fixedToFloat( st->hBWE_TD->tbe_premph_fx, st->prev_Q_bwe_exc - 16 ); + } +#endif +#else swb_tbe_enc( st, hStereoICBWE, shb_speech, bwe_exc_extended[n], voice_factors[n], fb_exc, pitch_buf[n] ); +#endif if ( st->extl == FB_TBE ) { @@ -882,8 +1055,7 @@ ivas_error ivas_core_enc( #ifdef IVAS_FLOAT_FIXED #ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word16 old_inp_12k8_fx[L_INP_12k8], old_inp_16k_fx[L_INP]; - Word16 old_syn_12k8_16k_fx[L_FRAME16k], q_val; - Word16 shb_speech_fx[L_FRAME16k]; + Word16 q_val; Word16 q_old_inp_16k_fx, q_old_syn_12k8_16k_fx, q_old_input_lp; Word16 q_old_inp_12k8_fx, q_shb_speech_fx, q_new_input_hp; @@ -909,7 +1081,7 @@ ivas_error ivas_core_enc( floatToFixed_arr16( old_inp_12k8[n], old_inp_12k8_fx, q_val, L_INP_12k8 ); floatToFixed_arr16( old_inp_16k[n], old_inp_16k_fx, q_val, L_INP ); - floatToFixed_arr16( old_syn_12k8_16k[n], old_syn_12k8_16k_fx, q_val, L_FRAME16k ); + floatToFixed_arr16( old_syn_12k8_16k[n], old_syn_12k8_16k_fx[n], q_val, L_FRAME16k ); floatToFixed_arr16( shb_speech, shb_speech_fx, q_shb_speech_fx, L_FRAME16k ); for ( int ii = 0; ii < L_FRAME48k + STEREO_DFT_OVL_MAX; ii++ ) @@ -922,7 +1094,7 @@ ivas_error ivas_core_enc( } #endif /* SWB(FB) BWE encoder */ - swb_bwe_enc_ivas_fx( st, last_element_mode, old_inp_12k8_fx, old_inp_16k_fx, old_syn_12k8_16k_fx, new_swb_speech_fx1, shb_speech_fx, q_shb_speech_fx, q_val ); + swb_bwe_enc_ivas_fx( st, last_element_mode, old_inp_12k8_fx, old_inp_16k_fx, old_syn_12k8_16k_fx[n], new_swb_speech_fx1, shb_speech_fx, q_shb_speech_fx, q_val ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS if ( st->hBWE_FD != NULL ) { @@ -1057,7 +1229,81 @@ ivas_error ivas_core_enc( if ( !MCT_flag ) /* for MCT do this later, otherwise there can be a problem because TCX quant happens later and might get the wrong last_core on a bit rate switch */ { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + f2me_buf_16( st->buf_speech_enc_pe_flt, st->buf_speech_enc_pe, &st->exp_buf_speech_enc_pe, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_speech_enc_flt, st->buf_speech_enc, &st->exp_buf_speech_enc, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + f2me_buf_16( st->buf_synth_flt, st->buf_synth, &st->exp_buf_synth, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + f2me_buf_16( st->buf_wspeech_enc_flt, st->buf_wspeech_enc, &st->exp_buf_wspeech_enc, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + f2me_buf_16( st->hTcxEnc->buf_speech_ltp_flt, st->hTcxEnc->buf_speech_ltp, &st->hTcxEnc->exp_buf_speech_ltp, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( st->hTcxEnc->tcxltp_norm_corr_past_flt, 15 ); + } +#endif + + updt_enc_common_ivas_fx( st ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf_16( st->buf_speech_enc_pe, st->exp_buf_speech_enc_pe, st->buf_speech_enc_pe_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_speech_enc, st->exp_buf_speech_enc, st->buf_speech_enc_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + me2f_buf_16( st->buf_synth, st->exp_buf_synth, st->buf_synth_flt, OLD_SYNTH_SIZE_ENC + L_FRAME32k ); + IF( st->hTcxEnc != NULL ) + { + me2f_buf_16( st->buf_wspeech_enc, st->exp_buf_wspeech_enc, st->buf_wspeech_enc_flt, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k ); + me2f_buf_16( st->hTcxEnc->buf_speech_ltp, st->hTcxEnc->exp_buf_speech_ltp, st->hTcxEnc->buf_speech_ltp_flt, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k ); + } + + IF( ( st->Opt_DTX_ON && LE_32( st->core_brate, SID_2k40 ) && EQ_16( st->cng_type, FD_CNG ) ) || ( st->tcxonly && ( EQ_16( st->codec_mode, MODE2 ) || GT_16( st->element_mode, EVS_MONO ) ) ) ) + { + set_zero( st->mem_MA, M ); + mvr2r( GEWB_Ave, st->mem_AR, M ); + } + + IF( st->hTcxEnc != NULL ) + { + IF( st->element_mode != IVAS_CPE_MDCT ) + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + } + } + + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_mem_flt = fixedToFloat( st->hTcxEnc->tcxltp_norm_corr_mem, 31 ); + } + + IF( EQ_16( st->element_mode, EVS_MONO ) && EQ_16( st->mdct_sw, MODE2 ) ) + { + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac_flt = PREEMPH_FAC_FLT; + st->gamma_flt = GAMMA1_FLT; + } + ELSE + { + st->preemph_fac_flt = PREEMPH_FAC_16k_FLT; + st->gamma_flt = GAMMA16k_FLT; + } + } + + IF( st->Opt_DTX_ON && st->hTdCngEnc != NULL ) + { + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( ( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GE_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) + { + st->hTdCngEnc->CNG_att = fix16_to_float( st->hTdCngEnc->CNG_att_fx, Q7 ); + } + } + } +#endif +#else updt_enc_common( st ); +#endif } } diff --git a/lib_enc/ivas_core_pre_proc.c b/lib_enc/ivas_core_pre_proc.c index b306b032e..ebfddf500 100644 --- a/lib_enc/ivas_core_pre_proc.c +++ b/lib_enc/ivas_core_pre_proc.c @@ -41,6 +41,7 @@ #include "wmc_auto.h" #include "prot_fx.h" #include "ivas_prot_fx.h" +#include "prot_fx_enc.h" /*-------------------------------------------------------------------* * pre_proc_ivas() @@ -1262,13 +1263,107 @@ ivas_error ivas_compute_core_buffers( mvr2r( st->lsp_old1, st->lspold_enc, M ); } +#ifndef IVAS_FLOAT_FIXED analy_lp( inp_16k, L_FRAME16k, L_look, ener, A, epsP, lsp_new, lsp_mid, st->lspold_enc, st->pitch, st->voicing, INT_FS_16k, 0 ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 *inp_16k_fx; + Word16 A_fx[NB_SUBFR16k * ( M + 1 )]; + Word32 epsP_fx[M + 1]; + Word16 epsP_h[M + 1], epsP_l[M + 1]; + Word16 lsp_new_fx[M], lsp_mid_fx[M]; + Word16 e_esp; + Word16 Q_r[2] = { 0 }; + + move16(); + move16(); + move16(); + move16(); + + f2me_buf_16( old_inp_16k, old_inp_16k_fx, &exp_old_inp_16k, L_INP ); + f2me_buf( epsP, epsP_fx, &e_esp, M + 1 ); + Q_old_inp_16k = sub( 31, exp_old_inp_16k ); + Word32 ener_fx[CPE_CHANNELS]; + + Word16 i; + flag1 = 0; + move16(); + + FOR( i = 0; i < L_INP; i++ ) + { + IF( old_inp_16k_fx[i] != 0 ) + { + flag1 = 1; + move16(); + break; + } + } + IF( flag1 == 0 ) + { + exp_old_inp_16k = 15; + move16(); + } + + new_inp_16k_fx = old_inp_16k_fx + L_INP_MEM; /* pointer to new samples of the input signal in 16kHz core */ + inp_16k_fx = new_inp_16k_fx - L_look; /* pointer to the current frame of input signal in 16kHz core */ + + Word16 exp_ener; + f2me_buf( ener, ener_fx, &exp_ener, CPE_CHANNELS ); + floatToFixed_arr( A, A_fx, Q14, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); + floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); + floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); +#endif + analy_lp_fx( inp_16k_fx, L_FRAME16k, L_look, ener_fx, A_fx, epsP_h, epsP_l, lsp_new_fx, lsp_mid_fx, st->lspold_enc_fx, st->pitch, st->voicing_fx, INT_FS_16k, 0, Q_old_inp_16k, Q_r ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf_16( old_inp_16k_fx, exp_old_inp_16k, old_inp_16k, L_INP ); + me2f_buf( ener_fx, exp_ener, ener, CPE_CHANNELS ); + fixedToFloat_arr( A_fx, A, Q14, NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); + fixedToFloat_arr( st->lspold_enc_fx, st->lspold_enc, Q15, M ); + fixedToFloat_arr( st->voicing_fx, st->voicing, Q15, 3 ); + for ( i = 0; i < M + 1; i++ ) + { + epsP_fx[i] = L_Comp( epsP_h[i], epsP_l[i] ); + move32(); + } + fixedToFloat_arrL( epsP_fx, epsP, Q_r[0] - Q_r[1], M + 1 ); +#endif +#endif /*--------------------------------------------------------------* * Compute Weighted Input *---------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED find_wsp( L_FRAME16k, L_SUBFR, NB_SUBFR16k, A, Aw, st->speech_enc_pe_flt, PREEMPH_FAC_16k_FLT, st->wspeech_enc_flt, &st->mem_wsp_enc_flt, st->gamma_flt, L_LOOK_16k ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )]; + + floatToFixed_arr( Aw, Aw_fx, Q12, NB_SUBFR16k * ( M + 1 ) ); + + floatToFixed_arr( st->speech_enc_pe_flt - M, st->speech_enc_pe - M, Q9, L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k - st->encoderPastSamples_enc + M ); + + floatToFixed_arr( st->wspeech_enc_flt, st->wspeech_enc, Q9, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k - st->L_frame - L_SUBFR ); + + st->mem_wsp_enc = (Word16) floatToFixed( st->mem_wsp_enc_flt, Q9 ); + + st->gamma = (Word16) floatToFixed( st->gamma_flt, Q15 ); + +#endif + ivas_find_wsp( L_FRAME16k, L_SUBFR, NB_SUBFR16k, A_fx, Aw_fx, st->speech_enc_pe, PREEMPH_FAC_16k, st->wspeech_enc, &st->mem_wsp_enc, st->gamma, L_LOOK_16k ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( Aw_fx, Aw, Q12, NB_SUBFR16k * ( M + 1 ) ); + + fixedToFloat_arr( st->wspeech_enc, st->wspeech_enc_flt, Q9, L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k - st->L_frame - L_SUBFR ); + + st->mem_wsp_enc_flt = fixedToFloat( st->mem_wsp_enc, Q9 ); +#endif +#endif } /*-----------------------------------------------------------------* @@ -1286,7 +1381,24 @@ ivas_error ivas_compute_core_buffers( } else if ( input_Fs > 8000 ) { +#ifndef IVAS_FLOAT_FIXED lerp_flt( st->old_inp_12k8 + L_INP_MEM - L_INP_MEM * 4 / 5, st->old_inp_16k, L_INP_MEM, L_INP_MEM * 4 / 5 ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_old_inp_12k8 = Q_factor_arr( st->old_inp_12k8, L_INP ); + floatToFixed_arr( st->old_inp_12k8, st->old_inp_12k8_fx, q_old_inp_12k8, L_INP ); + + Word16 q_old_inp_16k = Q_factor_arr( st->old_inp_16k, L_INP ); + floatToFixed_arr( st->old_inp_16k, st->old_inp_16k_fx, q_old_inp_16k, L_INP ); + + lerp( st->old_inp_12k8_fx + L_INP_MEM - L_INP_MEM * 4 / 5, st->old_inp_16k_fx, L_INP_MEM, L_INP_MEM * 4 / 5 ); +#endif + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( st->old_inp_12k8_fx, st->old_inp_12k8, q_old_inp_12k8, L_INP ); + fixedToFloat_arr( st->old_inp_16k_fx, st->old_inp_16k, q_old_inp_12k8, L_INP ); +#endif +#endif } if ( inp16k_out != NULL ) diff --git a/lib_enc/ivas_core_pre_proc_front.c b/lib_enc/ivas_core_pre_proc_front.c index a8761182a..f6c125d12 100644 --- a/lib_enc/ivas_core_pre_proc_front.c +++ b/lib_enc/ivas_core_pre_proc_front.c @@ -40,6 +40,7 @@ #include "prot_fx.h" #include "prot_fx_enc.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "wmc_auto.h" #include @@ -54,20 +55,12 @@ #define SCE_SMC_THR 16000 -/*-------------------------------------------------------------------* - * Local function prototypes - *--------------------------------------------------------------------*/ -#if 0 -static void change_q( Word16 *buff, Word16 size, Word16 Q ) -{ - Flag Overflow; - for ( Word16 i = 0; i < size; i++ ) - { - buff[i] = shr_o( buff[i], Q, &Overflow ); - } -} -#endif +#ifdef IVAS_FLOAT_FIXED +static void calculate_energy_buffer_ivas_fx( CPE_ENC_HANDLE hCPE, Word32 enerBuffer_dft[], const Word16 no_channels, const Word32 input_Fs, Word16 *enerBuffer_dft_e ); +#else static void calculate_energy_buffer( CPE_ENC_HANDLE hCPE, float enerBuffer_dft[], const int16_t no_channels, const int32_t input_Fs ); +#endif + #ifdef IVAS_FIXED_ENC static void calculate_energy_buffer_fx( CPE_ENC_HANDLE hCPE, Word64 enerBuffer_dft_fx[], Word16 *enerBuffer_dft_q_fx, const Word16 no_channels, const Word32 input_Fs ); #endif @@ -855,10 +848,11 @@ ivas_error pre_proc_front_ivas( ivas_error pre_proc_front_ivas_fx( SCE_ENC_HANDLE hSCE, /* i/o: SCE encoder structure */ CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - const int32_t element_brate, /* i : SCE/CPE element bitrate */ - const int16_t nb_bits_metadata, /* i : number of metadata bits */ - const int16_t input_frame, /* i : frame length */ - const int16_t n, /* i : channel number */ + const Word32 element_brate, /* i : SCE/CPE element bitrate */ + const Word16 nb_bits_metadata, /* i : number of metadata bits */ + const Word16 input_frame, /* i : frame length */ + const Word16 n, /* i : channel number */ + Word16 old_inp_12k8_fx[], /* o : (Q-1) buffer of old input signal */ float old_inp_12k8[], /* o : buffer of old input signal */ float old_inp_16k[], /* o : buffer of old input signal @16kHz */ float *ener, /* o : residual energy from Levinson-Durbin */ @@ -868,266 +862,345 @@ ivas_error pre_proc_front_ivas_fx( float epsP[M + 1], /* o : LP prediction errors */ float lsp_new[M], /* o : LSPs at the end of the frame */ float lsp_mid[M], /* o : LSPs in the middle of the frame */ - int16_t *vad_hover_flag, /* o : VAD hangover flag */ - int16_t *attack_flag, /* o : flag signaling attack */ + Word16 *vad_hover_flag, /* o : VAD hangover flag */ + Word16 *attack_flag, /* o : flag signaling attack */ float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: real buffer */ float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i/o: imag buffer */ float old_wsp[], /* o : weighted input signal buffer */ float pitch_fr[NB_SUBFR], /* o : fractional pitch values */ float voicing_fr[NB_SUBFR], /* o : fractional pitch gains */ - int16_t *loc_harm, /* o : harmonicity flag */ + Word16 *loc_harm, /* o : harmonicity flag */ float *cor_map_sum, /* o : speech/music clasif. parameter */ - int16_t *vad_flag_dtx, /* o : HE-SAD flag with additional DTX HO */ + Word16 *vad_flag_dtx, /* o : HE-SAD flag with additional DTX HO */ float enerBuffer[CLDFB_NO_CHANNELS_MAX], /* o : energy buffer */ float fft_buff[2 * L_FFT], /* o : FFT buffer */ + Word16 fft_buff_fx[2 * L_FFT], /* o : FFT buffer */ const float tdm_A_PCh[M + 1], /* i : unq. LP coeff. of primary channel */ const float tdm_lsp_new_PCh[M], /* i : unq. LSPs of primary channel */ const float currFlatness, /* i : flatness parameter */ - const int16_t tdm_ratio_idx, /* i : Current Ratio_L index */ + const Word16 tdm_ratio_idx, /* i : Current Ratio_L index */ float fr_bands_LR[][2 * NB_BANDS], /* i : energy in frequency bands */ const float Etot_LR[], /* i : total energy Left & Right channel Q8*/ float lf_E_LR[][2 * VOIC_BINS], /* i : per bin spectrum energy in lf, LR channels */ - const int16_t localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover, LR channels */ + const Word16 localVAD_HE_SAD_LR[], /* i : HE-SAD flag without hangover, LR channels */ float band_energies_LR[2 * NB_BANDS], /* o : energy in critical bands without minimum noise floor E_MIN */ - const int16_t flag_16k_smc, /* i : flag to indicate if the OL SMC is run at 16 kHz */ - const int16_t front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ - const int16_t force_front_vad, /* i : flag to force VAD decision */ - const int16_t front_vad_dtx_flag, /* i : front-VAD DTX flag to overwrite VAD decision*/ + const Word16 flag_16k_smc, /* i : flag to indicate if the OL SMC is run at 16 kHz */ + const Word16 front_vad_flag, /* i : front-VAD flag to overwrite VAD decision */ + const Word16 force_front_vad, /* i : flag to force VAD decision */ + const Word16 front_vad_dtx_flag, /* i : front-VAD DTX flag to overwrite VAD decision*/ const IVAS_FORMAT ivas_format, /* i : IVAS format */ - const int16_t MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ - const int32_t ivas_total_brate /* i : IVAS total bitrate - for setting the DTX */ + const Word16 MCT_flag, /* i : hMCT handle allocated (1) or not (0) */ + const Word32 ivas_total_brate /* i : IVAS total bitrate - for setting the DTX */ ) { - float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ - float *wsp; /* weighted input signal buffer */ - float Etot; /* total energy */ - float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ - float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ - float tmpN[NB_BANDS]; /* Temporary noise update */ - float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ - float tmpN_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ - float tmpE_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ - float cor_map_sum_LR[CPE_CHANNELS]; /* speech/music clasif. parameter */ - float non_staX_LR; /* non-stationarity for sp/mus classifier */ - float ncharX_LR; /* noise character for sp/mus classifier */ - float sp_div_LR; /* spectral diversity feature */ - float S_map_LR[L_FFT / 2]; /* short-term correlation map */ - float corr_shiftL; /* correlation shift */ - float corr_shiftR; /* correlation shift */ - int16_t loc_harmLR[CPE_CHANNELS]; /* harmonicity flag */ - int16_t lr_vad_enabled; /* LR VAD indicator */ - float ee[2]; /* Spectral tilt */ - float corr_shift; /* correlation shift */ - float sp_div, PS[128]; /* speech/music clasif. parameters */ - int16_t L_look; /* length of look-ahead */ -#if 1 - float snr_sum_he; /* HE SAD parameters */ -#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Encoder_State *st; + Word16 old_inp_12k8_e; + if ( hSCE != NULL ) + { + st = hSCE->hCoreCoder[n]; + floatToFixed_arr( hSCE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hSCE->hCoreCoder[n]->input_fx - (Word16) ( st->input_Fs / 50 ), -1, (Word16) ( st->input_Fs / 25 ) ); + floatToFixed_arrL( hSCE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hSCE->hCoreCoder[n]->input32_fx - (Word16) ( st->input_Fs / 50 ), 11, (Word16) ( st->input_Fs / 25 ) ); + } + else + { + st = hCPE->hCoreCoder[n]; + floatToFixed_arr( hCPE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hCPE->hCoreCoder[n]->input_fx - (Word16) ( st->input_Fs / 50 ), -1, (Word16) ( st->input_Fs / 25 ) ); + floatToFixed_arrL( hCPE->hCoreCoder[n]->input - (Word16) ( st->input_Fs / 50 ), hCPE->hCoreCoder[n]->input32_fx - (Word16) ( st->input_Fs / 50 ), 11, (Word16) ( st->input_Fs / 25 ) ); + } + Word16 mem_decim_e; + f2me_buf_16( st->mem_decim, st->mem_decim_fx, &mem_decim_e, 2 * L_FILT_MAX ); + IF( st->cldfbAnaEnc != NULL ) + { + floatToFixed_arrL( st->cldfbAnaEnc->cldfb_state, st->cldfbAnaEnc->cldfb_state_fx, Q11, sub( sub( st->cldfbAnaEnc->p_filter_length, st->cldfbAnaEnc->no_channels ), st->cldfbAnaEnc->zeros ) ); + } + f2me_buf_16( st->old_inp_12k8, st->old_inp_12k8_fx, &st->exp_old_inp_12k8, 240 ); + f2me_buf_16( old_inp_12k8, old_inp_12k8_fx, &old_inp_12k8_e, 496 ); + if ( old_inp_12k8_e > st->exp_old_inp_12k8 ) + { + Scale_sig( st->old_inp_12k8_fx, 240, st->exp_old_inp_12k8 - old_inp_12k8_e ); + st->exp_old_inp_12k8 = old_inp_12k8_e; + } + else + { + Scale_sig( old_inp_12k8_fx, 496, old_inp_12k8_e - st->exp_old_inp_12k8 ); + old_inp_12k8_e = st->exp_old_inp_12k8; + } + Word16 mem_preemph_DFT_e; + Word16 inp_12k8_mem_stereo_sw_e; + Word16 mem_preemph_e; + f2me_buf_16( st->inp_12k8_mem_stereo_sw, st->inp_12k8_mem_stereo_sw_fx, &inp_12k8_mem_stereo_sw_e, 4 ); + f2me_16( st->mem_preemph_DFT, &st->mem_preemph_DFT_fx, &mem_preemph_DFT_e ); + f2me_16( st->mem_preemph, &st->mem_preemph_fx, &mem_preemph_e ); +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + float *inp_12k8, *new_inp_12k8; /* pointers to current frame and new data */ + float *wsp; /* weighted input signal buffer */ + float Etot; /* total energy */ + float fr_bands[2 * NB_BANDS]; /* energy in frequency bands */ + float lf_E[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + float tmpN[NB_BANDS]; /* Temporary noise update */ + float tmpE[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + Word32 tmpN_fx[NB_BANDS]; /* Temporary noise update */ + Word32 tmpE_fx[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float tmpN_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ + float tmpE_LR[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ + float cor_map_sum_LR[CPE_CHANNELS]; /* speech/music clasif. parameter */ + float non_staX_LR; /* non-stationarity for sp/mus classifier */ + float ncharX_LR; /* noise character for sp/mus classifier */ + float sp_div_LR; /* spectral diversity feature */ + float S_map_LR[L_FFT / 2]; /* short-term correlation map */ + float corr_shiftL; /* correlation shift */ + float corr_shiftR; /* correlation shift */ + Word16 loc_harmLR[CPE_CHANNELS]; /* harmonicity flag */ + Word16 lr_vad_enabled; /* LR VAD indicator */ + float ee[2]; /* Spectral tilt */ + float corr_shift; /* correlation shift */ + float sp_div, PS[128]; /* speech/music clasif. parameters */ + Word16 L_look; /* length of look-ahead */ +#if 0 float mem_decim_dummy[2 * L_FILT_MAX]; /* dummy decimation filter memory */ float temp1F_icatdmResampBuf[L_FILT_MAX]; /* temp buffers for ICA TDM resamplers */ - float hp_E[2]; /* Energy in HF */ - int16_t flag_spitch; - int16_t high_lpn_flag; +#endif + float hp_E[2]; /* Energy in HF */ + Word16 flag_spitch; + Word16 high_lpn_flag; float lsf_new[M]; float band_energies[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ - int16_t localVAD_HE_SAD; +#if 0 + Word32 band_energies_fx[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ +#endif + Word16 localVAD_HE_SAD; float non_staX; float stab_fac; - int16_t alw_pitch_lag_12k8[2]; + Word16 alw_pitch_lag_12k8[2]; float alw_voicing[2]; - int16_t last_core_orig; + Word16 last_core_orig; float dummy; float S_map[L_FFT / 2]; - int16_t i, lMemRecalc, lMemRecalc_12k8; - int16_t smc_dec; + Word16 S_map_fx[L_FFT / 2]; + Word16 i, lMemRecalc, lMemRecalc_12k8; + Word16 smc_dec; float ncharX, dE1X; - Encoder_State *st; - float *signal_in; - int16_t element_mode; - int32_t input_Fs, last_element_brate; - int16_t *tdm_SM_last_clas, tmpS; + // Encoder_State *st; + // float *signal_in; + Word16 element_mode; + Word32 input_Fs, last_element_brate; + Word16 *tdm_SM_last_clas, tmpS; float *res_cod_SNR_M, tmpF[STEREO_DFT_BAND_MAX]; STEREO_CLASSIF_HANDLE hStereoClassif; - int16_t old_pitch1; /* previous frame OL pitch[1] @12.8 kHz */ - int16_t LR_localVAD; + Word16 old_pitch1; /* previous frame OL pitch[1] @12.8 kHz */ + Word16 LR_localVAD; ivas_error error; - push_wmops( "pre_proc_front" ); -#ifdef IVAS_FLOAT_FIXED Word16 *signal_in_fx; - Word16 *new_inp_12k8_fx; /* pointers to current frame and new data */ +#if 0 + Word16 *lgBin_E_fx; + Word32 PS_fx[128]; + Word32 lf_E_fx[2 * VOIC_BINS]; /* per bin spectrum energy in lf */ +#endif + Word32 *signal32_in_fx; +#if 0 + Word16 *inp_12k8_fx; +#endif + Word16 *inp_12k8_fx, *new_inp_12k8_fx; /* pointers to current frame and new data */ CLDFB_SCALE_FACTOR cldfbScale; Word32 *enerBuffer_fx; Word16 enerBuffer_exp; /*[CLDFB_NO_CHANNELS_MAX];*/ Word16 *temp1F_icatdmResampBuf_fx; - Word16 *old_inp_12k8_fx; Word16 *old_inp_16k_fx; Word16 *mem_decim_dummy_fx; /* dummy decimation filter memory */ Word32 Etot_fx; /* total energy */ -#if 0 +#if 1 + Word16 Etot_16fx; /* total energy, Q8 */ +#endif + Word32 tmpF_fx[STEREO_DFT_BAND_MAX]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + Word32 *res_cod_SNR_M_fx; +#endif + Word16 corr_shiftL_fx; + Word16 corr_shiftR_fx; + Word16 snr_sum_he_fx; /* HE SAD parameters */ + Word16 old_wsp_fx[L_WSP]; Word32 fr_bands_fx[2 * NB_BANDS]; /* energy in frequency bands */ - Word16 Q_new; - Word16 new_inp_out_size, mem_decim_size; - Word16 snr_sum_he_fx; /* HE SAD parameters */ + Word16 new_inp_out_size; Word16 Q_new_inp; + Word16 mem_decim_size; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + Word16 *wsp_fx; + Word16 Q_new; Word16 corr_shift_fx; +#endif Word16 dummy_fx; Word16 Etot_LR_fx[2]; +#if 0 Word16 Q_exp; Word32 Le_min_scaled; - Word32 fr_bands_LR_fx[2][2 * NB_BANDS]; Word16 relE_fx; - Word32 tmpN_fx[NB_BANDS]; /* Temporary noise update */ - Word32 tmpE_fx[NB_BANDS]; /* Temporary averaged energy of 2 sf. */ +#endif + Word32 fr_bands_LR_fx[2][2 * NB_BANDS]; Word32 tmpN_LR_fx[CPE_CHANNELS][NB_BANDS]; /* Temporary noise update */ Word32 tmpE_LR_fx[CPE_CHANNELS][NB_BANDS]; /* Temporary averaged energy of 2 sf. */ -#endif - - signal_in_fx = (Word16 *) malloc( 2 * 1965 * sizeof( Word16 * ) ); + enerBuffer_exp = 0; + move16(); enerBuffer_fx = (Word32 *) malloc( 60 * sizeof( Word32 * ) ); - old_inp_12k8_fx = (Word16 *) malloc( 496 * sizeof( Word16 * ) ); old_inp_16k_fx = (Word16 *) malloc( 880 * sizeof( Word16 * ) ); mem_decim_dummy_fx = (Word16 *) malloc( 90 * sizeof( Word16 * ) ); temp1F_icatdmResampBuf_fx = (Word16 *) malloc( 45 * sizeof( Word16 * ) ); - + set16_fx( fft_buff_fx, 0, 512 ); Word16 realBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word16 imagBuffer16[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 realBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 imagBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word16 sf_energySum[CLDFB_NO_CHANNELS_MAX]; + Word16 max_e; -#ifndef MSAN_FIX - floatToFixed_arr( old_inp_12k8, old_inp_12k8_fx, 0, 496 ); -#endif // MSAN_FIX -#endif /*------------------------------------------------------------------* * Initialization *------------------------------------------------------------------*/ error = IVAS_ERR_OK; + move32(); + + cldfbScale.lb_scale = 31; + cldfbScale.hb_scale = 31; + move16(); + move16(); tmpS = 0; + move16(); tdm_SM_last_clas = &tmpS; + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED set_f( tmpF, 0, STEREO_DFT_BAND_MAX ); res_cod_SNR_M = tmpF; +#endif // IVAS_FLOAT - LR_localVAD = 0; - - if ( hSCE != NULL ) - { - st = hSCE->hCoreCoder[n]; - signal_in = hSCE->hCoreCoder[n]->input; - element_mode = IVAS_SCE; - last_element_brate = hSCE->last_element_brate; - hStereoClassif = NULL; - lr_vad_enabled = 0; - } - else /* CPE */ - { - st = hCPE->hCoreCoder[n]; - signal_in = hCPE->hCoreCoder[n]->input; - element_mode = hCPE->element_mode; - last_element_brate = hCPE->last_element_brate; - hStereoClassif = hCPE->hStereoClassif; - lr_vad_enabled = 0; - if ( hCPE->hFrontVad[0] != NULL && hCPE->element_mode != IVAS_CPE_MDCT ) - { - lr_vad_enabled = 1; - } - - if ( lr_vad_enabled && n == 0 ) - { - /* Combine localVAD and vad_flag from LR processing */ - LR_localVAD = hCPE->hCoreCoder[0]->localVAD || hCPE->hCoreCoder[1]->localVAD; - } - - if ( hCPE->hStereoTD != NULL ) - { - tdm_SM_last_clas = &hCPE->hStereoTD->tdm_SM_last_clas[n]; - mvs2s( hCPE->hStereoTD->tdm_SM_last_clas, hCPE->hStereoTD->tdm_SM_last2_clas, CPE_CHANNELS ); - } - - if ( hCPE->hStereoDft != NULL ) - { - res_cod_SNR_M = hCPE->hStereoDft->res_cod_SNR_M; - } - } -#if 0 set32_fx( tmpF_fx, 0, STEREO_DFT_BAND_MAX ); +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING res_cod_SNR_M_fx = tmpF_fx; +#endif LR_localVAD = 0; + move16(); - IF ( hSCE != NULL ) + IF( hSCE != NULL ) { st = hSCE->hCoreCoder[n]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + signal_in = hSCE->hCoreCoder[n]->input; +#endif signal_in_fx = hSCE->hCoreCoder[n]->input_fx; + signal32_in_fx = hSCE->hCoreCoder[n]->input32_fx; element_mode = IVAS_SCE; last_element_brate = hSCE->last_element_brate; hStereoClassif = NULL; lr_vad_enabled = 0; + move16(); + move32(); + move16(); } ELSE /* CPE */ { st = hCPE->hCoreCoder[n]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + signal_in = hCPE->hCoreCoder[n]->input; +#endif signal_in_fx = hCPE->hCoreCoder[n]->input_fx; + signal32_in_fx = hCPE->hCoreCoder[n]->input32_fx; element_mode = hCPE->element_mode; last_element_brate = hCPE->last_element_brate; hStereoClassif = hCPE->hStereoClassif; lr_vad_enabled = 0; - IF ( hCPE->hFrontVad[0] != NULL && NE_16(hCPE->element_mode, IVAS_CPE_MDCT )) + move16(); + move32(); + move16(); + test(); + IF( hCPE->hFrontVad[0] != NULL && NE_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) { lr_vad_enabled = 1; + move16(); } - IF ( lr_vad_enabled && EQ_16(n, 0 )) + IF( lr_vad_enabled && n == 0 ) { /* Combine localVAD and vad_flag from LR processing */ + test(); LR_localVAD = hCPE->hCoreCoder[0]->localVAD || hCPE->hCoreCoder[1]->localVAD; + move16(); } - IF ( hCPE->hStereoTD != NULL ) + IF( hCPE->hStereoTD != NULL ) { tdm_SM_last_clas = &hCPE->hStereoTD->tdm_SM_last_clas[n]; Copy( hCPE->hStereoTD->tdm_SM_last_clas, hCPE->hStereoTD->tdm_SM_last2_clas, CPE_CHANNELS ); } - IF ( hCPE->hStereoDft != NULL ) + IF( hCPE->hStereoDft != NULL ) { +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + res_cod_SNR_M = hCPE->hStereoDft->res_cod_SNR_M; +#endif +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING res_cod_SNR_M_fx = hCPE->hStereoDft->res_cod_SNR_M_fx; +#endif } } + +#if 0 + lgBin_E_fx = NULL; + if ( st != NULL ) + { + lgBin_E_fx = &st->lgBin_E_fx[0]; + } #endif lMemRecalc_12k8 = 0; lMemRecalc = 0; + move16(); + move16(); + test(); IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) { - lMemRecalc = NS2SA( st->input_Fs, L_MEM_RECALC_NS ); - lMemRecalc_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_NS ); + lMemRecalc = NS2SA_FX2( st->input_Fs, L_MEM_RECALC_NS ); + lMemRecalc_12k8 = NS2SA_FX2( INT_FS_12k8, L_MEM_RECALC_NS ); } input_Fs = st->input_Fs; + move32(); localVAD_HE_SAD = 0; + move16(); + #if 1 - snr_sum_he = 0; -#endif corr_shiftL = 0; corr_shiftR = 0; -#if 0 +#endif // DEBUG + +#if 1 snr_sum_he_fx = 0; + move16(); #endif + + corr_shiftL_fx = 0; + corr_shiftR_fx = 0; + move16(); + move16(); + IF( hSCE != NULL ) { *vad_hover_flag = 0; + move16(); } st->sp_aud_decision1 = 0; st->sp_aud_decision2 = 0; st->coder_type = GENERIC; + move16(); + move16(); + move16(); IF( st->hGSCEnc != NULL ) { st->hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); } *attack_flag = 0; @@ -1137,19 +1210,24 @@ ivas_error pre_proc_front_ivas_fx( st->hSC_VBR->ppp_mode = 0; st->hSC_VBR->nelp_mode = 0; st->hSC_VBR->avoid_HQ_VBR_NB = 0; + move16(); + move16(); + move16(); + move16(); } L_look = L_LOOK_12k8; /* lookahead at 12.8kHz */ + move16(); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED new_inp_12k8 = old_inp_12k8 + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ inp_12k8 = new_inp_12k8 - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ -#ifdef IVAS_FLOAT_FIXED +#endif new_inp_12k8_fx = old_inp_12k8_fx + L_INP_MEM; /* pointer to new samples of the input signal in 12.8kHz core */ -#if 0 inp_12k8_fx = new_inp_12k8_fx - L_look; /* pointer to the current frame of input signal in 12.8kHz core */ -#endif -#endif - if ( element_mode != IVAS_CPE_DFT ) + +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + if ( NE_16( element_mode, IVAS_CPE_DFT ) ) { new_inp_12k8 -= L_FILT; } @@ -1166,186 +1244,127 @@ ivas_error pre_proc_front_ivas_fx( { mvr2r( st->old_inp_12k8, old_inp_12k8, L_INP_MEM - L_FILT ); } - mvr2r( st->old_wsp, old_wsp, L_WSP_MEM ); wsp = old_wsp + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ +#endif IF( NE_16( element_mode, IVAS_CPE_DFT ) ) { new_inp_12k8_fx -= L_FILT; } -#if 0 - IF(EQ_16(element_mode, IVAS_CPE_DFT)) + + IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { - Copy(st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - STEREO_DFT_OVL_12k8); + Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - STEREO_DFT_OVL_12k8 ); } - ELSE IF(EQ_16(element_mode, IVAS_CPE_TD)) + ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) ) { - Copy(st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - lMemRecalc_12k8 - L_FILT); + Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - lMemRecalc_12k8 - L_FILT ); } ELSE { - Copy(st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - L_FILT); + Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - L_FILT ); } - Copy(st->old_wsp, old_wsp, L_WSP_MEM); - wsp = old_wsp + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ -#endif + Copy( st->old_wsp_fx, old_wsp_fx, L_WSP_MEM ); + +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + wsp_fx = old_wsp_fx + L_WSP_MEM; /* pointer to the current frame of weighted signal in 12.8kHz core */ +#endif // REMOVE_IVAS_UNUSED_PARAMETERS_WARNING + st->rf_mode = st->Opt_RF_ON; + move16(); last_core_orig = st->last_core; + move16(); /*--------------------------------------------------------------* * energy analysis *---------------------------------------------------------------*/ - floatToFixed_arr( signal_in - (Word16) ( input_Fs / 50 ), signal_in_fx, 0, (Word16) ( input_Fs / 25 ) ); - signal_in_fx = signal_in_fx + input_Fs / 50; + test(); + test(); + test(); + test(); + test(); IF( EQ_16( element_mode, IVAS_SCE ) || ( EQ_16( element_mode, IVAS_CPE_MDCT ) && st->Opt_DTX_ON ) ) { - analysisCldfbEncoder_ivas_fx( st, signal_in_fx, realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); - for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) - { - for ( int j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) - { - realBuffer[i][j] = (float) realBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - imagBuffer[i][j] = (float) imagBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - } - } - cldfbScale.hb_scale = cldfbScale.lb_scale; - fixedToFloat_arrL( enerBuffer_fx, enerBuffer, 31 - enerBuffer_exp, 60 ); + analysisCldfbEncoder_ivas_fx( st, signal32_in_fx, 11, input_frame, realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); } - ELSE IF( ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->idchan, 0 ) ) || ( EQ_16( st->idchan, 1 ) && st->tdm_LRTD_flag ) ) + ELSE IF( ( EQ_16( element_mode, IVAS_CPE_TD ) && st->idchan == 0 ) || ( EQ_16( st->idchan, 1 ) && st->tdm_LRTD_flag ) ) { /* cldfb analysis only for pri. channel */ - analysisCldfbEncoder_ivas_fx( st, signal_in_fx - NS2SA( input_Fs, L_MEM_RECALC_TBE_NS ), realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); - for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) - { - for ( int j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) - { - realBuffer[i][j] = (float) realBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - imagBuffer[i][j] = (float) imagBuffer_fx[i][j] / ( 1 << ( 16 - cldfbScale.lb_scale ) ); - } - } - cldfbScale.hb_scale = cldfbScale.lb_scale; - fixedToFloat_arrL( enerBuffer_fx, enerBuffer, 31 - enerBuffer_exp, 60 ); + analysisCldfbEncoder_ivas_fx( st, signal32_in_fx - NS2SA_FX2( input_Fs, L_MEM_RECALC_TBE_NS ), 11, input_frame, realBuffer_fx, imagBuffer_fx, realBuffer16, imagBuffer16, enerBuffer_fx, &enerBuffer_exp, &cldfbScale ); } ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { - calculate_energy_buffer( hCPE, enerBuffer, st->cldfbAnaEnc->no_channels, input_Fs ); - f2me_buf( enerBuffer, enerBuffer_fx, &enerBuffer_exp, 60 ); + calculate_energy_buffer_ivas_fx( hCPE, enerBuffer_fx, st->cldfbAnaEnc->no_channels, input_Fs, &enerBuffer_exp ); } ELSE { set32_fx( enerBuffer_fx, 0, CLDFB_NO_CHANNELS_MAX ); enerBuffer_exp = 31; + move16(); } /*----------------------------------------------------------------* * Change the sampling frequency to 12.8 kHz * (if not available from downsampled DMX) *----------------------------------------------------------------*/ -#if 0 // Disabled due to high mld -- Scaling needs to be handled. - IF( element_mode == IVAS_SCE ) + Word16 scale_factor = sub( getScaleFactor16( st->input_fx - (Word16) ( st->input_Fs / 50 ), (Word16) ( st->input_Fs / 25 ) ), 1 ); + Word16 q_input = s_min( add( -1, scale_factor ), sub( 16, old_inp_12k8_e ) ); + Copy_Scale_sig32_16( st->input32_fx - (Word16) ( st->input_Fs / 50 ), st->input_fx - (Word16) ( st->input_Fs / 50 ), (Word16) ( st->input_Fs / 25 ), add( 16 - 11, q_input ) ); /*scaling down from q11 to q_input*/ + Scale_sig( st->mem_decim_fx, 90, sub( q_input, 15 - mem_decim_e ) ); /*scaling from q(15-mem_decim_e) to q_input*/ + Scale_sig( old_inp_12k8_fx, 496, sub( q_input, sub( 15, old_inp_12k8_e ) ) ); /*scaling from q(15-old_inp_12k8_e) to q_input*/ + test(); + IF( EQ_16( element_mode, IVAS_SCE ) ) { - new_inp_out_size = modify_Fs_fx( signal_in_fx, input_frame, input_Fs, new_inp_12k8_fx, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); - - fixedToFloat_arr( new_inp_12k8_fx, new_inp_12k8, Q_new_inp, new_inp_out_size ); // To be removed - fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, 0, mem_decim_size ); // To be removed - - change_q( new_inp_12k8_fx, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx, input_frame, input_Fs, new_inp_12k8_fx, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ Copy( st->mem_decim_fx, mem_decim_dummy_fx, 2 * L_FILT_MAX ); - set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); - - new_inp_out_size = modify_Fs_fx( temp1F_icatdmResampBuf_fx, NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); - - fixedToFloat_arr( new_inp_12k8_fx + L_FRAME, new_inp_12k8 + L_FRAME, Q_new_inp, new_inp_out_size ); // To be removed - change_q( new_inp_12k8_fx + L_FRAME, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( temp1F_icatdmResampBuf_fx, NS2SA_FX2( st->input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx + L_FRAME, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) { /* reconstruct past segment of the Secondary channel input signal when switching from DFT stereo */ - IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && EQ_16( st->idchan, 1 ) ) + test(); + IF( hCPE->last_element_mode == IVAS_CPE_DFT && st->idchan == 1 ) { - Word16 length_inp = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS ); - Word16 length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - - new_inp_out_size = modify_Fs_fx( signal_in_fx - lMemRecalc - length_inp, length_inp, input_Fs, new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, INT_FS_12k8, st->mem_decim_fx, 0, &Q_new_inp, &mem_decim_size ); + Word16 length_inp = NS2SA_FX2( input_Fs, L_MEM_RECALC_SCH_NS ); + Word16 length_12k8 = NS2SA_FX2( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, 0, mem_decim_size ); // To be removed - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, Q_new_inp, new_inp_out_size ); // To be removed - - change_q( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx - add( lMemRecalc, length_inp ), length_inp, input_Fs, new_inp_12k8_fx - add( lMemRecalc_12k8, length_12k8 ), INT_FS_12k8, st->mem_decim_fx, 0, &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx - add( lMemRecalc_12k8, length_12k8 ), new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } - new_inp_out_size = modify_Fs_fx( signal_in_fx - lMemRecalc, input_frame, input_Fs, new_inp_12k8_fx - lMemRecalc_12k8, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx - lMemRecalc, input_frame, input_Fs, new_inp_12k8_fx - lMemRecalc_12k8, INT_FS_12k8, st->mem_decim_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); Copy( st->mem_decim_fx, mem_decim_dummy_fx, 2 * L_FILT_MAX ); - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_12k8 - lMemRecalc_12k8, Q_new_inp, new_inp_out_size ); // To be removed - fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, 0, mem_decim_size ); // To be removed - - change_q( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_out_size, Q_new_inp ); + Scale_sig( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ - IF( GT_16( lMemRecalc, 0 ) ) + IF( lMemRecalc > 0 ) { - new_inp_out_size = modify_Fs_fx( signal_in_fx + input_frame - lMemRecalc, lMemRecalc, input_Fs, new_inp_12k8_fx + L_FRAME - lMemRecalc_12k8, INT_FS_12k8, mem_decim_dummy_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); - fixedToFloat_arr( new_inp_12k8_fx + L_FRAME - lMemRecalc_12k8, new_inp_12k8 + L_FRAME - lMemRecalc_12k8, Q_new_inp, new_inp_out_size ); // To be removed - - change_q( new_inp_12k8_fx + L_FRAME - lMemRecalc_12k8, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( signal_in_fx + sub( input_frame, lMemRecalc ), lMemRecalc, input_Fs, new_inp_12k8_fx + sub( L_FRAME, lMemRecalc_12k8 ), INT_FS_12k8, mem_decim_dummy_fx, ( st->max_bwidth == NB ), &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx + sub( L_FRAME, lMemRecalc_12k8 ), new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } set16_fx( temp1F_icatdmResampBuf_fx, 0, L_FILT_MAX ); - new_inp_out_size = modify_Fs_fx( temp1F_icatdmResampBuf_fx, NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); - fixedToFloat_arr( new_inp_12k8_fx + L_FRAME, new_inp_12k8 + L_FRAME, Q_new_inp, new_inp_out_size ); // To be removed - - change_q( new_inp_12k8_fx + L_FRAME, new_inp_out_size, Q_new_inp ); + new_inp_out_size = modify_Fs_ivas_fx( temp1F_icatdmResampBuf_fx, NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8_fx + L_FRAME, INT_FS_12k8, mem_decim_dummy_fx, 0, &Q_new_inp, &mem_decim_size ); + Scale_sig( new_inp_12k8_fx + L_FRAME, new_inp_out_size, negate( Q_new_inp ) ); /* scaling back to q_input*/ } ELSE /* DFT stereo */ { /* update the FIR resampling filter memory, needed for switching to time-domain (FIR) resampling */ - Copy( signal_in_fx + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim_fx, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); - mvr2r( signal_in + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); // To be removed + Copy( signal_in_fx + sub( input_frame, add( NS2SA_FX2( input_Fs, L_MEM_RECALC_NS ), 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ) ), st->mem_decim_fx, 2 * NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ) ); } -#else - if ( element_mode == IVAS_SCE ) - { - modify_Fs( signal_in, input_frame, input_Fs, new_inp_12k8, INT_FS_12k8, st->mem_decim, ( st->max_bwidth == NB ) ); + old_inp_12k8_e = sub( 15, q_input ); - mvr2r( st->mem_decim, mem_decim_dummy, 2 * L_FILT_MAX ); - set_f( temp1F_icatdmResampBuf, 0, L_FILT_MAX ); - modify_Fs( temp1F_icatdmResampBuf, NS2SA( st->input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8 + L_FRAME, INT_FS_12k8, mem_decim_dummy, 0 ); - } - else if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_MDCT ) - { - /* reconstruct past segment of the Secondary channel input signal when switching from DFT stereo */ - if ( hCPE->last_element_mode == IVAS_CPE_DFT && st->idchan == 1 ) - { - int16_t length_inp = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS ); - int16_t length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - - modify_Fs( signal_in - lMemRecalc - length_inp, length_inp, input_Fs, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, INT_FS_12k8, st->mem_decim, 0 ); - } - - modify_Fs( signal_in - lMemRecalc, input_frame, input_Fs, new_inp_12k8 - lMemRecalc_12k8, INT_FS_12k8, st->mem_decim, ( st->max_bwidth == NB ) ); - mvr2r( st->mem_decim, mem_decim_dummy, 2 * L_FILT_MAX ); - - if ( lMemRecalc > 0 ) - { - modify_Fs( signal_in + input_frame - lMemRecalc, lMemRecalc, input_Fs, new_inp_12k8 + L_FRAME - lMemRecalc_12k8, INT_FS_12k8, mem_decim_dummy, ( st->max_bwidth == NB ) ); - } - set_f( temp1F_icatdmResampBuf, 0, L_FILT_MAX ); - modify_Fs( temp1F_icatdmResampBuf, NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), input_Fs, new_inp_12k8 + L_FRAME, INT_FS_12k8, mem_decim_dummy, 0 ); - } - else /* DFT stereo */ - { - /* update the FIR resampling filter memory, needed for switching to time-domain (FIR) resampling */ - mvr2r( signal_in + input_frame - NS2SA( input_Fs, L_MEM_RECALC_NS ) - 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ), st->mem_decim, 2 * NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ) ); - } -#endif - /* save input resampled at 12.8kHz, non-preemhasised */ - if ( element_mode == IVAS_CPE_DFT ) - { - mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8, st->buf_speech_enc_flt + L_FRAME32k - STEREO_DFT_OVL_12k8, L_FRAME + STEREO_DFT_OVL_12k8 ); +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + /* save input resampled at 12.8kHz, non-preemhasised */ + if ( element_mode == IVAS_CPE_DFT ) + { + mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8, st->buf_speech_enc_flt + L_FRAME32k - STEREO_DFT_OVL_12k8, L_FRAME + STEREO_DFT_OVL_12k8 ); } else if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_MDCT ) { @@ -1355,6 +1374,8 @@ ivas_error pre_proc_front_ivas_fx( { mvr2r( new_inp_12k8, st->buf_speech_enc_flt + L_FRAME32k, L_FRAME ); } +#endif // DEBUG + #ifndef MSAN_FIX /*To be enabled when updations related to new_inp_12k8_fx is enabled */ #if 1 IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) @@ -1377,212 +1398,116 @@ ivas_error pre_proc_front_ivas_fx( /*------------------------------------------------------------------* * Perform fixed preemphasis (12.8 kHz signal) through 1 - g*z^-1 *-----------------------------------------------------------------*/ -#if 0 // Disabled due to high mld -#if 0 // EVS-Version - Word16 headroom = 1; - IF( ( ( EQ_16( st->bwidth, NB ) ) || ( EQ_16( st->max_bwidth, NB ) ) ) && ( GT_32( st->input_Fs, 8000 ) ) ) - { - headroom = add( headroom, 1 ); - } - IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) - { - Copy( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw_fx, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ - - st->mem_preemph_fx = st->mem_preemph_DFT_fx; - st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; - - Preemph_scaled( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type, 1 ); - - fixedToFloat_arr( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, new_inp_12k8 - STEREO_DFT_OVL_12k8, Q_new, L_FRAME ); // To be removed - dummy_fx = st->mem_preemph_fx; - Preemph_scaled( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, &Q_new, &dummy_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, STEREO_DFT_OVL_12k8, st->last_coder_type, 1 ); - - st->mem_preemph = (float) st->mem_preemph_fx; - fixedToFloat_arr( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, Q_new, STEREO_DFT_OVL_12k8 ); // To be removed - } - ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) - { - IF( EQ_16( st->idchan, 0 ) ) - { - IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) - { - st->mem_preemph_fx = st->mem_preemph_DFT_fx; - Copy( st->inp_12k8_mem_stereo_sw_fx, new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); - Preemph_scaled( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT, st->last_coder_type, 1 ); - - st->mem_preemph = (float) st->mem_preemph_fx; - fixedToFloat_arr( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), Q_new, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); // To be removed - } - - st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ - } - - /* preemphasise past segment of the Secondary channel input signal when switching from DFT stereo */ - IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && EQ_16( st->idchan, 1 ) ) - { - Word16 length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - Preemph_scaled( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, length_12k8, st->last_coder_type, 1 ); - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, Q_new, length_12k8 ); // To be removed - } - - Preemph_scaled( new_inp_12k8_fx - lMemRecalc_12k8, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type, 1 ); - dummy_fx = st->mem_preemph_fx; - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_12k8 - lMemRecalc_12k8, Q_new, L_FRAME ); // To be removed - - Preemph_scaled( new_inp_12k8_fx - lMemRecalc_12k8 + L_FRAME, &Q_new, &dummy_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, lMemRecalc_12k8 + L_FILT, st->last_coder_type, 1 ); - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 + L_FRAME, new_inp_12k8 - lMemRecalc_12k8 + L_FRAME, Q_new, lMemRecalc_12k8 + L_FILT ); // To be removed - } - ELSE /* IVAS_SCE or IVAS_CPE_MDCT */ - { - floatToFixed_arr( new_inp_12k8, new_inp_12k8_fx, 0, L_FRAME + L_FILT ); // To be removed - - Preemph_scaled( new_inp_12k8_fx, &Q_new, &st->mem_preemph_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FRAME, st->last_coder_type, 1 ); - dummy_fx = st->mem_preemph_fx; - - fixedToFloat_arr( new_inp_12k8_fx, new_inp_12k8, Q_new, L_FRAME ); // To be removed - floatToFixed_arr( new_inp_12k8, new_inp_12k8_fx, 0, L_FRAME + L_FILT ); // To be removed - - Preemph_scaled( new_inp_12k8_fx + L_FRAME, &Q_new, &dummy_fx, st->Q_max, PREEMPH_FAC, 0, headroom, L_Q_MEM, L_FILT, st->last_coder_type, 1 ); - st->mem_preemph = (float) st->mem_preemph_fx; - - fixedToFloat_arr( new_inp_12k8_fx + 256, new_inp_12k8 + 256, Q_new, 12 ); // To be removed - } - - Q_exp = sub( Q_new, st->Q_old ); - st->prev_Q_old = st->Q_old; + max_e = old_inp_12k8_e; move16(); - st->Q_old = Q_new; + max_e = s_max( max_e, mem_preemph_e ); + max_e = s_max( max_e, mem_preemph_DFT_e ); + Scale_sig( old_inp_12k8_fx, 496, sub( old_inp_12k8_e, max_e ) ); + st->mem_preemph_DFT_fx = shr( st->mem_preemph_DFT_fx, sub( max_e, mem_preemph_DFT_e ) ); + st->mem_preemph_fx = shr( st->mem_preemph_fx, sub( max_e, mem_preemph_e ) ); + old_inp_12k8_e = mem_preemph_DFT_e = mem_preemph_e = max_e; move16(); -#else // IVAS-Version - + move16(); + move16(); + move16(); + move16(); + test(); IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) { - floatToFixed_arr( new_inp_12k8 - STEREO_DFT_OVL_12k8, new_inp_12k8_fx - STEREO_DFT_OVL_12k8, 0, L_FRAME + STEREO_DFT_OVL_12k8 ); // To be removed - st->mem_preemph_fx = (Word16) st->mem_preemph; - st->mem_preemph_DFT_fx = (Word16) st->mem_preemph_DFT; - Copy( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw_fx, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ -#if 1 // TOBE removed later - mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; -#endif + inp_12k8_mem_stereo_sw_e = old_inp_12k8_e; + move16(); + st->mem_preemph_fx = st->mem_preemph_DFT_fx; + move16(); st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; + move16(); PREEMPH_FX( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, PREEMPH_FAC, L_FRAME, &st->mem_preemph_fx ); dummy_fx = st->mem_preemph_fx; - PREEMPH_FX( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, PREEMPH_FAC_FLT, STEREO_DFT_OVL_12k8, &dummy_fx ); + move16(); - fixedToFloat_arr( new_inp_12k8_fx - STEREO_DFT_OVL_12k8, new_inp_12k8 - STEREO_DFT_OVL_12k8, 0, L_FRAME + STEREO_DFT_OVL_12k8 ); // To be removed - st->mem_preemph = (float) st->mem_preemph_fx; - st->mem_preemph_DFT = (float) st->mem_preemph_DFT_fx; + PREEMPH_FX( new_inp_12k8_fx - STEREO_DFT_OVL_12k8 + L_FRAME, PREEMPH_FAC, STEREO_DFT_OVL_12k8, &dummy_fx ); } ELSE IF( EQ_16( element_mode, IVAS_CPE_TD ) || EQ_16( element_mode, IVAS_CPE_MDCT ) ) { - IF( EQ_16( st->idchan, 0 ) ) + IF( st->idchan == 0 ) { - - st->mem_preemph_fx = (Word16) st->mem_preemph; IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) { -#if 1 // TOBE removed later - - floatToFixed_arr( new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), 0, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); // To be removed - st->mem_preemph_DFT_fx = (Word16) st->mem_preemph_DFT; - - mvr2r( st->inp_12k8_mem_stereo_sw, new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); -#endif st->mem_preemph_fx = st->mem_preemph_DFT_fx; + move16(); + IF( GT_16( inp_12k8_mem_stereo_sw_e, old_inp_12k8_e ) ) + { + Scale_sig( new_inp_12k8_fx - ( L_INP_MEM - L_FILT ), L_FRAME + L_INP_MEM, old_inp_12k8_e - inp_12k8_mem_stereo_sw_e ); + old_inp_12k8_e = inp_12k8_mem_stereo_sw_e; + st->mem_preemph_fx = shr( st->mem_preemph_fx, inp_12k8_mem_stereo_sw_e - mem_preemph_e ); + mem_preemph_e = inp_12k8_mem_stereo_sw_e; + move16(); + move16(); + move16(); + } + ELSE + { + Scale_sig( st->inp_12k8_mem_stereo_sw_fx, 4, inp_12k8_mem_stereo_sw_e - old_inp_12k8_e ); + inp_12k8_mem_stereo_sw_e = old_inp_12k8_e; + move16(); + } Copy( st->inp_12k8_mem_stereo_sw_fx, new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); PREEMPH_FX( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), PREEMPH_FAC, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT, &st->mem_preemph_fx ); - - fixedToFloat_arr( new_inp_12k8_fx - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), 0, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); // To be removed } - st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ -#if 1 // TOBE removed later - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ // TO be remove later -#endif + st->mem_preemph_DFT_fx = old_inp_12k8_fx[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ + mem_preemph_DFT_e = old_inp_12k8_e; + move16(); } /* preemphasise past segment of the Secondary channel input signal when switching from DFT stereo */ + test(); IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) && EQ_16( st->idchan, 1 ) ) { - Word16 length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - - floatToFixed_arr( new_inp_12k8 - lMemRecalc_12k8 - length_12k8, new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, 0, length_12k8 ); // To be removed - + Word16 length_12k8 = NS2SA_FX2( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); + move16(); PREEMPH_FX( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, PREEMPH_FAC, length_12k8, &st->mem_preemph_fx ); - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8 - length_12k8, new_inp_12k8 - lMemRecalc_12k8 - length_12k8, 0, length_12k8 ); // To be removed } - floatToFixed_arr( new_inp_12k8 - lMemRecalc_12k8, new_inp_12k8_fx - lMemRecalc_12k8, 0, L_FRAME + lMemRecalc_12k8 + L_FILT ); // To be removed - PREEMPH_FX( new_inp_12k8_fx - lMemRecalc_12k8, PREEMPH_FAC, L_FRAME, &st->mem_preemph_fx ); dummy_fx = st->mem_preemph_fx; + move16(); PREEMPH_FX( new_inp_12k8_fx - lMemRecalc_12k8 + L_FRAME, PREEMPH_FAC, lMemRecalc_12k8 + L_FILT, &dummy_fx ); - - fixedToFloat_arr( new_inp_12k8_fx - lMemRecalc_12k8, new_inp_12k8 - lMemRecalc_12k8, 0, L_FRAME + lMemRecalc_12k8 + L_FILT ); // To be removed } ELSE /* IVAS_SCE or IVAS_CPE_MDCT */ { - floatToFixed_arr( new_inp_12k8, new_inp_12k8_fx, 0, L_FRAME + L_FILT ); // To be removed - st->mem_preemph_fx = (Word16) st->mem_preemph; - PREEMPH_FX( new_inp_12k8_fx, PREEMPH_FAC, L_FRAME, &st->mem_preemph_fx ); dummy_fx = st->mem_preemph_fx; + move16(); PREEMPH_FX( new_inp_12k8_fx + L_FRAME, PREEMPH_FAC, L_FILT, &dummy_fx ); - - st->mem_preemph = (float) st->mem_preemph_fx; - dummy = (float) dummy_fx; - fixedToFloat_arr( new_inp_12k8_fx, new_inp_12k8, 0, L_FRAME + L_FILT ); // To be removed } -#endif -#else - if ( element_mode == IVAS_CPE_DFT ) - { - mvr2r( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, st->inp_12k8_mem_stereo_sw, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); /* memory for TD/DFT stereo switching */ - st->mem_preemph = st->mem_preemph_DFT; - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; +#ifdef IVAS_FLOAT_FIXED_TO_BE_REMOVED + /*fixed to float from modify_fs block*/ + fixedToFloat_arr( st->mem_decim_fx, st->mem_decim, q_input, 90 ); // To be removed - preemph( new_inp_12k8 - STEREO_DFT_OVL_12k8, PREEMPH_FAC_FLT, L_FRAME, &st->mem_preemph ); - dummy = st->mem_preemph; - preemph( new_inp_12k8 - STEREO_DFT_OVL_12k8 + L_FRAME, PREEMPH_FAC_FLT, STEREO_DFT_OVL_12k8, &dummy ); - } - else if ( element_mode == IVAS_CPE_TD || element_mode == IVAS_CPE_MDCT ) - { - if ( st->idchan == 0 ) - { - if ( hCPE->last_element_mode == IVAS_CPE_DFT ) - { - st->mem_preemph = st->mem_preemph_DFT; - mvr2r( st->inp_12k8_mem_stereo_sw, new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); - preemph( new_inp_12k8 - L_MEM_RECALC_12K8 - ( STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ), PREEMPH_FAC_FLT, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT, &st->mem_preemph ); - } - - st->mem_preemph_DFT = old_inp_12k8[L_INP_MEM - STEREO_DFT_OVL_12k8 + L_FRAME - 1]; /* == inp_12k8[L_FRAME-1] */ - } + /*fixed to float conversions for preemph_fx block*/ + st->mem_preemph = me2f_16( st->mem_preemph_fx, mem_preemph_e ); + st->mem_preemph_DFT = me2f_16( st->mem_preemph_DFT_fx, mem_preemph_DFT_e ); + fixedToFloat_arr( st->inp_12k8_mem_stereo_sw_fx, st->inp_12k8_mem_stereo_sw, 15 - inp_12k8_mem_stereo_sw_e, STEREO_DFT_OVL_12k8 - L_MEM_RECALC_12K8 - L_FILT ); + fixedToFloat_arr( old_inp_12k8_fx, old_inp_12k8, 15 - old_inp_12k8_e, L_INP_MEM + L_FRAME ); // To be removed - /* preemphasise past segment of the Secondary channel input signal when switching from DFT stereo */ - if ( hCPE->last_element_mode == IVAS_CPE_DFT && st->idchan == 1 ) + /*analysisCldfbEncoder_ivas_fx*/ + for ( i = 0; i < CLDFB_NO_COL_MAX; i++ ) + { + for ( int j = 0; j < CLDFB_NO_CHANNELS_MAX; j++ ) { - int16_t length_12k8 = NS2SA( INT_FS_12k8, L_MEM_RECALC_SCH_NS ); - preemph( new_inp_12k8 - lMemRecalc_12k8 - length_12k8, PREEMPH_FAC_FLT, length_12k8, &st->mem_preemph ); + realBuffer[i][j] = fixedToFloat( realBuffer_fx[i][j], 16 - cldfbScale.lb_scale ); + imagBuffer[i][j] = fixedToFloat( imagBuffer_fx[i][j], 16 - cldfbScale.lb_scale ); } - - preemph( new_inp_12k8 - lMemRecalc_12k8, PREEMPH_FAC_FLT, L_FRAME, &st->mem_preemph ); - dummy = st->mem_preemph; - preemph( new_inp_12k8 - lMemRecalc_12k8 + L_FRAME, PREEMPH_FAC_FLT, lMemRecalc_12k8 + L_FILT, &dummy ); } - else /* IVAS_SCE or IVAS_CPE_MDCT */ + cldfbScale.hb_scale = cldfbScale.lb_scale; + fixedToFloat_arrL( enerBuffer_fx, enerBuffer, 31 - enerBuffer_exp, 60 ); + IF( st->cldfbAnaEnc != NULL ) { - preemph( new_inp_12k8, PREEMPH_FAC_FLT, L_FRAME, &st->mem_preemph ); - dummy = st->mem_preemph; - preemph( new_inp_12k8 + L_FRAME, PREEMPH_FAC_FLT, L_FILT, &dummy ); + fixedToFloat_arrL( st->cldfbAnaEnc->cldfb_state_fx, st->cldfbAnaEnc->cldfb_state, Q11, sub( sub( st->cldfbAnaEnc->p_filter_length, st->cldfbAnaEnc->no_channels ), st->cldfbAnaEnc->zeros ) ); } #endif @@ -1603,115 +1528,170 @@ ivas_error pre_proc_front_ivas_fx( /*-------------------------------------------------------------------------* * Spectral analysis *--------------------------------------------------------------------------*/ +#if 1 /*Fixed implementation disabled due to wrong values*/ analy_sp( element_mode, hCPE, input_Fs, inp_12k8, st->Bin_E, st->Bin_E_old, fr_bands, lf_E, &Etot, st->min_band, st->max_band, band_energies, PS, fft_buff ); +#else + Word16 Q_inp_dmx = Q_factor_arrL( hCPE->hStereoDft->DFT[0], STEREO_DFT_N_MAX_ENC ) - 1; + floatToFixed_arrL( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], Q_inp_dmx, STEREO_DFT_N_MAX_ENC ); + Word16 Q_new; + Word16 Scale_fac[2]; + Q_new = 15 - old_inp_12k8_e; + Le_min_scaled = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_new, QSCALE ) ) ), 1 ), 1 ); + ivas_analy_sp_fx( element_mode, hCPE, input_Fs, inp_12k8_fx /*old_inp_12k8_e*/, Q_new, fr_bands_fx, lf_E_fx, &Etot_16fx, st->min_band, st->max_band, Le_min_scaled, Scale_fac, st->Bin_E_fx, st->Bin_E_old_fx, PS_fx, lgBin_E_fx, band_energies_fx, fft_buff_fx, Q_inp_dmx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( fr_bands_fx, fr_bands, Q_new + QSCALE + 2, 40 ); + fixedToFloat_arrL( band_energies_fx, band_energies, Q_new + QSCALE + 2, 40 ); + fixedToFloat_arrL( lf_E_fx, lf_E, Q_new + QSCALE, 148 ); + fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, Q_new + QSCALE, 256 ); + IF( lgBin_E_fx != NULL ) + { + fixedToFloat_arr( lgBin_E_fx, st->Bin_E, Q7, 128 ); + } + fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, Q_new + QSCALE, 128 ); + fixedToFloat_arrL( PS_fx, PS, Q_new + QSCALE, 128 ); + Etot = fixedToFloat( Etot_16fx, Q8 ); + fixedToFloat_arr( fft_buff_fx, fft_buff, Q_new + QSCALE + Scale_fac[0] - 14, 512 ); +#endif +#endif - if ( hStereoClassif != NULL ) +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*float to fix conversions for noise_est_pre_32fx*/ + Etot_fx = (Word32) ( Etot * ( 1 << 24 ) ); + st->hNoiseEst->Etot_h_32fx = (Word32) ( st->hNoiseEst->Etot_h * 16777216.0 ); + st->hNoiseEst->Etot_l_32fx = (Word32) ( st->hNoiseEst->Etot_l * 16777216.0 ); + st->hNoiseEst->Etot_l_lp_32fx = (Word32) ( st->hNoiseEst->Etot_l_lp * 16777216.0 ); + st->hNoiseEst->Etot_last_32fx = (Word32) ( st->hNoiseEst->Etot_last * 16777216.0 ); + st->hNoiseEst->Etot_v_h2_32fx = (Word32) ( st->hNoiseEst->Etot_v_h2 * 16777216.0 ); + st->hNoiseEst->Etot_lp_32fx = (Word32) ( st->hNoiseEst->Etot_lp * 16777216.0 ); + st->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( st->hNoiseEst->sign_dyn_lp * 16777216.0 ); + + /*float to fix conversions for wb_vad_ivas_fx*/ + Word16 Q_new = Q_factor_arr( fr_bands, 40 ); + floatToFixed_arrL( fr_bands, fr_bands_fx, Q_new + QSCALE, 40 ); + st->lp_noise_fx = float_to_fix16( st->lp_noise, 8 ); + st->lp_speech_fx = float_to_fix16( st->lp_speech, 8 ); + floatToFixed_arrL( st->hNoiseEst->bckr, st->hNoiseEst->bckr_fx, Q_new + QSCALE, 20 ); + floatToFixed_arrL( st->hNoiseEst->enrO, st->hNoiseEst->enrO_fx, Q_new + QSCALE, 20 ); + st->flag_noisy_speech_snr_fx = (Word8) st->flag_noisy_speech_snr; + st->hVAD->bcg_flux_fx = float_to_fix16( st->hVAD->bcg_flux, 4 ); + st->hVAD->L_snr_sum_vad_fx = floatToFixed( st->hVAD->snr_sum_vad, 4 ); + st->hVAD->prim_act_quick_fx = float_to_fix16( st->hVAD->prim_act_quick, 15 ); + st->hVAD->prim_act_slow_fx = float_to_fix16( st->hVAD->prim_act_slow, 15 ); + st->hVAD->prim_act_fx = float_to_fix16( st->hVAD->prim_act, 15 ); + st->hVAD->prim_act_quick_he_fx = float_to_fix16( st->hVAD->prim_act_quick_he, 15 ); + st->hVAD->prim_act_slow_he_fx = float_to_fix16( st->hVAD->prim_act_slow_he, 15 ); + st->hVAD->prim_act_he_fx = float_to_fix16( st->hVAD->prim_act_he, 15 ); + + /*float to fix for dtx_hangover_addition_fx*/ + st->hNoiseEst->Etot_lp_fx = (Word16) ( st->hNoiseEst->Etot_lp * ( 1 << 8 ) ); + + if ( st->cldfbAnaEnc ) + st->cldfbAnaEnc->scale = (Word16) ( st->cldfbAnaEnc->scale_flt * ( 1 << 8 ) ); + st->lt_mean_NB_fx = (Word16) st->lt_mean_NB * ( 1 << 11 ); + st->lt_mean_WB_fx = (Word16) st->lt_mean_WB * ( 1 << 11 ); + st->lt_mean_SWB_fx = (Word16) st->lt_mean_SWB * ( 1 << 11 ); + + /* float to fix for noise_est_down*/ + st->hNoiseEst->Etot_last_fx = float_to_fix16( st->hNoiseEst->Etot_last, 8 ); + st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, 8 ); + Word16 Q_bands0 = 0, Q_bands1 = 0; + IF( lr_vad_enabled && st->idchan == 0 ) + { + Q_bands0 = Q_factor_arr( fr_bands_LR[0], 2 * NB_BANDS ); + Q_bands1 = Q_factor_arr( fr_bands_LR[1], 2 * NB_BANDS ); + floatToFixed_arrL( fr_bands_LR[0], fr_bands_LR_fx[0], Q_bands0 + QSCALE, 2 * NB_BANDS ); + floatToFixed_arrL( fr_bands_LR[1], fr_bands_LR_fx[1], Q_bands1 + QSCALE, 2 * NB_BANDS ); + floatToFixed_arrL( hCPE->hFrontVad[0]->hNoiseEst->bckr, hCPE->hFrontVad[0]->hNoiseEst->bckr_fx, Q_bands0 + QSCALE, NB_BANDS ); + floatToFixed_arrL( hCPE->hFrontVad[1]->hNoiseEst->bckr, hCPE->hFrontVad[1]->hNoiseEst->bckr_fx, Q_bands1 + QSCALE, NB_BANDS ); + hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->totalNoise, 8 ); + Etot_LR_fx[0] = float_to_fix16( Etot_LR[0], 8 ); + Etot_LR_fx[1] = float_to_fix16( Etot_LR[1], 8 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_last_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->Etot_last, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_last_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->Etot_last, 8 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2, 8 ); + } +#endif // IVAS_FLOAT_FIXED_TO_BE_REMOVED + + IF( hStereoClassif != NULL ) { - if ( st->lp_speech - Etot > 25 ) + IF( GT_32( L_sub( L_shl( st->lp_speech_fx, 16 ), Etot_fx ), 25 << Q24 ) ) /*q24*/ { hStereoClassif->silence_flag = 2; + move16(); } - else + ELSE { - hStereoClassif->silence_flag = hStereoClassif->silence_flag - 1; + hStereoClassif->silence_flag = sub( hStereoClassif->silence_flag, 1 ); + move16(); } - hStereoClassif->silence_flag = max( 0, hStereoClassif->silence_flag ); + hStereoClassif->silence_flag = s_max( 0, hStereoClassif->silence_flag ); + move16(); } /*----------------------------------------------------------------* * SAD (1-signal, 0-noise) *----------------------------------------------------------------*/ - Etot_fx = (Word32) ( Etot * ( 1 << 24 ) ); - st->hNoiseEst->Etot_h_32fx = (Word32) ( st->hNoiseEst->Etot_h * 16777216.0 ); - st->hNoiseEst->Etot_l_32fx = (Word32) ( st->hNoiseEst->Etot_l * 16777216.0 ); - st->hNoiseEst->Etot_l_lp_32fx = (Word32) ( st->hNoiseEst->Etot_l_lp * 16777216.0 ); - st->hNoiseEst->Etot_last_32fx = (Word32) ( st->hNoiseEst->Etot_last * 16777216.0 ); - st->hNoiseEst->Etot_v_h2_32fx = (Word32) ( st->hNoiseEst->Etot_v_h2 * 16777216.0 ); - st->hNoiseEst->Etot_lp_32fx = (Word32) ( st->hNoiseEst->Etot_lp * 16777216.0 ); - st->hNoiseEst->sign_dyn_lp_32fx = (Word32) ( st->hNoiseEst->sign_dyn_lp * 16777216.0 ); - noise_est_pre_32fx( Etot_fx, st->ini_frame, st->hNoiseEst, st->idchan, element_mode, hCPE != NULL ? hCPE->last_element_mode : element_mode ); - st->hNoiseEst->Etot_h = (float) ( st->hNoiseEst->Etot_h_32fx / 16777216.0 ); - st->hNoiseEst->Etot_l = (float) ( st->hNoiseEst->Etot_l_32fx / 16777216.0 ); - st->hNoiseEst->Etot_l_lp = (float) ( st->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); - st->hNoiseEst->Etot_last = (float) ( st->hNoiseEst->Etot_last_32fx / 16777216.0 ); - st->hNoiseEst->Etot_v_h2 = (float) ( st->hNoiseEst->Etot_v_h2_32fx / 16777216.0 ); - st->hNoiseEst->Etot_lp = (float) ( st->hNoiseEst->Etot_lp_32fx / 16777216.0 ); - st->hNoiseEst->sign_dyn_lp = (float) ( st->hNoiseEst->sign_dyn_lp_32fx / 16777216.0 ); - - IF( EQ_16( element_mode, IVAS_CPE_TD ) && ( ( abs( hCPE->hStereoTD->tdm_last_ratio_idx - tdm_ratio_idx ) > 5 && EQ_16( st->idchan, 1 ) ) || abs( hCPE->hStereoTD->tdm_last_inst_ratio_idx - hCPE->hStereoTD->tdm_inst_ratio_idx ) > 10 ) ) + test(); + test(); + test(); + if ( EQ_16( element_mode, IVAS_CPE_TD ) && ( ( GT_16( abs_s( sub( hCPE->hStereoTD->tdm_last_ratio_idx, tdm_ratio_idx ) ), 5 ) && EQ_16( st->idchan, 1 ) ) || GT_16( abs_s( sub( hCPE->hStereoTD->tdm_last_inst_ratio_idx, hCPE->hStereoTD->tdm_inst_ratio_idx ) ), 10 ) ) ) { st->ini_frame = 1; + move16(); } -#if 0 // Disbaled due to high MLD - Q_new = Q_factor_arr( fr_bands, 40 ); - floatToFixed_arrL( fr_bands, fr_bands_fx, Q_new + QSCALE, 40 ); - st->lp_noise_fx = (Word16) ( st->lp_noise * ( 1 << 8 ) ); - st->lp_speech_fx = (Word16) ( st->lp_speech * ( 1 << 8 ) ); - floatToFixed_arrL( st->hNoiseEst->bckr, st->hNoiseEst->bckr_fx, Q_new + QSCALE, 20 ); - floatToFixed_arrL( st->hNoiseEst->enrO, st->hNoiseEst->enrO_fx, Q_new + QSCALE, 20 ); - st->flag_noisy_speech_snr_fx = (Word8) st->flag_noisy_speech_snr; - st->hVAD->bcg_flux_fx = (Word16) st->hVAD->bcg_flux * ( 1 << 4 ); - st->hNoiseEst->Etot_v_h2_fx = (Word16) ( st->hNoiseEst->Etot_v_h2 * ( 1 << 8 ) ); - st->hNoiseEst->sign_dyn_lp_fx = (Word16) ( st->hNoiseEst->sign_dyn_lp * ( 1 << 8 ) ); - st->hVAD->snr_sum_vad_fx = (Word16) ( st->hVAD->snr_sum_vad * 32767 ); - st->hVAD->prim_act_quick_fx = (Word16) ( st->hVAD->prim_act_quick * 32767 ); - st->hVAD->prim_act_slow_fx = (Word16) ( st->hVAD->prim_act_slow * 32767 ); - st->hVAD->prim_act_fx = (Word16) ( st->hVAD->prim_act * 32767 ); - st->hVAD->prim_act_quick_he_fx = (Word16) ( st->hVAD->prim_act_quick_he * 32767 ); - st->hVAD->prim_act_slow_he_fx = (Word16) ( st->hVAD->prim_act_slow_he * 32767 ); - st->hVAD->prim_act_he_fx = (Word16) ( st->hVAD->prim_act_he * 32767 ); - + st->hNoiseEst->Etot_v_h2_fx = extract_h( st->hNoiseEst->Etot_v_h2_32fx ); /*q24 to q8*/ + st->hNoiseEst->sign_dyn_lp_fx = extract_h( st->hNoiseEst->sign_dyn_lp_32fx ); /*q24 to q8*/ st->vad_flag = wb_vad_ivas_fx( st, fr_bands_fx, &i, &i, &i, &snr_sum_he_fx, &localVAD_HE_SAD, &( st->flag_noisy_speech_snr_fx ), Q_new, NULL, NULL, -MAX_16, -MAX_16 ); //-100000f == max 16bit float + move16(); + move16(); + move16(); - st->hNoiseEst->Etot_v_h2 = (float) ( st->hNoiseEst->Etot_v_h2_fx / ( 256.0 ) ); - st->hNoiseEst->sign_dyn_lp = (float) ( st->hNoiseEst->sign_dyn_lp_fx / ( 256.0 ) ); - st->hVAD->bcg_flux = (float) ( st->hVAD->bcg_flux_fx / ( 16.0 ) ); - st->flag_noisy_speech_snr = (Word16) st->flag_noisy_speech_snr_fx; - st->hVAD->snr_sum_vad = (float) ( st->hVAD->snr_sum_vad_fx / 32767.0 ); - st->hVAD->prim_act_quick = (float) ( st->hVAD->prim_act_quick_fx / 32767.0 ); - st->hVAD->prim_act_slow = (float) ( st->hVAD->prim_act_slow_fx / 32767.0 ); - st->hVAD->prim_act = (float) ( st->hVAD->prim_act_fx / 32767.0 ); - st->hVAD->prim_act_quick_he = (float) ( st->hVAD->prim_act_quick_he_fx / 32767.0 ); - st->hVAD->prim_act_slow_he = (float) ( st->hVAD->prim_act_slow_he_fx / 32767.0 ); - st->hVAD->prim_act_he = (float) ( st->hVAD->prim_act_he_fx / 32767.0 ); -#else - st->vad_flag = wb_vad( st, fr_bands, &i, &i, &i, &snr_sum_he, &localVAD_HE_SAD, &( st->flag_noisy_speech_snr ), NULL, NULL, -1000.0f, -1000.0f ); -#endif - + test(); IF( EQ_16( force_front_vad, 1 ) || EQ_16( front_vad_flag, 1 ) ) { /* overwrite VAD decision with front-VAD decision if external VAD is set to 1*/ st->vad_flag = front_vad_flag; st->localVAD = front_vad_flag; + move16(); + move16(); } - IF( ( hCPE != NULL && !( lr_vad_enabled && EQ_16( st->idchan, 0 ) ) ) || hSCE != NULL ) + test(); + test(); + test(); + IF( ( hCPE != NULL && !( lr_vad_enabled && st->idchan == 0 ) ) || hSCE != NULL ) { - st->lp_noise_fx = (Word16) ( st->lp_noise * ( 1 << 8 ) ); - st->lp_speech_fx = (Word16) ( st->lp_speech * ( 1 << 8 ) ); - st->hVAD->prim_act_he_fx = (Word16) ( st->hVAD->prim_act_he * MAX_16 ); - st->hNoiseEst->Etot_lp_fx = (Word16) ( st->hNoiseEst->Etot_lp * ( 1 << 8 ) ); *vad_flag_dtx = dtx_hangover_addition_fx( st, st->vad_flag, sub( st->lp_speech_fx, st->lp_noise_fx ), 0, vad_hover_flag, NULL, NULL ); + move16(); } ELSE { /* This only applies to st->idchan==0 now */ /* Add down mix stereo activity to LR vad_flag_dtx */ + test(); *vad_flag_dtx = *vad_flag_dtx || st->vad_flag; + move16(); /* Determine hangover flag status based on LR localVAD and downmix localVAD */ + test(); + test(); *vad_hover_flag = *vad_flag_dtx && !( LR_localVAD || st->localVAD ); + move16(); } - IF( EQ_16( force_front_vad, 1 ) || EQ_16( front_vad_dtx_flag, 1 ) ) + test(); + if ( EQ_16( force_front_vad, 1 ) || EQ_16( front_vad_dtx_flag, 1 ) ) { /* overwrite VAD decision with front-VAD decision if external VAD is set to 1*/ *vad_flag_dtx = front_vad_dtx_flag; + move16(); } /*----------------------------------------------------------------* @@ -1723,37 +1703,31 @@ ivas_error pre_proc_front_ivas_fx( move16(); } + test(); IF( EQ_16( st->idchan, 0 ) && NE_16( element_mode, IVAS_CPE_MDCT ) ) { - st->cldfbAnaEnc->scale = (Word16) ( st->cldfbAnaEnc->scale_flt * ( 1 << 8 ) ); - floatToFixed_arr( st->input, st->input_fx, 0, 480 ); -#ifdef MSAN_FIX - st->lt_mean_NB_fx = (Word16) st->lt_mean_NB * ( 1 << 11 ); - st->lt_mean_WB_fx = (Word16) st->lt_mean_WB * ( 1 << 11 ); - st->lt_mean_SWB_fx = (Word16) st->lt_mean_SWB * ( 1 << 11 ); - st->lp_noise_fx = (Word16) st->lp_noise * ( 1 << 8 ); // have taken Q8 as above one functions uses Q8 -#endif + Scale_sig( st->input_fx, 480, negate( q_input ) ); /*scaling from q_input to q0*/ bw_detect_fx( st, st->input_fx, NULL, enerBuffer_fx, sf_energySum, ivas_format, 0 ); - st->lt_mean_NB = (float) st->lt_mean_NB_fx / ( 1 << 11 ); - st->lt_mean_WB = (float) st->lt_mean_WB_fx / ( 1 << 11 ); - st->lt_mean_SWB = (float) st->lt_mean_SWB_fx / ( 1 << 11 ); + Scale_sig( st->input_fx, 480, q_input ); /*scaling back to q_input*/ } + IF( NE_16( element_mode, IVAS_CPE_MDCT ) ) /* in MDCT stereo, set_bw_stereo() is used instead */ { -#ifndef IVAS_FLOAT_FIXED - set_bw( element_mode, element_brate, st, MODE1 ); -#else set_bw_fx( element_mode, element_brate, st, MODE1 ); -#endif } + /* set the BW of the TD secondary channel in LRTD mode same as BW of the primary channel (only at higher bitrates) */ - IF( EQ_16( st->idchan, 1 ) && EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->tdm_LRTD_flag, 1 ) && st->bits_frame_channel >= IVAS_16k4 / FRAMES_PER_SEC ) + test(); + test(); + test(); + if ( EQ_16( st->idchan, 1 ) && EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( st->tdm_LRTD_flag, 1 ) && GE_16( st->bits_frame_channel, IVAS_16k4 / FRAMES_PER_SEC ) ) { st->bwidth = hCPE->hCoreCoder[0]->bwidth; + move16(); } /*----------------------------------------------------------------* @@ -1762,31 +1736,72 @@ ivas_error pre_proc_front_ivas_fx( * Correlation correction as a function of total noise level *----------------------------------------------------------------*/ - noise_est_down( fr_bands, st->hNoiseEst->bckr, tmpN, tmpE, st->min_band, st->max_band, &st->hNoiseEst->totalNoise, Etot, &st->hNoiseEst->Etot_last, &st->hNoiseEst->Etot_v_h2 ); + Word32 Le_min_scaled = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_new, QSCALE ) ) ), 1 ), 1 ); + Etot_16fx = extract_h( Etot_fx ); /*q24 to q8*/ + noise_est_down_fx( fr_bands_fx, st->hNoiseEst->bckr_fx, tmpN_fx, tmpE_fx, st->min_band, st->max_band, &st->hNoiseEst->totalNoise_fx, Etot_16fx, &st->hNoiseEst->Etot_last_fx, &st->hNoiseEst->Etot_v_h2_fx, Q_new, Le_min_scaled ); - if ( lr_vad_enabled && st->idchan == 0 ) + test(); + IF( lr_vad_enabled && st->idchan == 0 ) { - noise_est_down( fr_bands_LR[0], hCPE->hFrontVad[0]->hNoiseEst->bckr, tmpN_LR[0], tmpE_LR[0], st->min_band, st->max_band, &hCPE->hFrontVad[0]->hNoiseEst->totalNoise, Etot_LR[0], &hCPE->hFrontVad[0]->hNoiseEst->Etot_last, &hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2 ); - noise_est_down( fr_bands_LR[1], hCPE->hFrontVad[1]->hNoiseEst->bckr, tmpN_LR[1], tmpE_LR[1], st->min_band, st->max_band, &hCPE->hFrontVad[1]->hNoiseEst->totalNoise, Etot_LR[1], &hCPE->hFrontVad[1]->hNoiseEst->Etot_last, &hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2 ); -#ifndef IVAS_FLOAT_FIXED - corr_shiftL = correlation_shift( hCPE->hFrontVad[0]->hNoiseEst->totalNoise ); - corr_shiftR = correlation_shift( hCPE->hFrontVad[1]->hNoiseEst->totalNoise ); -#else -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 corr_shiftL_fx, corr_shiftR_fx; - // performing float to fix conversion of (totalNoise) - hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); - hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[1]->hNoiseEst->totalNoise, 8 ); -#endif + Word32 Le_min_scaled0, Le_min_scaled1; + Le_min_scaled0 = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_bands0, QSCALE ) ) ), 1 ), 1 ); + Le_min_scaled1 = L_shr_r( L_add( L_shr( E_MIN_FXQ15, sub( 14, add( Q_bands1, QSCALE ) ) ), 1 ), 1 ); + noise_est_down_fx( fr_bands_LR_fx[0], hCPE->hFrontVad[0]->hNoiseEst->bckr_fx, tmpN_LR_fx[0], tmpE_LR_fx[0], st->min_band, st->max_band, &hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx, Etot_LR_fx[0], &hCPE->hFrontVad[0]->hNoiseEst->Etot_last_fx, &hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx, Q_bands0, Le_min_scaled0 ); + noise_est_down_fx( fr_bands_LR_fx[1], hCPE->hFrontVad[1]->hNoiseEst->bckr_fx, tmpN_LR_fx[1], tmpE_LR_fx[1], st->min_band, st->max_band, &hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx, Etot_LR_fx[1], &hCPE->hFrontVad[1]->hNoiseEst->Etot_last_fx, &hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx, Q_bands1, Le_min_scaled1 ); + corr_shiftL_fx = correlation_shift_fx( hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx ); corr_shiftR_fx = correlation_shift_fx( hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx ); + } #ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*cleanup changes for noise_est_pre_32fx*/ + st->hNoiseEst->Etot_h = (float) ( st->hNoiseEst->Etot_h_32fx / 16777216.0 ); + st->hNoiseEst->Etot_l = (float) ( st->hNoiseEst->Etot_l_32fx / 16777216.0 ); + st->hNoiseEst->Etot_l_lp = (float) ( st->hNoiseEst->Etot_l_lp_32fx / 16777216.0 ); + st->hNoiseEst->Etot_last = (float) ( st->hNoiseEst->Etot_last_32fx / 16777216.0 ); + st->hNoiseEst->Etot_lp = (float) ( st->hNoiseEst->Etot_lp_32fx / 16777216.0 ); + + /*cleanup changes for wb_vad_ivas_fx*/ + st->hNoiseEst->sign_dyn_lp = fixedToFloat( st->hNoiseEst->sign_dyn_lp_fx, 8 ); + st->hVAD->bcg_flux = fixedToFloat( st->hVAD->bcg_flux_fx, 4 ); + st->flag_noisy_speech_snr = (Word16) st->flag_noisy_speech_snr_fx; + st->hVAD->snr_sum_vad = fixedToFloat( st->hVAD->L_snr_sum_vad_fx, 4 ); + st->hVAD->prim_act_quick = fixedToFloat( st->hVAD->prim_act_quick_fx, 15 ); + st->hVAD->prim_act_slow = fixedToFloat( st->hVAD->prim_act_slow_fx, 15 ); + st->hVAD->prim_act = fixedToFloat( st->hVAD->prim_act_fx, 15 ); + st->hVAD->prim_act_quick_he = fixedToFloat( st->hVAD->prim_act_quick_he_fx, 15 ); + st->hVAD->prim_act_slow_he = fixedToFloat( st->hVAD->prim_act_slow_he_fx, 15 ); + st->hVAD->prim_act_he = fixedToFloat( st->hVAD->prim_act_he_fx, 15 ); + + st->lt_mean_NB = (float) st->lt_mean_NB_fx / ( 1 << 11 ); + st->lt_mean_WB = (float) st->lt_mean_WB_fx / ( 1 << 11 ); + st->lt_mean_SWB = (float) st->lt_mean_SWB_fx / ( 1 << 11 ); + + /*fixed to float for noise_est_down*/ + fixedToFloat_arrL( st->hNoiseEst->bckr_fx, st->hNoiseEst->bckr, Q_new + QSCALE, NB_BANDS ); + st->hNoiseEst->totalNoise = fixedToFloat( st->hNoiseEst->totalNoise_fx, 8 ); + fixedToFloat_arrL( tmpN_fx, tmpN, Q_new + QSCALE, 20 ); + fixedToFloat_arrL( tmpE_fx, tmpE, Q_new + QSCALE, 20 ); + st->hNoiseEst->Etot_v_h2 = fixedToFloat( st->hNoiseEst->Etot_v_h2_fx, 8 ); + + /*fixed to float for noise_est_down_fx concerned with fr_bands_LR*/ + IF( lr_vad_enabled && st->idchan == 0 ) + { + fixedToFloat_arrL( hCPE->hFrontVad[0]->hNoiseEst->bckr_fx, hCPE->hFrontVad[0]->hNoiseEst->bckr, Q_bands0 + QSCALE, NB_BANDS ); + fixedToFloat_arrL( hCPE->hFrontVad[1]->hNoiseEst->bckr_fx, hCPE->hFrontVad[1]->hNoiseEst->bckr, Q_bands1 + QSCALE, NB_BANDS ); + hCPE->hFrontVad[0]->hNoiseEst->totalNoise = fixedToFloat( hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx, 8 ); + hCPE->hFrontVad[1]->hNoiseEst->totalNoise = fixedToFloat( hCPE->hFrontVad[1]->hNoiseEst->totalNoise_fx, 8 ); + fixedToFloat_arrL( tmpN_LR_fx[0], tmpN_LR[0], Q_bands0 + QSCALE, 20 ); + fixedToFloat_arrL( tmpE_LR_fx[0], tmpE_LR[0], Q_bands0 + QSCALE, 20 ); + hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2 = fixedToFloat( hCPE->hFrontVad[0]->hNoiseEst->Etot_v_h2_fx, 8 ); + fixedToFloat_arrL( tmpN_LR_fx[1], tmpN_LR[1], Q_bands1 + QSCALE, 20 ); + fixedToFloat_arrL( tmpE_LR_fx[1], tmpE_LR[1], Q_bands1 + QSCALE, 20 ); + hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2 = fixedToFloat( hCPE->hFrontVad[1]->hNoiseEst->Etot_v_h2_fx, 8 ); + // performing fix to float conversion of (corr_shift_fx) corr_shiftL = fix16_to_float( corr_shiftL_fx, 15 ); corr_shiftR = fix16_to_float( corr_shiftR_fx, 15 ); -#endif -#endif } +#endif *relE = Etot - st->lp_speech; @@ -2058,7 +2073,6 @@ ivas_error pre_proc_front_ivas_fx( #else #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // conv params from float to fix - Word16 Etot_LR_fx[2]; Etot_LR_fx[0] = float_to_fix16( Etot_LR[0], 8 ); Etot_LR_fx[1] = float_to_fix16( Etot_LR[1], 8 ); hCPE->hFrontVad[0]->hNoiseEst->totalNoise_fx = float_to_fix16( hCPE->hFrontVad[0]->hNoiseEst->totalNoise, 8 ); @@ -2109,8 +2123,57 @@ ivas_error pre_proc_front_ivas_fx( { if ( ivas_format == SBA_FORMAT && st->core_brate != FRAME_NO_DATA && st->last_core_brate == FRAME_NO_DATA && st->sba_br_sw_while_no_data ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( ( NE_32( imult1616( st->last_bits_frame_nominal, FRAMES_PER_SEC ), st->total_brate ) ) || + ( NE_16( st->last_bwidth, st->bwidth ) ) || + ( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->element_mode, EVS_MONO ) ) || + ( ( NE_16( st->last_core, TCX_20_CORE ) && NE_16( st->last_core, TCX_10_CORE ) ) && GT_16( st->element_mode, EVS_MONO ) ) || + ( NE_16( st->rf_mode_last, st->rf_mode ) ) || + ( GT_16( st->element_mode, EVS_MONO ) && st->ini_frame == 0 ) ) + { + Word16 bSwitchFromAmrwbIO = 0, switchWB = 0, fscale; + Word32 sr_core; + move16(); + move16(); + + IF( EQ_16( st->last_core, AMR_WB_CORE ) ) + { + bSwitchFromAmrwbIO = 1; + move16(); + } + sr_core = getCoreSamplerateMode2( st->element_mode, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode, st->is_ism_format ); + fscale = sr2fscale_fx( sr_core ); + IF( EQ_32( fscale, st->fscale ) && !bSwitchFromAmrwbIO && !switchWB ) + { + st->hTcxCfg->bandwidth_flt = getTcxBandwidth_flt( st->bwidth ); + } + IF( st->envWeighted && !st->enableTcxLpc ) + { + /* Unweight the envelope */ + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + st->gamma = (Word16) floatToFixed( st->gamma_flt, Q14 ); + } + } +#endif + + SetModeIndex_ivas_fx( st, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), element_mode, MCT_flag ); + + st->sba_br_sw_while_no_data = 0; + move16(); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IF( st->envWeighted && !st->enableTcxLpc ) + { + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + fixedToFloat_arr( st->lsf_old_fx, st->lsf_old, Q15, M ); + } +#endif +#else SetModeIndex( st, st->bits_frame_nominal * FRAMES_PER_SEC, element_mode, MCT_flag ); + st->sba_br_sw_while_no_data = 0; +#endif // IVAS_FLOAT_FIXED } else if ( ivas_format == SBA_FORMAT && st->core_brate == FRAME_NO_DATA && element_brate != last_element_brate ) { @@ -2136,9 +2199,58 @@ ivas_error pre_proc_front_ivas_fx( /* Switch to ACELP for non-harmonic transient signals */ else if ( ( ( element_mode >= IVAS_CPE_DFT && element_brate <= IVAS_16k4 ) || ( element_mode == IVAS_SCE && element_brate < SCE_SMC_THR ) ) && ( loc_harm[0] != 1 ) && smc_dec == MUSIC ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_multi_harm_limit; + Word16 exp_multi_harm_limit = 0; + f2me_16( st->hNoiseEst->multi_harm_limit, &st->hNoiseEst->multi_harm_limit_fx, &exp_multi_harm_limit ); + Q_multi_harm_limit = 15 - exp_multi_harm_limit; + + Word16 Q_cor_map = Q_factor_arr( st->hNoiseEst->cor_map, L_FFT / 2 ); + floatToFixed_arr( st->hNoiseEst->cor_map, st->hNoiseEst->cor_map_fx, Q_cor_map, L_FFT / 2 ); + + Word16 q1 = Q_factor_arr( st->hTranDet->subblockEnergies.subblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY ); + Word16 q2 = Q_factor_arr( st->hTranDet->subblockEnergies.accSubblockNrg_flt, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + + st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg = float_to_fix16( st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg_flt, Q15 ); + floatToFixed_arrL( st->hTranDet->subblockEnergies.subblockNrg_flt, st->hTranDet->subblockEnergies.subblockNrg, q1, NSUBBLOCKS + MAX_TD_DELAY ); + floatToFixed_arrL( st->hTranDet->subblockEnergies.accSubblockNrg_flt, st->hTranDet->subblockEnergies.accSubblockNrg, q2, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + st->hTranDet->subblockEnergies.subblockNrg_e = 31 - q1; + st->hTranDet->subblockEnergies.accSubblockNrg_e = 31 - q2; + +#endif + IF( EQ_16( element_mode, IVAS_SCE ) ) + { + if ( transient_analysis_ivas_fx( st->hTranDet, st->hNoiseEst->cor_map_fx, Q_cor_map, st->hNoiseEst->multi_harm_limit_fx, Q_multi_harm_limit ) ) + { + smc_dec = SPEECH; + move16(); + } + } + ELSE IF( EQ_16( element_mode, IVAS_CPE_DFT ) ) + { + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + test(); + if ( smc_dec != SPEECH && transient_analysis_ivas_fx( hCPE->hCoreCoder[i]->hTranDet, st->hNoiseEst->cor_map_fx, Q_cor_map, st->hNoiseEst->multi_harm_limit_fx, Q_multi_harm_limit ) ) + { + smc_dec = SPEECH; /* overwrite initial music decision, initial SPEECH_MUSIC never changed */ + move16(); + } + } + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( st->hNoiseEst->cor_map_fx, st->hNoiseEst->cor_map, Q_cor_map, L_FFT / 2 ); + fixedToFloat_arrL( st->hTranDet->subblockEnergies.subblockNrg, st->hTranDet->subblockEnergies.subblockNrg_flt, q1, NSUBBLOCKS + MAX_TD_DELAY ); + fixedToFloat_arrL( st->hTranDet->subblockEnergies.accSubblockNrg, st->hTranDet->subblockEnergies.accSubblockNrg_flt, q2, NSUBBLOCKS + MAX_TD_DELAY + 1 ); + st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg_flt = fix16_to_float( st->hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg, Q15 ); +#endif +#else if ( element_mode == IVAS_SCE ) { if ( transient_analysis( st->hTranDet, st->hNoiseEst->cor_map, st->hNoiseEst->multi_harm_limit ) ) + { smc_dec = SPEECH; } @@ -2153,10 +2265,69 @@ ivas_error pre_proc_front_ivas_fx( } } } +#endif + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS +#define ATT_SEG_LEN ( L_FRAME / ATT_NSEG ) + Word16 relE_fx; + relE_fx = float_to_fix16( *relE, Q8 ); + Etot16_fx = float_to_fix16( Etot, Q8 ); + // Q_new = s_min(Q_factor_arr( inp_12k8, ATT_NSEG * ATT_SEG_LEN ), Q_factor_arr( st->Bin_E, 256 )) - 1; + Q_new = 0; /* Dynamic Q_new used above causes overflow issues */ + for ( int k = 0; k < ATT_NSEG * ATT_SEG_LEN; k++ ) + { + if ( fabs( inp_12k8[k] ) > 32768.0f ) + { + Q_new = -1; + break; + } } + floatToFixed_arr( inp_12k8, inp_12k8_fx, Q_new, ATT_NSEG * ATT_SEG_LEN ); + floatToFixed_arrL( st->Bin_E, st->Bin_E_fx, Q_new + Q_SCALE - 2, TOD_NSPEC ); + floatToFixed_arrL( st->hSpMusClas->tod_lt_Bin_E, st->hSpMusClas->tod_lt_Bin_E_fx, Q_new + Q_SCALE - 2, TOD_NSPEC ); + floatToFixed_arr( S_map, S_map_fx, Q7, L_FFT / 2 ); + floatToFixed_arr( st->hSpMusClas->gsc_lt_diff_etot, st->hSpMusClas->gsc_lt_diff_etot_fx, Q8, MAX_LT ); + st->hSpMusClas->gsc_mem_etot_fx = float_to_fix16( st->hSpMusClas->gsc_mem_etot, Q8 ); + floatToFixed_arr( st->hSpMusClas->gsc_thres, st->hSpMusClas->gsc_thres_fx, Q11, 4 ); + st->old_corr_fx = float_to_fix16( st->old_corr, Q15 ); + floatToFixed_arr( st->hSpMusClas->var_cor_t, st->hSpMusClas->var_cor_t_fx, Q11, VAR_COR_LEN ); + floatToFixed_arrL( st->hSpMusClas->finc_prev, st->hSpMusClas->finc_prev_fx, 2 * Q_new, ATT_NSEG ); + st->hSpMusClas->lt_finc_fx = floatToFixed( st->hSpMusClas->lt_finc, 2 * Q_new ); + st->lp_noise_fx = float_to_fix16( st->lp_noise, Q8 ); + st->hSpMusClas->wdlp_0_95_sp_fx = float_to_fix16( st->hSpMusClas->wdlp_0_95_sp, Q8 ); + st->hSpMusClas->ener_RAT_fx = float_to_fix16( st->hSpMusClas->ener_RAT, Q8 ); + st->hSpMusClas->lt_dec_thres_fx = float_to_fix16( st->hSpMusClas->lt_dec_thres, Q9 ); + st->hSpMusClas->tod_S_mass_lt_fx = float_to_fix( st->hSpMusClas->tod_S_mass_lt, Q22 ); + st->hSpMusClas->tod_S_mass_prev_fx = float_to_fix( st->hSpMusClas->tod_S_mass_prev, Q22 ); + st->hSpMusClas->tod_thr_lt_fx = float_to_fix( st->hSpMusClas->tod_thr_lt, Q22 ); + floatToFixed_arrL( st->hSpMusClas->tod_S_map_lt, st->hSpMusClas->tod_S_map_lt_fx, Q22, TOD_NSPEC ); + st->hSpMusClas->tod_weight_fx = float_to_fix16( st->hSpMusClas->tod_weight, Q15 ); + st->hSpMusClas->mold_corr_fx = float_to_fix16( st->hSpMusClas->mold_corr, Q15 ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + /* 2nd stage speech/music classification (ACELP/GSC/TCX core selection) */ + ivas_smc_mode_selection_fx( st, element_brate, smc_dec, relE_fx, Etot16_fx, attack_flag, inp_12k8_fx, Q_new, S_map_fx, flag_spitch ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( st->hSpMusClas->gsc_lt_diff_etot_fx, st->hSpMusClas->gsc_lt_diff_etot, Q8, MAX_LT ); + st->hSpMusClas->gsc_mem_etot = fix16_to_float( st->hSpMusClas->gsc_mem_etot_fx, Q8 ); + fixedToFloat_arrL( st->hSpMusClas->finc_prev_fx, st->hSpMusClas->finc_prev, 2 * Q_new, ATT_NSEG ); + st->hSpMusClas->lt_finc = fixedToFloat( st->hSpMusClas->lt_finc_fx, 2 * Q_new ); + fixedToFloat_arrL( st->hSpMusClas->tod_lt_Bin_E_fx, st->hSpMusClas->tod_lt_Bin_E, Q_new + Q_SCALE - 2, TOD_NSPEC ); + st->hSpMusClas->mold_corr = fix16_to_float( st->hSpMusClas->mold_corr_fx, Q15 ); + st->hSpMusClas->tod_S_mass_lt = fix_to_float( st->hSpMusClas->tod_S_mass_lt_fx, Q22 ); + st->hSpMusClas->tod_S_mass_prev = fix_to_float( st->hSpMusClas->tod_S_mass_prev_fx, Q22 ); + st->hSpMusClas->tod_thr_lt = fix_to_float( st->hSpMusClas->tod_thr_lt_fx, Q22 ); + fixedToFloat_arrL( st->hSpMusClas->tod_S_map_lt_fx, st->hSpMusClas->tod_S_map_lt, Q22, TOD_NSPEC ); + st->hSpMusClas->tod_weight = fix16_to_float( st->hSpMusClas->tod_weight_fx, Q15 ); + fixedToFloat_arr( st->hSpMusClas->var_cor_t_fx, st->hSpMusClas->var_cor_t, Q11, VAR_COR_LEN ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#else /* 2nd stage speech/music classification (ACELP/GSC/TCX core selection) */ ivas_smc_mode_selection( st, element_brate, smc_dec, *relE, Etot, attack_flag, inp_12k8, S_map, flag_spitch ); +#endif // IVAS_FLOAT_FIXED } /*----------------------------------------------------------------* @@ -2176,9 +2347,7 @@ ivas_error pre_proc_front_ivas_fx( mvr2r( &old_inp_12k8[L_FRAME], st->old_inp_12k8, L_INP_MEM ); #ifdef IVAS_FLOAT_FIXED - free( signal_in_fx - ( input_Fs / 50 ) ); free( enerBuffer_fx ); - free( old_inp_12k8_fx ); free( old_inp_16k_fx ); free( mem_decim_dummy_fx ); free( temp1F_icatdmResampBuf_fx ); @@ -2256,24 +2425,25 @@ static void calculate_energy_buffer_fx( * * calculate DFT-based energies *--------------------------------------------------------------------*/ - -static void calculate_energy_buffer( - CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ - float enerBuffer_dft[], /* o : energy buffer */ - const int16_t no_channels, /* i : no. of used CLDFB channels */ - const int32_t input_Fs /* i : input sampling rate */ -) -{ #ifdef IVAS_FLOAT_FIXED - float *pDFT_DMX; // to be removed +static void calculate_energy_buffer_ivas_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word32 enerBuffer_dft_fx[], /* o : energy buffer() */ + const Word16 no_channels, /* i : no. of used CLDFB channels */ + const Word32 input_Fs, /* i : input sampling rate */ + Word16 *enerBuffer_dft_e ) +{ Word16 i, j; - Word64 enerBuffer_dft_fx[CLDFB_NO_CHANNELS_MAX]; // to be removed Word64 nrg_DMX_fx[CLDFB_NO_CHANNELS_MAX]; Word64 *p_nrg_DMX_fx; - Word32 *pDFT_DMX_fx; + Word32 *pDFT_DMX_fx; /*q_DFT_DMX_fx*/ Word32 chan_width_bins_fx; Word16 band_res_dft_fx, chan_width_f_fx, start, stop; + Word16 norm_nrg_DMX_fx; + Word64 max_abs_nrg_DMX_fx; + Flag overflow = 0; + max_abs_nrg_DMX_fx = 0; Word16 temp_q1 = norm_l( input_Fs ) - 1; Word16 temp_q2 = norm_s( hCPE->hStereoDft->NFFT ); @@ -2281,55 +2451,53 @@ static void calculate_energy_buffer( /* chan_width_f = 24000.f / CLDFB_NO_CHANNELS_MAX; */ chan_width_f_fx = 24000 / CLDFB_NO_CHANNELS_MAX; chan_width_bins_fx = L_shl( (Word32) div_s( chan_width_f_fx, band_res_dft_fx ), ( sub( temp_q1, temp_q2 ) ) ); // Q16 + set64_fx( nrg_DMX_fx, 0, CLDFB_NO_CHANNELS_MAX ); - pDFT_DMX = hCPE->hStereoDft->DFT[0]; // to be removed start = 1; - pDFT_DMX_fx = hCPE->hStereoDft->DFT_fx[0]; + pDFT_DMX_fx = hCPE->hStereoDft->DFT_fx[0]; /*q_DFT_DMX_fx = 31-hCPE->hStereoDft->DFT_fx_e[0]*/ p_nrg_DMX_fx = nrg_DMX_fx; - pDFT_DMX_fx[0] = (Word32) ( pDFT_DMX[0] * ONE_IN_Q11 ); + *p_nrg_DMX_fx = Mpy_32_32( pDFT_DMX_fx[0], pDFT_DMX_fx[0] ); /*2 * q_DFT_DMX_fx -31 */ FOR( i = 0; i < no_channels; i++ ) { - stop = (Word16) ( L_add( Mpy_32_16_1( chan_width_bins_fx, add( i, 1 ) ), 1 ) >> 1 ); - nrg_DMX_fx[i] = 0; + stop = extract_l( L_shr( L_add( Mpy_32_16_1( chan_width_bins_fx, add( i, 1 ) ), 1 ), 1 ) ); FOR( j = start; j < stop; j++ ) { - pDFT_DMX_fx[2 * j] = (Word32) ( pDFT_DMX[2 * j] * ONE_IN_Q11 ); - pDFT_DMX_fx[2 * j + 1] = (Word32) ( pDFT_DMX[2 * j + 1] * ONE_IN_Q11 ); - } - start = stop; - } - start = 1; - - *p_nrg_DMX_fx = Mpy_32_32( pDFT_DMX_fx[0], pDFT_DMX_fx[0] ); - - FOR( i = 0; i < no_channels; i++ ) - { - stop = (Word16) ( L_add( Mpy_32_16_1( chan_width_bins_fx, add( i, 1 ) ), 1 ) >> 1 ); - FOR( j = start; j < stop; j++ ) - { - *p_nrg_DMX_fx = W_add( *p_nrg_DMX_fx, Mpy_32_32( pDFT_DMX_fx[2 * j], pDFT_DMX_fx[2 * j] ) ); + *p_nrg_DMX_fx = W_add( *p_nrg_DMX_fx, Mpy_32_32( pDFT_DMX_fx[2 * j], pDFT_DMX_fx[2 * j] ) ); /*2 * q_DFT_DMX_fx -31 */ *p_nrg_DMX_fx = W_add( *p_nrg_DMX_fx, Mpy_32_32( pDFT_DMX_fx[2 * j + 1], pDFT_DMX_fx[2 * j + 1] ) ); - // Q(-9) = Q11 + Q11 - Q31 + // 2 * DFT_fx_e } + if ( GT_64( W_abs( *p_nrg_DMX_fx ), max_abs_nrg_DMX_fx ) ) + max_abs_nrg_DMX_fx = W_abs( *p_nrg_DMX_fx ); start = stop; + move16(); p_nrg_DMX_fx++; } + norm_nrg_DMX_fx = W_norm( max_abs_nrg_DMX_fx ); FOR( i = 0; i < no_channels; i++ ) /* Consider only used channels, dependent on Fs */ { - enerBuffer_dft_fx[i] = nrg_DMX_fx[i] / 3; - enerBuffer_dft[i] = (float) enerBuffer_dft_fx[i] * ( 1 << 9 ); // Q(-9) adjustment, to be removed + enerBuffer_dft_fx[i] = W_extract_h( W_shl_o( nrg_DMX_fx[i], norm_nrg_DMX_fx, &overflow ) ) / 3; /*q_enerBuffer_dft_fx=2 * q_DFT_DMX_fx -31+ norm_nrg_DMX_fx -32*/ } + *enerBuffer_dft_e = sub( add( 32, shl( hCPE->hStereoDft->DFT_fx_e[0], 1 ) ), norm_nrg_DMX_fx ); /*31-q_enerBuffer_dft_fx*/ /* Set remaining entries of enerBuffer to zero */ FOR( ; i < CLDFB_NO_CHANNELS_MAX; i++ ) { - enerBuffer_dft[i] = 0.f; + enerBuffer_dft_fx[i] = 0; } + return; +} #else +static void calculate_energy_buffer( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + float enerBuffer_dft[], /* o : energy buffer */ + const int16_t no_channels, /* i : no. of used CLDFB channels */ + const int32_t input_Fs /* i : input sampling rate */ +) +{ int16_t i, j; float *pDFT_DMX, *p_nrg_DMX; float nrg_DMX[CLDFB_NO_CHANNELS_MAX]; @@ -2368,6 +2536,6 @@ static void calculate_energy_buffer( { enerBuffer_dft[i] = 0.f; } -#endif return; } +#endif diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index 1f26d7586..b1d026f59 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -84,8 +84,10 @@ ivas_error ivas_cpe_enc( float old_inp_16k[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ #endif #ifdef IVAS_FLOAT_FIXED - Word32 old_inp_12k8_fx[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ - Word32 old_inp_16k_fx[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ + Word32 old_inp_12k8_fx[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + Word16 old_inp_12k8_16fx[CPE_CHANNELS][L_INP_12k8]; /* buffer of input signal @ 12k8 */ + Word32 old_inp_16k_fx[CPE_CHANNELS][L_INP]; /* buffer of input signal @ 16kHz */ + Word16 fft_buff_fx[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ #endif float ener[CPE_CHANNELS]; /* residual energy from Levinson-Durbin */ float relE[CPE_CHANNELS]; /* frame relative energy */ @@ -465,7 +467,10 @@ ivas_error ivas_cpe_enc( /*flt2fix: dft_td_itd*/ - f2me_buf( hCPE->hStereoDft->xspec_smooth, hCPE->hStereoDft->xspec_smooth_fx, &hCPE->hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); + for ( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + f2me( hCPE->hStereoDft->xspec_smooth[i], &hCPE->hStereoDft->xspec_smooth_fx[i], &hCPE->hStereoDft->xspec_smooth_fx_e[i] ); + } f2me_buf( hCPE->hStereoDft->Spd_L_smooth, hCPE->hStereoDft->Spd_L_smooth_fx, &hCPE->hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); f2me_buf( hCPE->hStereoDft->Spd_R_smooth, hCPE->hStereoDft->Spd_R_smooth_fx, &hCPE->hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); floatToFixed_arrL( hCPE->hStereoDft->hItd->itd, hCPE->hStereoDft->hItd->itd_fx, 16, STEREO_DFT_ENC_DFT_NB ); @@ -647,7 +652,10 @@ ivas_error ivas_cpe_enc( /*fix2flt: dft_td_itd*/ - me2f_buf( hCPE->hStereoDft->xspec_smooth_fx, hCPE->hStereoDft->xspec_smooth_fx_e, hCPE->hStereoDft->xspec_smooth, STEREO_DFT_N_32k_ENC ); + for ( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + hCPE->hStereoDft->xspec_smooth[i] = me2f( hCPE->hStereoDft->xspec_smooth_fx[i], hCPE->hStereoDft->xspec_smooth_fx_e[i] ); + } me2f_buf( hCPE->hStereoDft->Spd_L_smooth_fx, hCPE->hStereoDft->Spd_L_smooth_fx_e, hCPE->hStereoDft->Spd_L_smooth, STEREO_DFT_N_32k_ENC / 2 ); me2f_buf( hCPE->hStereoDft->Spd_R_smooth_fx, hCPE->hStereoDft->Spd_R_smooth_fx_e, hCPE->hStereoDft->Spd_R_smooth, STEREO_DFT_N_32k_ENC / 2 ); fixedToFloat_arrL( hCPE->hStereoDft->hItd->itd_fx, hCPE->hStereoDft->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); @@ -738,10 +746,10 @@ ivas_error ivas_cpe_enc( for ( n = 0; n < n_CoreChannels; n++ ) { #ifdef IVAS_FLOAT_FIXED - error = pre_proc_front_ivas_fx( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8[n], old_inp_16k[n], + error = pre_proc_front_ivas_fx( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8_16fx[n], old_inp_12k8[n], old_inp_16k[n], &ener[n], &relE[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], &vad_hover_flag[n], &attack_flag[n], realBuffer[n], imagBuffer[n], old_wsp[n], pitch_fr[n], voicing_fr[n], &loc_harm[n], &cor_map_sum[n], &vad_flag_dtx[n], enerBuffer[n], - fft_buff[n], A[0], lsp_new[0], currFlatness[n], tdm_ratio_idx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, band_energies_LR, 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, 0, 0, ivas_format, st_ivas->hMCT != NULL, ivas_total_brate ); + fft_buff[n], fft_buff_fx[n], A[0], lsp_new[0], currFlatness[n], tdm_ratio_idx, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, band_energies_LR, 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, 0, 0, ivas_format, st_ivas->hMCT != NULL, ivas_total_brate ); #else error = pre_proc_front_ivas( NULL, hCPE, hCPE->element_brate, nb_bits_metadata, input_frame, n, old_inp_12k8[n], old_inp_16k[n], &ener[n], &relE[n], A[n], Aw[n], epsP[n], lsp_new[n], lsp_mid[n], &vad_hover_flag[n], &attack_flag[n], @@ -889,11 +897,13 @@ ivas_error ivas_cpe_enc( *----------------------------------------------------------------*/ cpe_brate = 0; - if ( hCPE->element_mode == IVAS_CPE_DFT ) + move16(); + IF( EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) { - if ( hEncoderConfig->Opt_DTX_ON ) + IF( hEncoderConfig->Opt_DTX_ON ) { - if ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) + test(); + IF( EQ_32( sts[0]->core_brate, SID_2k40 ) || EQ_32( sts[0]->core_brate, FRAME_NO_DATA ) ) { /* Reconfigure DFT Stereo for inactive frames */ #ifndef IVAS_FLOAT_FIXED @@ -918,7 +928,7 @@ ivas_error ivas_cpe_enc( stereo_dft_cng_side_gain_fx( hCPE->hStereoDft, hCPE->hStereoCng, sts[0]->core_brate, sts[0]->last_core_brate, sts[0]->bwidth ); } - else + ELSE { stereo_cng_upd_counters_fx( hCPE->hStereoCng, hCPE->element_mode, hCPE->hStereoDft->nbands, hCPE->hStereoDft->sidSideGain_fx, sts[0]->hTdCngEnc->burst_ho_cnt, &hCPE->hStereoDft->coh_fade_counter ); } @@ -926,19 +936,43 @@ ivas_error ivas_cpe_enc( /* Write stereo bitstream */ cpe_brate = st_ivas->hCPE[0]->element_brate; + move16(); /* DFT stereo side bits */ - if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && cpe_brate < MASA_STEREO_MIN_BITRATE && sts[0]->core_brate != SID_2k40 && sts[0]->core_brate != FRAME_NO_DATA ) + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && LT_32( cpe_brate, MASA_STEREO_MIN_BITRATE ) && NE_32( sts[0]->core_brate, SID_2k40 ) && NE_32( sts[0]->core_brate, FRAME_NO_DATA ) ) { nb_bits = 0; /* Only mono downmix is transmitted in this case */ + move16(); } - else if ( ( ivas_format == MASA_FORMAT || ivas_format == MASA_ISM_FORMAT ) && ( sts[0]->core_brate == SID_2k40 || sts[0]->core_brate == FRAME_NO_DATA ) ) + ELSE IF( ( EQ_16( ivas_format, MASA_FORMAT ) || EQ_16( ivas_format, MASA_ISM_FORMAT ) ) && ( EQ_32( sts[0]->core_brate, SID_2k40 ) || EQ_32( sts[0]->core_brate, FRAME_NO_DATA ) ) ) { nb_bits = hCPE->hMetaData->nb_bits_tot; + move16(); } - else + ELSE { - stereo_dft_enc_write_BS( hCPE, &nb_bits ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*flt2fix: dft_td_itd*/ + for ( Word16 i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + f2me( hCPE->hStereoDft->xspec_smooth[i], &hCPE->hStereoDft->xspec_smooth_fx[i], &hCPE->hStereoDft->xspec_smooth_fx_e[i] ); + } +#endif + stereo_dft_enc_write_BS_fx( hCPE, &nb_bits ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /*fix2flt: dft_td_itd*/ + for ( Word16 i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) + { + hCPE->hStereoDft->xspec_smooth[i] = me2f( hCPE->hStereoDft->xspec_smooth_fx[i], hCPE->hStereoDft->xspec_smooth_fx_e[i] ); + } +#endif } /* Residual coding in MDCT domain */ @@ -954,7 +988,13 @@ ivas_error ivas_cpe_enc( } } - stereo_dft_enc_res( hCPE->hStereoDft, old_inp_12k8[1] + L_INP_MEM - STEREO_DFT_OVL_8k, hCPE->hMetaData, &nb_bits, max_bits ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < CPE_CHANNELS; i++ ) + { + floatToFixed_arrL( old_inp_12k8[i], old_inp_12k8_fx[i], Q16, L_INP_12k8 ); + } +#endif + stereo_dft_enc_res_fx( hCPE->hStereoDft, old_inp_12k8_fx[1] + L_INP_MEM - STEREO_DFT_OVL_8k, hCPE->hMetaData, &nb_bits, max_bits ); } if ( sts[0]->core_brate == FRAME_NO_DATA || sts[0]->core_brate == SID_2k40 ) diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index d56ae05d0..714a1c62d 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -433,6 +433,7 @@ ivas_error ivas_ism_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8] = { 0 }; /* buffer of input signal @ 12k8 */ float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP] = { 0 }; /* buffer of input signal @ 16kHz */ + Word16 old_inp_12k8_fx[MAX_NUM_OBJECTS][1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ #else float old_inp_12k8[MAX_NUM_OBJECTS][1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ float old_inp_16k[MAX_NUM_OBJECTS][1][L_INP]; /* buffer of input signal @ 16kHz */ @@ -465,6 +466,7 @@ ivas_error ivas_ism_enc( float enerBuffer[MAX_NUM_OBJECTS][1][CLDFB_NO_CHANNELS_MAX]; /* energy buffer */ float currFlatness[1]; /* flatness parameter */ float fft_buff[MAX_NUM_OBJECTS][1][2 * L_FFT]; /* FFT buffer */ + Word16 fft_buff_fx[MAX_NUM_OBJECTS][1][2 * L_FFT]; /* FFT buffer */ float fr_bands[1][2 * NB_BANDS]; /* energy in frequency bands */ float Etot_LR[1]; /* total energy; correlation shift */ float lf_E[1][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ @@ -568,10 +570,10 @@ ivas_error ivas_ism_enc( /*----------------------------------------------------------------* * Front Pre-processing *----------------------------------------------------------------*/ - error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata[sce_id], input_frame, 0, old_inp_12k8[sce_id][0], old_inp_16k[sce_id][0], + error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata[sce_id], input_frame, 0, old_inp_12k8_fx[sce_id][0], old_inp_12k8[sce_id][0], old_inp_16k[sce_id][0], &ener[sce_id][0], &relE[sce_id][0], A[sce_id][0], Aw[sce_id][0], epsP[sce_id][0], lsp_new[sce_id][0], lsp_mid[sce_id][0], &vad_hover_flag[sce_id][0], &attack_flag[sce_id][0], realBuffer[sce_id][0], imagBuffer[sce_id][0], old_wsp[sce_id][0], pitch_fr[sce_id][0], voicing_fr[sce_id][0], &loc_harm[sce_id][0], &cor_map_sum[sce_id][0], &vad_flag_dtx[sce_id][0], enerBuffer[sce_id][0], - fft_buff[sce_id][0], A[sce_id][0], lsp_new[sce_id][0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, 0, 0, 0, 0, ISM_FORMAT, 0, st_ivas->hEncoderConfig->ivas_total_brate ); + fft_buff[sce_id][0], fft_buff_fx[sce_id][0], A[sce_id][0], lsp_new[sce_id][0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, 0, 0, 0, 0, ISM_FORMAT, 0, st_ivas->hEncoderConfig->ivas_total_brate ); IF( NE_32( error, IVAS_ERR_OK ) ) { diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index afba3cc1a..4aea681d7 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -1597,6 +1597,7 @@ void enc_prm_igf_mdct( * MCT preprocessing up to whitening the core spectrum *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED void ivas_mdct_core_whitening_enc( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ @@ -1634,6 +1635,8 @@ void ivas_mdct_core_whitening_enc( float scf[CPE_CHANNELS][NB_DIV][M]; float scf_q[CPE_CHANNELS][NB_DIV][M]; #ifdef IVAS_FLOAT_FIXED + Word16 old_wsp_fx[CPE_CHANNELS][L_WSP]; + Word16 q_fac; Word32 scf_fx[CPE_CHANNELS][NB_DIV][M]; Word32 scf_q_fx[CPE_CHANNELS][NB_DIV][M]; #endif @@ -1759,8 +1762,27 @@ void ivas_mdct_core_whitening_enc( SetCurrentPsychParams( st->core, 0, st->hTcxCfg ); /* tcx ltp analysis on the 12.8kHz weighted speech, saves preproc resampling to sr_core */ - tcx_ltp_encode( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + floatToFixed_arr( st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, st->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, NSUBBLOCKS + MAX_TD_DELAY ); + hTcxEnc->tcxltp_gain_past = float_to_fix16( hTcxEnc->tcxltp_gain_past_flt, Q15 ); + hTcxEnc->tcxltp_norm_corr_past = float_to_fix16( hTcxEnc->tcxltp_norm_corr_past_flt, Q15 ); + q_fac = Q_factor_arr( old_wsp[ch], L_WSP ); + floatToFixed_arr( old_wsp[ch], old_wsp_fx[ch], q_fac, L_WSP ); +#endif + tcx_ltp_encode_ivas_fx( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp_fx[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp_fx[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( old_wsp_fx[ch], old_wsp[ch], q_fac, L_WSP ); + hTcxEnc->tcxltp_gain_past_flt = fix16_to_float( hTcxEnc->tcxltp_gain_past, Q15 ); + hTcxEnc->tcxltp_gain_flt = fix16_to_float( hTcxEnc->tcxltp_gain, Q15 ); + hTcxEnc->tcxltp_norm_corr_past_flt = fix16_to_float( hTcxEnc->tcxltp_norm_corr_past, Q15 ); +#endif +#else + tcx_ltp_encode( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); +#endif core_signal_analysis_high_bitrate( new_samples[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, mdst_spectrum[ch], tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0 ); /* BWD in MDCT domain */ @@ -2762,6 +2784,632 @@ void ivas_mdct_core_whitening_enc( pop_wmops(); return; } +#else +void ivas_mdct_core_whitening_enc( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + float new_samples[CPE_CHANNELS][L_INP], /* i : new samples */ + float old_wsp[CPE_CHANNELS][L_WSP], /* i : 12.8kHz weighted speech (for LTP */ + float pitch_buf[CPE_CHANNELS][NB_SUBFR16k], /* o : floating pitch for each subframe */ + float *mdst_spectrum_long[CPE_CHANNELS], /* o : buffer for MDST spectrum */ + int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* o : buffer TNS bits */ + float *orig_spectrum_long[CPE_CHANNELS], /* o : origingal spectrum w/o whitening */ + int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* o : number of tns parameters put into prm */ + int16_t p_param[CPE_CHANNELS][NB_DIV], /* o : pointer to the parameter table */ + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const int16_t mct_on, /* i : flag mct block (1) or stereo (0) */ + const int16_t nChannels /* i : total number of coded channels */ +) +{ + int16_t n, ch, nSubframes, L_subframe, L_subframeTCX, tcx_subframe_coded_lines; + float A_q[CPE_CHANNELS][NB_DIV][M + 1]; + int16_t sns_vq_indices[CPE_CHANNELS * NB_DIV * SNS_MSVQ_NSTAGES_TCX10]; + int16_t sns_stereo_mode[NB_DIV]; + int16_t idx; + int16_t param_lpc[CPE_CHANNELS][NPRM_LPC_NEW]; + int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; + int16_t ltpBits[CPE_CHANNELS]; + int16_t i, T_op[CPE_CHANNELS][3]; + float *orig_spectrum[CPE_CHANNELS][NB_DIV]; /* Pointers to MDCT output for a short block (L/R) */ + float temp_buffer[15 * L_FRAME48k / 8]; + float *windowedSignal[CPE_CHANNELS]; + float *powerSpec = orig_spectrum_long[0]; + float *mdst_spectrum[CPE_CHANNELS][NB_DIV]; + float nrg; + Encoder_State *st, **sts; + float scf[CPE_CHANNELS][NB_DIV][M]; + float scf_q[CPE_CHANNELS][NB_DIV][M]; + float chE[2], chE_tot; + int8_t sns_low_br_mode; + int16_t nbits_start_sns; + int16_t num_sns; + int8_t skipped_first_channel; + int16_t zero_side_flag[NB_DIV]; + + push_wmops( "mdct_core_whitening" ); + + /*--------------------------------------------------------------* + * Initialization + *---------------------------------------------------------------*/ + + sts = hCPE->hCoreCoder; + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + stereo_tcx_init_enc( sts[ch] ); + + set_s( tnsSize[ch], 0, 2 ); + set_s( tnsBits[ch], 0, 2 ); + ltpBits[ch] = 0; + + for ( i = 0; i < 3; i++ ) + { + T_op[ch][i] = sts[ch]->pitch[i]; + + /* check minimum pitch for quantization */ + if ( T_op[ch][i] < PIT_MIN_SHORTER ) + { + T_op[ch][i] *= 2; + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + orig_spectrum[ch][0] = orig_spectrum_long[ch]; + orig_spectrum[ch][1] = orig_spectrum_long[ch] + N_TCX10_MAX; + mdst_spectrum[ch][0] = mdst_spectrum_long[ch]; + mdst_spectrum[ch][1] = mdst_spectrum_long[ch] + N_TCX10_MAX; + } + + windowedSignal[0] = orig_spectrum_long[0]; /* NOTE temporarily available */ + windowedSignal[1] = temp_buffer; /* orig_spectrum_long isn't long enough */ + + /*--------------------------------------------------------------* + * TCX20/TCX10 switching decision + *---------------------------------------------------------------*/ + + if ( mct_on ) + { + sts[0]->hTcxEnc->tfm_mem = sts[1]->hTcxEnc->tfm_mem = sqrtf( 0.5f * ( sts[0]->hTcxEnc->tfm_mem * sts[0]->hTcxEnc->tfm_mem + sts[1]->hTcxEnc->tfm_mem * sts[1]->hTcxEnc->tfm_mem ) ); /* RMS */ + sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt = sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt = 0.5f * ( sts[0]->hTcxEnc->tcxltp_norm_corr_past_flt + sts[1]->hTcxEnc->tcxltp_norm_corr_past_flt ); + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + SetTCXModeInfo( st, st->hTranDet, &st->hTcxCfg->tcx_curr_overlap_mode ); + } + } + + sts[0]->core = sts[0]->hTcxEnc->tcxMode; + sts[1]->core = sts[1]->hTcxEnc->tcxMode; + + /*--------------------------------------------------------------* + * Core Signal Analysis: MDCT, TNS + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + continue; + } + SetCurrentPsychParams( st->core, 0, st->hTcxCfg ); + + /* tcx ltp analysis on the 12.8kHz weighted speech, saves preproc resampling to sr_core */ + tcx_ltp_encode( st, st->hTcxEnc->tcxMode, L_FRAME, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, NULL, old_wsp[ch] + L_WSP_MEM + L_LOOK_12k8, T_op[ch], ¶m_core[ch][1 + NOISE_FILL_RANGES], <pBits[ch], NULL, 0, IVAS_CPE_MDCT ); + + core_signal_analysis_high_bitrate( new_samples[ch] + L_INP_MEM, T_op[ch], NULL, NULL, st, mdst_spectrum[ch], tnsSize[ch], tnsBits[ch], param_core[ch], <pBits[ch], windowedSignal[ch], st->L_frame, st->hTcxEnc->L_frameTCX, hCPE->last_element_mode, 0 ); + + /* BWD in MDCT domain */ + if ( st->hTcxCfg->tcx_last_overlap_mode != TRANSITION_OVERLAP ) + { + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + bw_detect( st, NULL, st->hTcxEnc->spectrum[n], NULL, MC_FORMAT /*just cannot be ISM_FORMAT*/, mct_on ); + + if ( nSubframes == NB_DIV && n == 0 ) + { + st->last_input_bwidth = st->input_bwidth; + } + } + } + + if ( st->last_core == ACELP_CORE ) /* reset past kernel info */ + { + st->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + st->hTcxEnc->kernel_symmetry_past = 0; + } + } + + /*--------------------------------------------------------------* + * Transform Kernel Switching, Stereo Pre-Processing, and TNS + *---------------------------------------------------------------*/ + + sts[0]->hTcxEnc->fUseTns[1] = 0; + + if ( sts[0]->element_brate < IVAS_80k && sts[0]->core == sts[1]->core && sts[0]->element_mode == IVAS_CPE_MDCT && !mct_on && !hCPE->hStereoMdct->isSBAStereoMode ) + { + int16_t nSampCore; + int32_t totalRate; + TCX_ENC_HANDLE hTcxEnc0, hTcxEnc1; + + nSampCore = ( sts[0]->igf ) ? max( sts[0]->hIGFEnc->infoStartLine, sts[1]->hIGFEnc->infoStartLine ) : 0; + totalRate = sts[0]->element_brate; + hTcxEnc0 = sts[0]->hTcxEnc; + hTcxEnc1 = sts[1]->hTcxEnc; + + init_tcx_enc_info( sts[0], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); + + if ( nSampCore == 0 ) + { + nSampCore = tcx_subframe_coded_lines; + } + + nrg = 0.25f * ( hTcxEnc0->tcxltp_norm_corr_past_flt + hTcxEnc0->tcxltp_norm_corr_mem_flt + /* tcxltp_norm_corr_past already contains the */ + hTcxEnc1->tcxltp_norm_corr_past_flt + hTcxEnc1->tcxltp_norm_corr_mem_flt ); /* normalized correlation of the current frame */ + + L_subframe = max( 512, L_subframe ); + nSubframes = ( hTcxEnc0->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( hTcxEnc0->transform_type[n] == hTcxEnc1->transform_type[n] ) + { + const int16_t switchKernel = /* these 4 transform types can be applied: 0 = MDCT-IV, 1 = MDST-II, 2 = MDCT-II, 3 = MDST-IV */ + kernel_switch_detect( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / nSubframes, + L_subframeTCX / nSubframes, hTcxEnc0->transform_type[n], &hTcxEnc0->kernel_switch_corr_past_flt, ( totalRate * L_subframe ) / nSubframes ); + if ( switchKernel ) /* apply MDST-IV coding in one of the channels */ + { + hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 3 : 1 ) - max( 0, switchKernel ); + hTcxEnc1->kernel_type[n] = ( hTcxEnc1->kernel_symmetry_past ? 2 : 0 ) + max( 0, switchKernel ); + } + else /* switchKernel == 0, switch back to MDCT-IV in both channels */ + { + hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 2 : 0 ); + hTcxEnc1->kernel_type[n] = ( hTcxEnc1->kernel_symmetry_past ? 2 : 0 ); + } + } + else + { + hTcxEnc0->kernel_switch_corr_past_flt = 0.f; /* don't update the kernel switching state, postpone it to when data is available */ + hTcxEnc0->kernel_type[n] = ( hTcxEnc0->kernel_symmetry_past ? 3 : 0 ); + hTcxEnc1->kernel_type[n] = ( hTcxEnc1->kernel_symmetry_past ? 3 : 0 ); + } + hTcxEnc0->kernel_symmetry_past = hTcxEnc0->kernel_type[n] & 1; + hTcxEnc1->kernel_symmetry_past = hTcxEnc1->kernel_type[n] & 1; + + kernel_switch_update_transforms( hTcxEnc0->spectrum[n], mdst_spectrum[0][n], hTcxEnc0->transform_type[n], sts[0]->hTcxCfg, sts[0]->bwidth_sw_cnt, hTcxEnc0->kernel_type[n], + hTcxEnc0->new_speech_TCX_flt, ( n == 1 ? NULL : hTcxEnc0->speech_TCX_flt ), windowedSignal[0] + n * L_FRAME48k, L_subframeTCX / nSubframes ); + kernel_switch_update_transforms( hTcxEnc1->spectrum[n], mdst_spectrum[1][n], hTcxEnc1->transform_type[n], sts[1]->hTcxCfg, sts[1]->bwidth_sw_cnt, hTcxEnc1->kernel_type[n], + hTcxEnc1->new_speech_TCX_flt, ( n == 1 ? NULL : hTcxEnc1->speech_TCX_flt ), windowedSignal[1] + n * L_FRAME48k, L_subframeTCX / nSubframes ); + } + for ( n = 0; n < nSubframes; n++ ) + { + if ( hTcxEnc0->transform_type[n] == hTcxEnc1->transform_type[n] && /* do not combine TCX-5 and TCX-10 as this causes artifacts */ + sts[0]->hTcxCfg->tcx_curr_overlap_mode == sts[1]->hTcxCfg->tcx_curr_overlap_mode && + sts[0]->hTcxCfg->tcx_last_overlap_mode == sts[1]->hTcxCfg->tcx_last_overlap_mode ) + { + if ( hTcxEnc0->transform_type[n] == TCX_5 ) + { + const int16_t tcx5SizeFB = sts[1]->hTcxCfg->tcx5SizeFB; + + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / ( 2 * NB_DIV ), + L_subframeTCX / ( 2 * NB_DIV ), ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / ( 2 * NB_DIV ) ); + + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum[n] + tcx5SizeFB, hTcxEnc1->spectrum[n] + tcx5SizeFB, mdst_spectrum[0][n] + tcx5SizeFB, mdst_spectrum[1][n] + tcx5SizeFB, nSampCore / ( 2 * NB_DIV ), + L_subframeTCX / ( 2 * NB_DIV ), ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / ( 2 * NB_DIV ) ); + } + else + { + hTcxEnc0->enc_ste_pre_corr_past = + enc_ste_pre_mdct( hTcxEnc0->spectrum[n], hTcxEnc1->spectrum[n], mdst_spectrum[0][n], mdst_spectrum[1][n], nSampCore / nSubframes, + L_subframeTCX / nSubframes, ( nrg > MAX_STE_PRE_NRG ? 1 : 0 ), hTcxEnc0->enc_ste_pre_corr_past, ( totalRate * L_subframe ) / nSubframes ); + } + } + else + { + hTcxEnc0->enc_ste_pre_corr_past = 0; + } + } + } + else + { + sts[0]->hTcxEnc->enc_ste_pre_corr_past = 0; + sts[0]->hTcxEnc->kernel_switch_corr_past_flt = 0.f; + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + TCX_ENC_HANDLE hTcxEncCh = sts[ch]->hTcxEnc; + + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + hTcxEncCh->kernel_symmetry_past = hTcxEncCh->kernel_type[0] = 0; + + continue; + } + + init_tcx_enc_info( sts[ch], &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); + nSubframes = ( hTcxEncCh->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + hTcxEncCh->kernel_type[n] = ( hTcxEncCh->kernel_symmetry_past && sts[ch]->element_mode == IVAS_CPE_MDCT ? 3 - mct_on : 0 ); + hTcxEncCh->kernel_symmetry_past = hTcxEncCh->kernel_type[n] & 1; + + kernel_switch_update_transforms( hTcxEncCh->spectrum[n], mdst_spectrum[ch][n], hTcxEncCh->transform_type[n], sts[ch]->hTcxCfg, sts[ch]->bwidth_sw_cnt, hTcxEncCh->kernel_type[n], + hTcxEncCh->new_speech_TCX_flt, ( n /*1*/ ? NULL : hTcxEncCh->speech_TCX_flt ), windowedSignal[ch] + n * L_FRAME48k, L_subframeTCX / nSubframes ); + } + } + } + + TNSAnalysisStereo( sts, mdst_spectrum, 0, tnsSize, tnsBits, param_core, mct_on ); + + /*--------------------------------------------------------------* + * Envelope Quantization and FDNS + *---------------------------------------------------------------*/ + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + continue; + } + + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + if ( mct_on ) + { + set_zero( chE, NB_DIV ); + } + + init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); + + L_subframe = L_subframe / nSubframes; + L_subframeTCX = ( mct_on ? L_subframeTCX / nSubframes : L_subframe ); + tcx_subframe_coded_lines = tcx_subframe_coded_lines / nSubframes; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( st->hTcxEnc->fUseTns[n] ) + { + for ( i = 0; i < L_subframeTCX; i++ ) + { + powerSpec[i] = ( st->hTcxEnc->spectrum[n][i] * st->hTcxEnc->spectrum[n][i] ); + } + } + else + { + for ( i = 0; i < L_subframeTCX; i++ ) + { + powerSpec[i] = ( mdst_spectrum[ch][n][i] * mdst_spectrum[ch][n][i] + st->hTcxEnc->spectrum[n][i] * st->hTcxEnc->spectrum[n][i] ); + } + } + + if ( mct_on ) + { + chE[n] = sum_f( powerSpec, L_subframeTCX ); + } + + sns_compute_scf( powerSpec, st->hTcxCfg->psychParamsCurrent, st->L_frame, scf[ch][n] ); + } + + /* MCT: detect whether there are silent channels and set mct_chan_mode accordingly */ + if ( mct_on ) + { + chE_tot = sum_f( chE, NB_DIV ); + + if ( chE_tot < SILENT_CHANNEL_THRES && nSubframes == 1 ) + { + st->mct_chan_mode = MCT_CHAN_MODE_IGNORE; + st->bits_frame_channel = 0; + } + else + { + st->mct_chan_mode = MCT_CHAN_MODE_REGULAR; + } + } + } + + /* set low br mode, if possible. Can later be discarded, depending on the stereo mode used for SNS parameter decoding */ + if ( hCPE->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) ) + { + sns_low_br_mode = !sts[0]->sp_aud_decision0; + } + else + { + sns_low_br_mode = 0; + } + + if ( !mct_on && sts[0]->sr_core == 25600 && ( ( hCPE->element_brate == IVAS_48k || hCPE->element_brate == IVAS_64k ) ) ) + { + quantize_sns( scf, scf_q, sts, sns_vq_indices, zero_side_flag, sns_stereo_mode ); + } + else + { + if ( sts[0]->hTcxEnc->tcxMode == TCX_20 && sts[1]->hTcxEnc->tcxMode == TCX_20 && + sts[0]->mct_chan_mode == MCT_CHAN_MODE_REGULAR && sts[1]->mct_chan_mode == MCT_CHAN_MODE_REGULAR ) + { + sns_avq_cod_stereo( scf[0][0], scf[1][0], sts[0]->L_frame, scf_q[0][0], scf_q[1][0], param_lpc[0], param_lpc[1] ); + } + else + { + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + param_lpc[ch][0] = ch; + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st = sts[ch]; + if ( st->hTcxEnc->tcxMode == TCX_20 ) + { + sns_avq_cod( scf[ch][0], NULL, scf_q[ch][0], NULL, ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); + } + else + { + sns_avq_cod( scf[ch][1], scf[ch][0], scf_q[ch][1], scf_q[ch][0], ¶m_lpc[ch][1], st->hTcxEnc->tcxMode, st->L_frame, sns_low_br_mode ); + } + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); + + L_subframe = L_subframe / nSubframes; + L_subframeTCX = L_subframeTCX / nSubframes; + tcx_subframe_coded_lines = tcx_subframe_coded_lines / nSubframes; + + for ( n = 0; n < nSubframes; n++ ) + { + mvr2r( st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], L_subframeTCX ); + + /* Shape spectrum */ + ShapeSpectrum( st->hTcxCfg, A_q[ch][n], NULL, L_subframe, tcx_subframe_coded_lines, st->hTcxEnc->spectrum[n], st->hTcxEnc->fUseTns[n], st, scf_q[ch][n] ); + } + } + + /*--------------------------------------------------------------* + * TNS + *---------------------------------------------------------------*/ + + /* first deinterleave once more */ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( st->hTcxEnc->transform_type[n] == TCX_5 ) + { + tcx5SpectrumDeinterleaving( st->hTcxCfg->tcx5SizeFB, st->hTcxEnc->spectrum[n] ); + tcx5SpectrumDeinterleaving( st->hTcxCfg->tcx5SizeFB, mdst_spectrum[ch][n] ); + } + } + } + + TNSAnalysisStereo( sts, mdst_spectrum, 1, tnsSize, tnsBits, param_core, mct_on ); + + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + if ( sts[ch]->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + + st = sts[ch]; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + + init_tcx_enc_info( st, &L_subframe, &L_subframeTCX, &tcx_subframe_coded_lines ); + + L_subframe = L_subframe / nSubframes; + L_subframeTCX = L_subframeTCX / nSubframes; + tcx_subframe_coded_lines = tcx_subframe_coded_lines / nSubframes; + + for ( n = 0; n < nSubframes; n++ ) + { + if ( !st->hTcxEnc->fUseTns[n] ) + { + ShapeSpectrum( st->hTcxCfg, A_q[ch][n], NULL, L_subframe, tcx_subframe_coded_lines, mdst_spectrum[ch][n], st->hTcxEnc->fUseTns[n], st, scf_q[ch][n] ); + } + } + } + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + /*no need to write last channel bit in case of odd channels*/ + if ( ( hCPE->cpe_id * CPE_CHANNELS + ch ) >= nChannels ) + { + continue; + } + + st = sts[ch]; + + if ( mct_on ) /* signal bits should be written only for MCT*/ + { + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + push_next_indice( hBstr, 1, 1 ); + } + else + { + assert( st->mct_chan_mode == MCT_CHAN_MODE_REGULAR ); + push_next_indice( hBstr, 0, 1 ); + } + } + } + + /* write bitstream with info up to here */ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + st->side_bits_frame_channel = 0; + /*dummy initialization to prevent range coder crashing in case all channels are silent and bits are distributed to channel 0 */ + *p_param[ch] = 1 + NOISE_FILL_RANGES + LTPSIZE + tnsSize[ch][0] + NPRM_CTX_HM; + continue; + } + + enc_prm_pre_mdct( st, param_core[ch], ( ( ( ch > 0 ) && ( sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 ) && !mct_on ) ? tnsSize[ch] : NULL ), p_param[ch], mct_on, hBstr ); + + if ( ch > 0 && sts[0]->hTcxEnc->fUseTns[0] + sts[0]->hTcxEnc->fUseTns[1] > 0 && !mct_on ) + { + if ( st->hTcxEnc->tnsData[0].nFilters < 0 ) + { + tnsBits[ch][0] = 1; + } + else + { + tnsBits[ch][0]++; + } + + if ( st->core == TCX_10_CORE ) + { + if ( st->hTcxEnc->tnsData[1].nFilters < 0 ) + { + tnsBits[ch][1] = 1; + } + else + { + tnsBits[ch][1]++; + } + } + } + } + + /*--------------------------------------------------------------------------------* + * SNS parameters + *--------------------------------------------------------------------------------*/ + + if ( !mct_on && sts[0]->sr_core == 25600 && ( ( hCPE->element_brate == IVAS_48k || hCPE->element_brate == IVAS_64k ) ) ) + { + idx = 0; + + if ( sts[0]->core == sts[1]->core ) + { + nSubframes = ( sts[0]->core == TCX_20_CORE ) ? 1 : NB_DIV; + + /* push all stereo mode bits first */ + for ( n = 0; n < nSubframes; ++n ) + { + push_next_indice( hBstr, sns_stereo_mode[n], 1 ); + sts[0]->side_bits_frame_channel++; + } + + /* zero side flags only get transmitted if needed */ + for ( n = 0; n < nSubframes; ++n ) + { + if ( sns_stereo_mode[n] == SNS_STEREO_MODE_MS ) + { + push_next_indice( hBstr, zero_side_flag[n], 1 ); + sts[0]->side_bits_frame_channel++; + } + } + } + + for ( ch = 0; ch < CPE_CHANNELS; ++ch ) + { + st = sts[ch]; + nbits_start_sns = hBstr->nb_bits_tot; + nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + for ( n = 0; n < nSubframes; ++n ) + { + const int16_t is_side = ch == 1 && sns_stereo_mode[n] == SNS_STEREO_MODE_MS; + const int16_t *bits = ( nSubframes == 1 ) ? ivas_sns_cdbks_tcx20_bits : ivas_sns_cdbks_tcx10_bits; + int16_t nStages = ( ( nSubframes == 1 ) ? SNS_MSVQ_NSTAGES_TCX20 : SNS_MSVQ_NSTAGES_TCX10 ); + + if ( is_side ) + { + if ( zero_side_flag[n] ) + { + continue; + } + nStages = SNS_MSVQ_NSTAGES_SIDE; + bits = ( sts[ch]->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_bits : ivas_sns_cdbks_side_tcx10_bits; + } + for ( int16_t j = 0; j < nStages; ++j, ++idx ) + { + push_next_indice( hBstr, sns_vq_indices[idx], bits[j] ); + } + } + st->side_bits_frame_channel += hBstr->nb_bits_tot - nbits_start_sns; + } + } + else + { + /* write SNS parameter separately since at the decoder, both channels' cores need to be decoded before, so the joint SNS decoding can be done */ + skipped_first_channel = 0; + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + skipped_first_channel = 1; + continue; + } + + nbits_start_sns = hBstr->nb_bits_tot; + + num_sns = ( st->core == TCX_20_CORE ) ? 1 : NB_DIV; + + if ( ch == 0 || skipped_first_channel ) + { + push_next_indice( hBstr, param_lpc[0][0] >> 1, 1 ); + + if ( st->element_brate == IVAS_48k && !( ( sts[0]->core == TCX_20 && sts[1]->core == TCX_20 ) ) ) + { + /* write classifier decision to signal low br mode for SNS encoding, for all other configs, low_br mode is not possible */ + push_next_indice( hBstr, sns_low_br_mode, 1 ); + } + } + encode_lpc_avq( hBstr, num_sns, param_lpc[ch], st->core, st->element_mode ); + + st->side_bits_frame_channel += hBstr->nb_bits_tot - nbits_start_sns; + } + } + + + /*update pitch buffer*/ + for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + { + continue; + } + if ( param_core[ch][1 + NOISE_FILL_RANGES] != 0 ) + { + set_f( pitch_buf[ch], ( st->hTcxEnc->tcxltp_pitch_int + (float) st->hTcxEnc->tcxltp_pitch_fr / (float) st->pit_res_max ) * (float) st->sr_core / (float) INT_FS_12k8, NB_SUBFR16k ); + } + else + { + set_f( pitch_buf[ch], L_SUBFR, NB_SUBFR16k ); + } + } + + pop_wmops(); + return; +} +#endif /*--------------------------------------------------------------* diff --git a/lib_enc/ivas_rom_enc.c b/lib_enc/ivas_rom_enc.c index b318fd695..e9a217312 100644 --- a/lib_enc/ivas_rom_enc.c +++ b/lib_enc/ivas_rom_enc.c @@ -185,6 +185,24 @@ const float icbwe_thr_DFT[7] = { -1.19952f, -1.42293f, -1.074940f, -1.63089f, 0. const float icbwe_regressionValuesTDM[8] = { 0.104430f, 0.025943f, 0.50332f, 0.12767f, 0.80566f, 0.27640f, 0.98366f, 0.35556f }; const float icbwe_regressionValuesDFT[8] = { 0.030371f, 0.155500f, 0.52510f, 0.10623f, 0.79167f, 0.23188f, 0.98325f, 0.00000f }; +#ifdef IVAS_FLOAT_FIXED +#define FLOAT_2_FIX_Q30(a) ((Word32)(a * 1024.0 * 1024.0 * 1024.0)) +#define FLOAT_2_FIX_Q31(a) ((Word32)(a * 1024.0 * 1024.0 * 1024.0 * 2.0)) +/* Q30Value >> Q5 */ +const Word32 icbwe_thr_TDM_fx[7] = {-1318855552 >> 5, -1667671424 >> 5, -1072553216 >> 5, + 920192448 >> 5, 897910144 >> 5, 936654016 >> 5, + 1043856384 >> 5}; +/* Q30Value >> Q5*/ +const Word32 icbwe_thr_DFT_fx[7] = {-1287974784 >> 5, -1527859456 >> 5, -1154208000 >> 5, + -1751154816 >> 5, 955618432 >> 5, 959420544 >> 5, + 1047207488 >> 5}; +/* Q31 */ +const Word32 icbwe_regressionValuesTDM_fx[8] = {224261712, 55712168, 1080871424, 274169248, + 1730141696, 593564480, 2112393728, 763559296}; +/* Q31 */ +const Word32 icbwe_regressionValuesDFT_fx[8] = {65221224, 333933696, 1127643648, 228127184, + 1700098432, 497958496, 2111513344, 0}; +#endif /*----------------------------------------------------------------------------------* * DFT stereo ROM tables @@ -715,12 +733,22 @@ const float log2TB[ECSQ_log2TB_SIZE] = 0.858721f, 0.232908f, 0.059619f, 0.014997f, 0.003755f, 0.000939f, 0.000235f, 0.000059f, 0.000015f, 0.000004f, 0.000001f, 0.000000f, 0.000000f }; +const Word32 log2TB_Q31[ECSQ_log2TB_SIZE] = +{ + 1844089344, 500166112, 128030824, 32205812, 8063801, 2016487, 504658, 126701, 32212, 8589, 2147, 0, 0 +}; + /* precomuputed table for log_2(factorial(i)), for i in {0, .., ECSQ_SEGMENT_SIZE} */ const float ECSQ_log2_fact[1 + ECSQ_SEGMENT_SIZE] = { 0.0000000f, 0.0000000f, 1.0000000f, 2.5849625f, 4.5849625f, 6.9068906f, 9.4918531f, 12.2992080f, 15.2992080f }; +const Word16 ECSQ_log2_fact_Q10[1 + ECSQ_SEGMENT_SIZE] = +{ + 0, 0, 1024, 2647, 4695, 7072, 9719, 12594, 15666 +}; + const uint16_t ECSQ_tab_param[ECSQ_CONFIG_COUNT][1 + ECSQ_PARAM_COUNT] = { { 16384, 15360, 14336, 13312, 12288, 11264, 10240, 9216, 8192, 7168, 6144, 5120, 4096, 3072, 2048, 1024, 0 }, /* un-optimized (reserved) */ diff --git a/lib_enc/ivas_rom_enc.h b/lib_enc/ivas_rom_enc.h index 6b6fa1c78..81758f589 100644 --- a/lib_enc/ivas_rom_enc.h +++ b/lib_enc/ivas_rom_enc.h @@ -81,6 +81,13 @@ extern const float icbwe_thr_DFT[]; extern const float icbwe_regressionValuesTDM[]; extern const float icbwe_regressionValuesDFT[]; +#ifdef IVAS_FLOAT_FIXED +extern const Word32 icbwe_thr_TDM_fx[]; +extern const Word32 icbwe_thr_DFT_fx[]; +extern const Word32 icbwe_regressionValuesTDM_fx[]; +extern const Word32 icbwe_regressionValuesDFT_fx[]; +#endif + /*----------------------------------------------------------------------------------* * DFT stereo ROM tables *----------------------------------------------------------------------------------*/ @@ -137,7 +144,9 @@ extern const Word32 ari_bit_estimate_s17_LC_fx[RANGE_N_CONTEXT][RANGE_N_SYMBOLS] extern const int16_t log2_1px_table[65]; extern const float log2TB[ECSQ_log2TB_SIZE]; +extern const Word32 log2TB_Q31[ECSQ_log2TB_SIZE]; extern const float ECSQ_log2_fact[1 + ECSQ_SEGMENT_SIZE]; +extern const Word16 ECSQ_log2_fact_Q10[1 + ECSQ_SEGMENT_SIZE]; extern const uint16_t ECSQ_tab_param[ECSQ_CONFIG_COUNT][1 + ECSQ_PARAM_COUNT]; extern const uint16_t *const ECSQ_tab_abs_lsbs[1 + 4]; extern const uint16_t ECSQ_tab_vals[ECSQ_PARAM_COUNT - 1][1 + ECSQ_TAB_VALS_SIZE]; diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index 4adcc2ed3..453d08ba4 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -68,6 +68,7 @@ ivas_error ivas_sce_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // required for float to fix conversion float old_inp_12k8[1][L_INP_12k8] = { 0 }; /* buffer of input signal @ 12k8 */ float old_inp_16k[1][L_INP] = { 0 }; /* buffer of input signal @ 16kHz */ + Word16 old_inp_12k8_fx[1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ #else float old_inp_12k8[1][L_INP_12k8]; /* buffer of input signal @ 12k8 */ float old_inp_16k[1][L_INP]; /* buffer of input signal @ 16kHz */ @@ -97,6 +98,7 @@ ivas_error ivas_sce_enc( float enerBuffer[1][CLDFB_NO_CHANNELS_MAX]; /* energy buffer */ float currFlatness[1]; /* flatness parameter */ float fft_buff[1][2 * L_FFT]; /* FFT buffer */ + Word16 fft_buff_fx[1][2 * L_FFT]; /* FFT buffer */ float fr_bands[1][2 * NB_BANDS]; /* energy in frequency bands */ float Etot_LR[1]; /* total energy */ float lf_E[1][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ @@ -194,10 +196,10 @@ ivas_error ivas_sce_enc( * Front Pre-processing *----------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED - error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8[0], old_inp_16k[0], + error = pre_proc_front_ivas_fx( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8_fx[0], old_inp_12k8[0], old_inp_16k[0], &ener[0], &relE[0], A[0], Aw[0], epsP[0], lsp_new[0], lsp_mid[0], &vad_hover_flag[0], &attack_flag[0], realBuffer[0], imagBuffer[0], old_wsp[0], pitch_fr[0], voicing_fr[0], &loc_harm[0], &cor_map_sum[0], &vad_flag_dtx[0], enerBuffer[0], - fft_buff[0], A[0], lsp_new[0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, flag_16k_smc, + fft_buff[0], fft_buff_fx[0], A[0], lsp_new[0], currFlatness[0], 0, fr_bands, Etot_LR, lf_E, localVAD_HE_SAD, NULL, flag_16k_smc, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_flag : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->force_front_vad : 0, st_ivas->hSpar != NULL ? st_ivas->hSpar->front_vad_dtx_flag : 0, ivas_format, 0, st_ivas->hEncoderConfig->ivas_total_brate ); #else error = pre_proc_front_ivas( hSCE, NULL, hSCE->element_brate, nb_bits_metadata, input_frame, 0, old_inp_12k8[0], old_inp_16k[0], diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index 6ac31ad8c..fd9daf546 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -356,7 +356,7 @@ typedef struct stereo_dft_enc_data_struct Word32 ipd_buf_fx[STEREO_DFT_BAND_MAX][STEREO_DFT_IPD_BUF_LEN]; // Q13 Word32 prev_gipd_fx; // Q13 Word32 xspec_smooth_fx[STEREO_DFT_N_32k_ENC]; // Q(31 - xspec_smooth_fx_e) - Word16 xspec_smooth_fx_e; + Word16 xspec_smooth_fx_e[STEREO_DFT_N_32k_ENC]; Word32 Spd_L_smooth_fx[STEREO_DFT_N_32k_ENC / 2]; // Q(31 - Spd_L_smooth_fx_e) Word16 Spd_L_smooth_fx_e; Word32 Spd_R_smooth_fx[STEREO_DFT_N_32k_ENC / 2]; // Q(31 - Spd_R_smooth_fx_e) @@ -390,7 +390,7 @@ typedef struct stereo_dft_enc_data_struct Word16 res_cod_NRG_S_fx_e[STEREO_DFT_BAND_MAX]; Word32 res_cod_SNR_M_fx[STEREO_DFT_BAND_MAX]; // Q(31 - res_cod_SNR_M_fx_e[]) Word16 res_cod_SNR_M_fx_e[STEREO_DFT_BAND_MAX]; - Word32 old_snr_fx; + Word32 old_snr_fx; // Q25 Word32 past_nrgL_fx[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; // Q(31 - past_nrgL_fx_e[]) Word16 past_nrgL_fx_e[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; Word32 past_nrgR_fx[STEREO_DFT_NRG_PAST_LEN * STEREO_DFT_BAND_MAX]; // Q(31 - past_nrgR_fx_e[]) @@ -650,7 +650,7 @@ typedef struct stereo_icbwe_enc_data_structure Word16 memHPF_fx[8]; // Q -> q_dataChan_fx Word16 mem_decim_shb_ch0_fx[2 * L_FILT_MAX]; // Q0 - Word32 mem_shb_speech_ref_fx[L_LOOK_16k]; + Word16 mem_shb_speech_ref_fx[L_LOOK_16k]; Word32 mem_shb_speech_nonref_fx[L_LOOK_16k]; Word32 mem_lpc_shbsynth_nonref_fx[LPC_SHB_ORDER]; Word32 prevSpecMapping_fx; @@ -671,12 +671,13 @@ typedef struct stereo_icbwe_enc_data_structure Word32 mem_nrg_DMX_fx[CPE_CHANNELS]; Word32 gDes_pastFrame_fx; // Q31 Word32 icbweRefEner_fx; - Word32 shbSynthRef_fx[L_FRAME16k]; - Word32 nlExc16k_fx[L_FRAME16k]; - Word32 mixExc16k_fx[L_FRAME16k]; + Word16 shbSynthRef_fx[L_FRAME16k]; + Word16 nlExc16k_fx[L_FRAME16k]; + Word16 mixExc16k_fx[L_FRAME16k]; Word32 lpSHBRef_fx[LPC_SHB_ORDER + 1]; Word16 MSFlag; + Word16 icbweRefEner_fx_e; } STEREO_ICBWE_ENC_DATA, *STEREO_ICBWE_ENC_HANDLE; diff --git a/lib_enc/ivas_stereo_cng_enc.c b/lib_enc/ivas_stereo_cng_enc.c index 84bbc55c2..42f8e8c2f 100644 --- a/lib_enc/ivas_stereo_cng_enc.c +++ b/lib_enc/ivas_stereo_cng_enc.c @@ -60,7 +60,172 @@ * * Encodes the coherence in SID frames * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_sid_calc_coh_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ + Word32 prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence Q31 */ + Word16 *td_active, /* i/o: TD stereo mode indicator */ + Word16 *first_SID, /* i/o: First SID indicator */ + Word32 *cohBand /* i/o: Coherence per band Q31 */ +) +{ + Word16 b, k; + Word32 coh_weight; + Word16 coh_weight_e; + Word32 coh_weight_sum; + Word16 coh_weight_sum_e; + Word32 xspec_scale; + Word32 L_tmp1, L_tmp2, L_tmp3; + Word16 L_tmp1_e, L_tmp2_e, L_tmp3_e; + Word64 W_tmp; + Word16 W_tmp_q; + // Word16 prev_cohBand_e[2 * (STEREO_DFT_BAND_MAX / 2)]; + Word16 cohBand_e[STEREO_DFT_BAND_MAX / 2]; + /* Cluster the coherence into bands using a weighted average. The coherence is weighted with the energy spectrum of the + mixdown signal. */ + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + cohBand[b] = 0; + move32(); + cohBand_e[b] = 0; + move16(); + coh_weight_sum = 0; + move32(); + coh_weight_sum_e = 0; + move16(); + + test(); + IF( hStereoDft->coh_fade_counter == 0 && !*first_SID ) + { + FOR( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + { + // xspec_scale = sqrtf( ( prev_cohBand[b] * ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] ) ) / ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] + EPSILON ) ); + W_tmp = W_mult_32_32( hStereoDft->Spd_L_smooth_fx[k], hStereoDft->Spd_R_smooth_fx[k] ); + W_tmp_q = W_norm( W_tmp ); + L_tmp1 = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + L_tmp1_e = sub( add( hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_R_smooth_fx_e ), W_tmp_q ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], hStereoDft->xspec_smooth_fx[2 * k] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k], 1 ), Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], hStereoDft->xspec_smooth_fx[2 * k + 1] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k + 1], 1 ), &L_tmp2_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp2_e ); + L_tmp3 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, L_tmp2, &L_tmp3_e ); + L_tmp3_e = add( L_tmp3_e, sub( L_tmp1_e, L_tmp2_e ) ); + L_tmp3 = Mpy_32_32( prev_cohBand[b], L_tmp3 ); + xspec_scale = Sqrt32( L_tmp3, &L_tmp3_e ); + // xspec_scale = L_shl(xspec_scale, L_tmp3_e);//Q31 + + hStereoDft->xspec_smooth_fx[2 * k] = Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], xspec_scale ); + move32(); + hStereoDft->xspec_smooth_fx_e[2 * k] = add( hStereoDft->xspec_smooth_fx_e[2 * k], L_tmp3_e ); + move16(); + hStereoDft->xspec_smooth_fx[2 * k + 1] = Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], xspec_scale ); + move32(); + hStereoDft->xspec_smooth_fx_e[2 * k + 1] = add( hStereoDft->xspec_smooth_fx_e[2 * k + 1], L_tmp3_e ); + move16(); + } + + cohBand[b] = prev_cohBand[b]; + move32(); + } + ELSE + { + FOR( k = hStereoDft->band_limits[b]; k < hStereoDft->band_limits[b + 1]; k++ ) + { + // coh_weight = hStereoDft->DFT[0][2 * k] * hStereoDft->DFT[0][2 * k] + hStereoDft->DFT[0][2 * k + 1] * hStereoDft->DFT[0][2 * k + 1]; + W_tmp = W_add( W_mult_32_32( hStereoDft->DFT_fx[0][2 * k], hStereoDft->DFT_fx[0][2 * k] ), W_mult_32_32( hStereoDft->DFT_fx[0][2 * k + 1], hStereoDft->DFT_fx[0][2 * k + 1] ) ); + W_tmp_q = W_norm( W_tmp ); + coh_weight = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + coh_weight_e = sub( shl( hStereoDft->DFT_fx_e[0], 1 ), W_tmp_q ); // 31 - dft_e*2 + W_tmp_q + + // cohBand[b] += coh_weight * ( hStereoDft->xspec_smooth[2 * k] * hStereoDft->xspec_smooth[2 * k] + hStereoDft->xspec_smooth[2 * k + 1] * hStereoDft->xspec_smooth[2 * k + 1] ) / ( hStereoDft->Spd_L_smooth[k] * hStereoDft->Spd_R_smooth[k] + EPSILON ); + L_tmp1 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k], hStereoDft->xspec_smooth_fx[2 * k] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k], 1 ), Mpy_32_32( hStereoDft->xspec_smooth_fx[2 * k + 1], hStereoDft->xspec_smooth_fx[2 * k + 1] ), shl( hStereoDft->xspec_smooth_fx_e[2 * k + 1], 1 ), &L_tmp1_e ); + W_tmp = W_mult_32_32( hStereoDft->Spd_L_smooth_fx[k], hStereoDft->Spd_R_smooth_fx[k] ); + W_tmp_q = W_norm( W_tmp ); + L_tmp2 = W_extract_h( W_shl( W_tmp, W_tmp_q ) ); + L_tmp2_e = sub( add( hStereoDft->Spd_L_smooth_fx_e, hStereoDft->Spd_R_smooth_fx_e ), W_tmp_q ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, EPSILON_FX_M, EPSILON_FX_E, &L_tmp2_e ); + L_tmp3 = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, L_tmp2, &L_tmp3_e ); + L_tmp3_e = add( L_tmp3_e, sub( L_tmp1_e, L_tmp2_e ) ); + L_tmp3 = Mpy_32_32( coh_weight, L_tmp3 ); + L_tmp3_e = add( coh_weight_e, L_tmp3_e ); + cohBand[b] = BASOP_Util_Add_Mant32Exp( cohBand[b], cohBand_e[b], L_tmp3, L_tmp3_e, &cohBand_e[b] ); + move32(); + + // coh_weight_sum += coh_weight; + coh_weight_sum = BASOP_Util_Add_Mant32Exp( coh_weight_sum, coh_weight_sum_e, coh_weight, coh_weight_e, &coh_weight_sum_e ); + } + IF( coh_weight_sum > 0 ) + { + // cohBand[b] = cohBand[b] / coh_weight_sum; + cohBand[b] = BASOP_Util_Divide3232_Scale_cadence( cohBand[b], coh_weight_sum, &L_tmp1_e ); + move32(); + cohBand_e[b] = add( L_tmp1_e, sub( cohBand_e[b], coh_weight_sum_e ) ); + move16(); + cohBand[b] = L_shl_sat( cohBand[b], cohBand_e[b] ); // Q31: value does not exceed 1.0 + move32(); + } + } + } + + IF( *first_SID ) + { + Copy32( cohBand, prev_cohBand, hStereoDft->nbands ); + Copy32( prev_cohBand, &( prev_cohBand[STEREO_DFT_BAND_MAX / 2] ), hStereoDft->nbands ); + *first_SID = 0; + move32(); + } + + test(); + test(); + IF( LT_16( hStereoDft->coh_fade_counter, COH_FADE_MAX ) && ( *td_active || LT_16( hStereoDft->currentNumUpdates, COH_FADE_UPDATES ) ) ) + { + FOR( b = 0; b < hStereoDft->nbands; b++ ) + { + // cohBand[b] = ( cohBand[b] * hStereoDft->coh_fade_counter + prev_cohBand[b] * ( COH_FADE_MAX - hStereoDft->coh_fade_counter ) ) / COH_FADE_MAX; + SWITCH( hStereoDft->coh_fade_counter ) + { + case 0: + cohBand[b] = prev_cohBand[b]; + move32(); + BREAK; + case 1: + cohBand[b] = L_add( L_shr( cohBand[b], 2 ), Mpy_32_32( prev_cohBand[b], 1610612736 /*3/4*/ ) ); + move32(); + BREAK; + case 2: + cohBand[b] = L_add( L_shr( cohBand[b], 1 ), L_shr( prev_cohBand[b], 1 ) ); + move32(); + BREAK; + case 3: + cohBand[b] = L_add( Mpy_32_32( cohBand[b], 1610612736 /*3/4*/ ), L_shr( prev_cohBand[b], 2 ) ); + move32(); + BREAK; + default: + assert( "unexpected hStereoDft->coh_fade_counter value" ); + BREAK; + } + } + hStereoDft->coh_fade_counter = add( hStereoDft->coh_fade_counter, 1 ); + IF( hStereoDft->coh_fade_counter > 0 ) + { + Copy32( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands ); + } + Copy32( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands ); + } + ELSE + { + IF( hStereoDft->coh_fade_counter > 0 ) + { + Copy32( &prev_cohBand[STEREO_DFT_BAND_MAX / 2], prev_cohBand, hStereoDft->nbands ); + } + Copy32( cohBand, &prev_cohBand[STEREO_DFT_BAND_MAX / 2], hStereoDft->nbands ); + hStereoDft->coh_fade_counter = COH_FADE_MAX; + move16(); + *td_active = 0; + move16(); + } + return; +} +#else void stereo_dft_enc_sid_calc_coh( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: DFT stereo handle */ float prev_cohBand[2 * ( STEREO_DFT_BAND_MAX / 2 )], /* i/o: Previous coherence */ @@ -139,7 +304,7 @@ void stereo_dft_enc_sid_calc_coh( return; } - +#endif /*--------------------------------------------------------------- * stereo_dft_enc_sid_coh() @@ -147,6 +312,231 @@ void stereo_dft_enc_sid_calc_coh( * Encodes the coherence in SID frames * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_sid_coh_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word32 *mem_cohBand, /* i/o: Coherence memory */ + const Word16 nbands, /* i : number of DFT stereo bands */ + Word16 *nb_bits, /* i/o: number of bits written */ + Word32 *cohBand /* i/o: Coherence per band */ +) +{ + Word16 b, k; + Word16 zeropad; + Word16 nr_of_sid_stereo_bits; + Word16 coh_pred_index; + Word16 min_pred_err; + Word16 min_pred_err_e; + Word16 pred_err; // Q13 + Word16 res_index; + Word16 i; + Word16 tmp; + const Word16 *pptr; + Word16 pred; // Q13 + Word16 cohBandq[STEREO_DFT_BAND_MAX / 2]; /* Reconstructed coherence values for intra-frame prediction Q15 */ + const Word16 *alphaptr; + Word16 nbbits_test; + Word16 prev_nbbits_test; + Word16 alpha_step; + Word16 alpha_level; + Word16 n; + + nr_of_sid_stereo_bits = ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS; + move16(); + zeropad = 0; + move16(); + + /* Encode coherence vector. Find best fixed predictor by minimizing prediction error on input vector. + The prediction is formed by a linear combination of the previous values + in the vector. Hence, prediction is only done for coefficient 1 and up. + If not enough bits for at least one bit for encoding prediction + residual then skip the coding and write zeroes to the bitstream if needed. + In this case the decoder will set alpha to 0, i.e. reuse previous coherence */ + + IF( sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS + STEREO_DFT_PRED_NBITS ) > 0 ) + { + min_pred_err = 31250; + move32(); + min_pred_err_e = 20; + move16(); + coh_pred_index = -1; + move16(); + pptr = dft_cng_coh_pred_fx[0]; // Q13 + FOR( k = 0; k < STEREO_DFT_N_COH_PRED; k++ ) + { + pred_err = 0; + move16(); + FOR( b = 1; b < nbands; b++ ) /* Set b=1 to skip first coefficient (same error would otherwise be added for all predictors: (cohBand[0] - 0).^2) */ + { + pred = 0; + move16(); + FOR( i = 0; i < b; i++ ) + { + // pred += ( *pptr++ ) * cohBand[i]; + pred = add( pred, mult_r( extract_h( cohBand[i] ), ( *pptr++ ) ) ); // Q13 + } + tmp = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred ); // Q13 + // pred_err += tmp * tmp; + pred_err = add( pred_err, shl( mult_r( tmp, tmp ), 2 ) ); // Q13 + } + // if ( pred_err < min_pred_err ) /* Store best candidate */ + IF( BASOP_Util_Cmp_Mant32Exp( pred_err, 16, min_pred_err, add( min_pred_err_e, 16 ) ) < 0 ) /* Store best candidate */ + { + min_pred_err = pred_err; + move32(); + min_pred_err_e = 0; + move16(); + coh_pred_index = k; + move16(); + } + } + + push_next_indice( hBstr, coh_pred_index, STEREO_DFT_PRED_NBITS ); /* Write selected predictor to bitstream */ + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_PRED_NBITS ); + move16(); + + /* Pick two different alphas (one low and one high) as a function + of the number of available bits. */ + alpha_step = 0; + move16(); + FOR( i = 0; i < STEREO_DFT_N_COH_ALPHA_STEPS - 1; i++ ) + { + IF( GT_16( sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS ), dft_cng_coh_alpha_start[i] ) ) + { + alpha_step = add( i, 1 ); + } + } + + /* Calculate the number of encoded bits. */ + alphaptr = dft_cng_alpha_bits_fx[alpha_step]; + alpha_level = 0; + move16(); + prev_nbbits_test = 100; + move16(); + FOR( i = 0; i < STEREO_DFT_N_COH_ALPHA_LEVELS; i++ ) + { + nbbits_test = 0; + move16(); + pptr = dft_cng_coh_pred_fx[coh_pred_index]; // Q13 + pred = 3277 /*0.4f*/; + move16(); + FOR( b = 0; b < nbands; b++ ) + { + FOR( n = 0; n < b; n++ ) + { + // pred += ( *pptr++ ) * cohBandq[n]; + pred = add( pred, mult_r( cohBandq[n], *pptr++ ) ); // Q13 + } + + // pred = ( *alphaptr ) * pred + ( 1 - ( *alphaptr ) ) * mem_cohBand[b]; + pred = add( mult_r( pred, *alphaptr ), shr_r( mult_r( extract_h( mem_cohBand[b] ), sub( MAX_16, *alphaptr ) ), 2 ) ); // Q13 + pred_err = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred ); // Q13 + res_index = usquant_fx( pred_err, &pred_err, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/, 9 ); + res_index = dft_cng_coh_i2u[res_index]; + nbbits_test = add( nbbits_test, add( res_index, 1 ) ); + res_index = dft_cng_coh_u2i[res_index]; + pred_err = usdequant_fx( res_index, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/ ); // Q13 + cohBandq[b] = add( pred, pred_err ); + move16(); + cohBandq[b] = shl_sat( cohBandq[b], 2 ); // Q15 + move16(); + if ( cohBandq[b] < 0 ) + { + cohBandq[b] = 0; + move16(); + } + pred = 0; + move16(); + } + + if ( LT_16( nbbits_test, sub( sub( nr_of_sid_stereo_bits, *nb_bits ), STEREO_DFT_N_COH_ALPHA_BITS ) ) ) + { + alpha_level = i; + move16(); + } + + if ( LT_16( nbbits_test, prev_nbbits_test ) ) + { + alpha_level = i; + move16(); + } + + prev_nbbits_test = nbbits_test; + move16(); + alphaptr++; + } + + /* Do the actual encoding using the selected predictor and alpha */ + push_next_indice( hBstr, alpha_level, STEREO_DFT_N_COH_ALPHA_BITS ); /* Write selected alpha index to bitstream */ + ( *nb_bits ) += STEREO_DFT_N_COH_ALPHA_BITS; + move16(); + alphaptr = &dft_cng_alpha_bits_fx[alpha_step][alpha_level]; + pptr = dft_cng_coh_pred_fx[coh_pred_index]; /* Set pointer to selected predictor */ + pred = 3277 /*0.4f in Q13*/; + + FOR( b = 0; b < nbands; b++ ) + { + /* Intra-frame prediction using quantized values */ + FOR( i = 0; i < b; i++ ) + { + // pred += ( *pptr++ ) * cohBandq[i]; + pred = add( pred, mult_r( cohBandq[i], *pptr++ ) ); // Q13 + } + /* Weighted intra/inter-frame prediction */ + // pred = ( *alphaptr ) * pred + ( 1 - ( *alphaptr ) ) * mem_cohBand[b]; + pred = add( mult_r( pred, *alphaptr ), shr_r( mult_r( extract_h( mem_cohBand[b] ), sub( MAX_16, *alphaptr ) ), 2 ) ); // Q13 + pred_err = sub( shr_r( extract_h( cohBand[b] ), 2 ), pred ); // Q13 + + res_index = usquant_fx( pred_err, &pred_err, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/, 9 ); /* Quantize prediction residual */ + res_index = dft_cng_coh_i2u[res_index]; /* Convert to unary codeword - res_index+1 now equal to codeword + length in bits with the following order: + [0.0, 0.1, -0.1, 0.2, -0.2, 0.3, -0.3, 0.4, -0.4] */ + /* Bit rate truncation */ + WHILE( res_index + 1 + *nb_bits > nr_of_sid_stereo_bits && res_index > 0 ) + { + test(); + res_index = s_max( 0, sub( res_index, 2 ) ); /* Reduce step by one, keeping sign. */ + } + /* Write residual index to bitstream */ + IF( LE_16( add( add( res_index, 1 ), *nb_bits ), nr_of_sid_stereo_bits ) ) /* If the bit limit is reached, res_index = 0 is assumed for remaining indices */ + { + *nb_bits = add( *nb_bits, write_GR0( hBstr, IND_STEREO_DFT_SID_COH, &res_index, 1 ) ); + move16(); + } + + /* Reconstruct */ + res_index = dft_cng_coh_u2i[res_index]; + move16(); + pred_err = usdequant_fx( res_index, -3277 /*-0.4f in Q13*/, 410 /*0.1f in Q12*/ ); + cohBandq[b] = add( pred, pred_err ); /* Store for intra-frame prediction */ + move16(); + cohBandq[b] = shl_sat( cohBandq[b], 2 ); // Q15 + move16(); + if ( cohBandq[b] < 0 ) + { + cohBandq[b] = 0; + move16(); + } + + mem_cohBand[b] = L_deposit_h( cohBandq[b] ); /* Update memory for next frame */ + move32(); + pred = 0; + move16(); + } + } + + /* Zero pad up to max number of bits to get constant bitrate */ + FOR( k = *nb_bits; k < nr_of_sid_stereo_bits; k++ ) + { + push_next_indice( hBstr, zeropad, 1 ); + ( *nb_bits ) = add( *nb_bits, 1 ); + move16(); + } + + + return; +} +#else void stereo_dft_enc_sid_coh( BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ float *mem_cohBand, /* i/o: Coherence memory */ @@ -332,7 +722,7 @@ void stereo_dft_enc_sid_coh( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_cng_side_gain() diff --git a/lib_enc/ivas_stereo_dft_enc.c b/lib_enc/ivas_stereo_dft_enc.c index 7da597f49..f2e351a97 100644 --- a/lib_enc/ivas_stereo_dft_enc.c +++ b/lib_enc/ivas_stereo_dft_enc.c @@ -133,9 +133,27 @@ static Word32 stereo_dft_gain_offset_fx( const Word32 c, const Word16 c_e, const static float stereo_dft_gain_offset( const float c, const int16_t itd ); #endif +#ifdef IVAS_FLOAT_FIXED +static void side_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_GR[], + const Word16 sp_aud_decision0, /* i : Speech/audio decision 0 */ + const Word32 last_core_brate /* i : Last core bitrate */ +); +#else static void side_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, int16_t encoded_ind_GR[], const int16_t sp_aud_decision0, const int32_t last_core_brate ); +#endif +#ifdef IVAS_FLOAT_FIXED +static void res_pred_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_pred_GR[], + const Word16 k_offset, /* i : Parameter offset */ + const Word32 last_core_brate /* i : Last core bitrate */ +); +#else static void res_pred_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, int16_t encoded_ind_pred_GR[], const int16_t k_offset, const int32_t last_core_brate ); +#endif #ifdef IVAS_FLOAT_FIXED static void stereo_dft_enc_calculate_nrg_for_icbwe_fx( @@ -476,7 +494,7 @@ static void stereo_dft_quantize_ipd_fx( return; } -#endif +#else static void stereo_dft_quantize_ipd( const float *in, float *out, @@ -523,6 +541,7 @@ static void stereo_dft_quantize_ipd( return; } +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_create() @@ -1175,8 +1194,13 @@ void stereo_dft_enc_reset_fx( /*Coherence*/ set32_fx( hStereoDft->xspec_smooth_fx, MAX_32, STEREO_DFT_N_32k_ENC ); + set16_fx( hStereoDft->xspec_smooth_fx_e, 0, STEREO_DFT_N_32k_ENC ); set32_fx( hStereoDft->Spd_L_smooth_fx, MAX_32, shr( STEREO_DFT_N_32k_ENC, 1 ) ); + hStereoDft->Spd_L_smooth_fx_e = 0; + move16(); set32_fx( hStereoDft->Spd_R_smooth_fx, MAX_32, shr( STEREO_DFT_N_32k_ENC, 1 ) ); + hStereoDft->Spd_R_smooth_fx_e = 0; + move16(); hStereoDft->currentNumUpdates = 0; move16(); @@ -4260,6 +4284,168 @@ static void stereo_dft_enc_get_res_cod_mode_flag( * Code the residual signal *-------------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_res_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + const Word32 *input_8k, /* i : input buffer sampled at 8kHz Q16 */ + BSTR_ENC_HANDLE hBstr, /* i/o: bitstream handle */ + Word16 *nb_bits, /* o : number of bits written */ + const Word16 max_bits ) +{ + Word16 i, b; + RangeUniEncState range_uni_enc_state; + ECSQ_instance ecsq_inst; + Word32 MDCT_RES[L_FRAME8k]; + Word16 MDCT_RES_e; + Word16 win[L_FRAME8k + STEREO_DFT_OVL_8k]; // Q0 + Word16 global_gain_index; + Word16 total_bit_count; + Word32 max_snr; // Q25 + Word32 panning_gain, panning_gain_min; + Word32 res_cod_gain[10]; // Q25 + Word32 in_phase_ratio; + Word16 in_phase_ratio_e; + Word32 L_tmp1, L_tmp2; + Word16 /*L_tmp1_e,*/ L_tmp2_e; + assert( hStereoDft->res_cod_line_max <= L_FRAME8k ); + + IF( hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) + { + /* Windowing */ + /* overlapping parts */ + /*input_8k-=STEREO_DFT_OVL_8k;*/ + FOR( i = 0; i < STEREO_DFT_OVL_8k; i++ ) + { + // win[i] = input_8k[i] * hStereoDft->win_mdct_8k[i]; + win[i] = extract_h( Mpy_32_32( input_8k[i], hStereoDft->win_mdct_8k_fx[i] /*Q31*/ ) ); + move32(); + // win[L_FRAME8k + i] = input_8k[L_FRAME8k + i] * hStereoDft->win_mdct_8k[STEREO_DFT_OVL_8k - 1 - i]; + win[L_FRAME8k + i] = extract_h( Mpy_32_32( input_8k[L_FRAME8k + i], hStereoDft->win_mdct_8k_fx[STEREO_DFT_OVL_8k - 1 - i] /*Q31*/ ) ); + move32(); + } + /* middle part */ + FOR( ; i < L_FRAME8k; i++ ) + { + win[i] = extract_h( input_8k[i] ); + move32(); + } + + /* MDCT analysis */ + // TCX_MDCT_flt( win, MDCT_RES, STEREO_DFT_OVL_8k, L_FRAME8k - STEREO_DFT_OVL_8k, STEREO_DFT_OVL_8k, IVAS_CPE_DFT ); + MDCT_RES_e = 16; + move16(); + TCX_MDCT( win, MDCT_RES, &MDCT_RES_e, STEREO_DFT_OVL_8k, L_FRAME8k - STEREO_DFT_OVL_8k, STEREO_DFT_OVL_8k, IVAS_CPE_DFT ); + + /*Compute the DMX to RES for each band*/ + max_snr = 0; /*minimum gain for residual coding -> no coding*/ + move32(); + FOR( b = 0; b < hStereoDft->res_cod_band_max; b++ ) + { + /*Get side gain information and it is we*/ + panning_gain = hStereoDft->side_gain_fx[STEREO_DFT_OFFSET * STEREO_DFT_BAND_MAX + b]; + panning_gain_min = L_sub( MAX_32, L_abs( panning_gain ) ); + + // in_phase_ratio = ( panning_gain_min * panning_gain_min * hStereoDft->res_cod_NRG_M[b] ) / ( panning_gain_min * panning_gain_min * hStereoDft->res_cod_NRG_M[b] + hStereoDft->res_cod_NRG_S[b] + 1 ); + L_tmp1 = Mpy_32_32( Mpy_32_32( panning_gain_min, panning_gain_min ), hStereoDft->res_cod_NRG_M_fx[b] ); + L_tmp2 = L_tmp1; + L_tmp2_e = hStereoDft->res_cod_NRG_M_fx_e[b]; + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, hStereoDft->res_cod_NRG_S_fx[b], hStereoDft->res_cod_NRG_S_fx_e[b], &L_tmp2_e ); + L_tmp2 = BASOP_Util_Add_Mant32Exp( L_tmp2, L_tmp2_e, MAX_32, 0, &L_tmp2_e ); + in_phase_ratio = BASOP_Util_Divide3232_Scale_cadence( L_tmp1, L_tmp2, &in_phase_ratio_e ); + in_phase_ratio_e = add( in_phase_ratio_e, sub( hStereoDft->res_cod_NRG_M_fx_e[b], L_tmp2_e ) ); + in_phase_ratio = L_shl_sat( in_phase_ratio, in_phase_ratio_e ); // Q31 : bound from 0.0 to 1.0 + in_phase_ratio = L_max( 0, in_phase_ratio ); + // in_phase_ratio = check_bounds(in_phase_ratio, 0, 1); + + // res_cod_gain[b] = in_phase_ratio * STEREO_DFT_RES_COD_SNR_MIN + ( 1 - in_phase_ratio ) * STEREO_DFT_RES_COD_SNR_MAX; + res_cod_gain[b] = L_add( Mpy_32_32( in_phase_ratio, STEREO_DFT_RES_COD_SNR_MIN_Q25 ), Mpy_32_32( L_sub( MAX_32, in_phase_ratio ), STEREO_DFT_RES_COD_SNR_MAX ) ); // Q25 + move32(); + + /*get the maximum through bands*/ + if ( GT_32( res_cod_gain[b], max_snr ) ) + { + max_snr = res_cod_gain[b]; + move32(); + } + } + + /*Smooth max_snr because of several perturbations in computation*/ + hStereoDft->old_snr_fx = L_add( Mpy_32_32( 429496730 /*0.2f*/, max_snr ), Mpy_32_32( 1717986918 /*0.8f*/, hStereoDft->old_snr_fx ) ); + move32(); + max_snr = hStereoDft->old_snr_fx; + move32(); + + if ( LT_32( max_snr, STEREO_DFT_RES_COD_SNR_MIN_Q25 ) ) + { + max_snr = STEREO_DFT_RES_COD_SNR_MIN_Q25; + move32(); + } + + push_wmops( "residual_encode" ); + /* residual encoding */ + ECSQ_init_instance_fx( &ecsq_inst, 0 /*dummy index*/, &range_uni_enc_state ); + rc_uni_enc_init( &range_uni_enc_state ); + + ecsq_inst.bit_count_estimate = 0; + move32(); + ecsq_inst.config_index = sub( shl( hStereoDft->res_cod_mode[STEREO_DFT_OFFSET], 1 ), 1 ); + move16(); + + /* 7 bits (STEREO_DFT_RES_GLOBAL_GAIN_BITS) for global_gain_index, 2 bits for closing of the arithmetic coder, 8 safety bits to account for the size estimation accuracy */ + ECSQ_encode_target_SNR_fx( &ecsq_inst, MDCT_RES, MDCT_RES_e, hStereoDft->res_cod_line_max, max_snr, max_bits - ( *nb_bits ) - STEREO_DFT_RES_GLOBAL_GAIN_BITS - 2 - 8, NULL, &global_gain_index ); + IF( NE_16( global_gain_index, ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO ) ) + { + total_bit_count = rc_uni_enc_finish( &range_uni_enc_state ); + + IF( LE_16( total_bit_count, sub( sub( max_bits, *nb_bits ), STEREO_DFT_RES_GLOBAL_GAIN_BITS ) ) ) + { + Word16 idx; + UWord8 *byte_buffer; + + /* Global gain */ + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_GLOBAL_GAIN, global_gain_index, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + move16(); + + /* Push arithmetic coded bits */ + byte_buffer = range_uni_enc_state.byte_buffer; + FOR( idx = 0; idx < shr( total_bit_count, 3 ); ++idx ) + { + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_COD, byte_buffer[idx], 8 ); + } + IF( s_and( total_bit_count, 7 ) != 0 ) + { + /* move the last 1 to 7 bits from the MSB position of the last byte to the LSB postion */ + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_COD, shr( byte_buffer[idx], sub( 8, s_and( total_bit_count, 7 ) ) ), s_and( total_bit_count, 7 ) ); + } + ( *nb_bits ) = add( *nb_bits, total_bit_count ); + move16(); + } + ELSE + { + /* Global gain -> 127*/ + global_gain_index = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + move16(); + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_GLOBAL_GAIN, global_gain_index, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + move16(); + } + } + ELSE + { + /* Global gain -> 127*/ + push_indice( hBstr, IND_STEREO_DFT_RESIDUAL_GLOBAL_GAIN, global_gain_index, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_RES_GLOBAL_GAIN_BITS ); + move16(); + } + + pop_wmops(); + } + + + return; +} +#else void stereo_dft_enc_res( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ const float *input_8k, /* i : input buffer sampled at 8kHz*/ @@ -4384,29 +4570,29 @@ void stereo_dft_enc_res( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_write_BS() * * Write DFT stereo bitstream *-------------------------------------------------------------------------*/ - -void stereo_dft_enc_write_BS( +#ifdef IVAS_FLOAT_FIXED +void stereo_dft_enc_write_BS_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - int16_t *nb_bits /* o : number of bits written */ + Word16 *nb_bits /* o : number of bits written */ ) { - int16_t b, k_offset, itd, nb, nbands, sp_aud_decision0; - int16_t NFFT_inner, nbands_full; - int16_t no_GR_ord; - int16_t encoded_ind_GR[STEREO_DFT_BAND_MAX]; - int16_t encoded_ind_pred_GR[STEREO_DFT_BAND_MAX]; - int16_t sid_gIpd_index, sid_itd; - float cohBand[STEREO_DFT_BAND_MAX / 2]; + Word16 b, k_offset, itd, nb, nbands, sp_aud_decision0; + Word16 NFFT_inner, nbands_full; + Word16 no_GR_ord; + Word16 encoded_ind_GR[STEREO_DFT_BAND_MAX]; + Word16 encoded_ind_pred_GR[STEREO_DFT_BAND_MAX]; + Word16 sid_gIpd_index, sid_itd; + Word32 cohBand[STEREO_DFT_BAND_MAX / 2]; BSTR_ENC_HANDLE hBstr; STEREO_DFT_ENC_DATA_HANDLE hStereoDft; - int32_t core_brate; + Word32 core_brate; /*------------------------------------------------------------------* * Initialization @@ -4415,124 +4601,147 @@ void stereo_dft_enc_write_BS( hStereoDft = hCPE->hStereoDft; hBstr = hCPE->hMetaData; core_brate = hCPE->hCoreCoder[0]->core_brate; + move32(); sp_aud_decision0 = 0; - if ( hCPE->last_element_mode == IVAS_CPE_DFT ) + move16(); + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_DFT ) ) { sp_aud_decision0 = hCPE->hCoreCoder[0]->sp_aud_decision0; + move16(); } *nb_bits = 0; + move16(); k_offset = STEREO_DFT_OFFSET; + move16(); nbands_full = hStereoDft->nbands; + move16(); - if ( core_brate == FRAME_NO_DATA || core_brate == SID_2k40 ) + test(); + IF( EQ_32( core_brate, FRAME_NO_DATA ) || EQ_32( core_brate, SID_2k40 ) ) { - NFFT_inner = min( STEREO_DFT_N_32k_ENC, STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k ); + NFFT_inner = s_min( STEREO_DFT_N_32k_ENC, STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k ); hStereoDft->band_res[k_offset] = hStereoDft->hConfig->band_res; + move16(); hStereoDft->res_pred_mode[k_offset] = 0; + move16(); hStereoDft->res_cod_mode[k_offset] = 0; + move16(); } - else + ELSE { - NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k; + // NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k; + NFFT_inner = shl( inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth], 1 ); } /* set number of bands according to bandwidth after BWD */ -#ifndef IVAS_FLOAT_FIXED - hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); -#else hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); -#endif + move16(); - if ( core_brate == FRAME_NO_DATA ) + IF( EQ_32( core_brate, FRAME_NO_DATA ) ) { /* No data frame */ ( *nb_bits ) = 0; + move16(); return; } /* attack present */ /* attackPresent not sent in inactive frames, receiver assumes = 0 */ - if ( core_brate != SID_2k40 ) + IF( NE_32( core_brate, SID_2k40 ) ) { push_indice( hBstr, IND_STEREO_DFT_ATTACK_PRESENT, hStereoDft->attackPresent, 1 ); - ( *nb_bits )++; + ( *nb_bits ) = add( *nb_bits, 1 ); + move16(); } /* Writing coding residual coding mode into bitstream */ - if ( hStereoDft->hConfig->ada_wb_res_cod_mode && hCPE->hCoreCoder[0]->bwidth == WB ) + test(); + IF( hStereoDft->hConfig->ada_wb_res_cod_mode && EQ_16( hCPE->hCoreCoder[0]->bwidth, WB ) ) { push_indice( hBstr, IND_STEREO_DFT_RES_COD, hStereoDft->res_cod_mode[k_offset], 1 ); - ( *nb_bits )++; + ( *nb_bits ) = add( *nb_bits, 1 ); + move16(); hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->res_cod_mode[k_offset]]; - hStereoDft->res_pred_band_min = max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + move16(); + hStereoDft->res_pred_band_min = s_max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + move16(); } - if ( nbands_full < hStereoDft->nbands ) + if ( LT_16( nbands_full, hStereoDft->nbands ) ) { hStereoDft->reverb_flag = 0; + move16(); } /* Side gains */ hStereoDft->side_gain_flag_1 = 0; /* EC coding by default */ - side_gain_mode_decision( hStereoDft, encoded_ind_GR, sp_aud_decision0, hCPE->hCoreCoder[0]->last_core_brate ); + move16(); + side_gain_mode_decision_fx( hStereoDft, encoded_ind_GR, sp_aud_decision0, hCPE->hCoreCoder[0]->last_core_brate ); /* residual pred. gains */ hStereoDft->res_pred_flag_1 = 0; /* EC coding by default */ + move16(); - res_pred_gain_mode_decision( hStereoDft, encoded_ind_pred_GR, k_offset, hCPE->hCoreCoder[0]->last_core_brate ); + res_pred_gain_mode_decision_fx( hStereoDft, encoded_ind_pred_GR, k_offset, hCPE->hCoreCoder[0]->last_core_brate ); /*------------------------------------------------------------------* * write ITD indices *-----------------------------------------------------------------*/ - if ( core_brate != SID_2k40 ) + IF( NE_32( core_brate, SID_2k40 ) ) { - push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, ( hStereoDft->hItd->itd[k_offset] != 0 ), STEREO_DFT_ITD_MODE_NBITS ); - ( *nb_bits ) += STEREO_DFT_ITD_MODE_NBITS; /*ITD mode flag: 1bit*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, ( hStereoDft->hItd->itd_fx[k_offset] != 0 ), STEREO_DFT_ITD_MODE_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_MODE_NBITS ); /*ITD mode flag: 1bit*/ + move16(); } - if ( core_brate != SID_2k40 ) + IF( NE_32( core_brate, SID_2k40 ) ) { - if ( hStereoDft->hItd->itd[k_offset] ) + IF( hStereoDft->hItd->itd_fx[k_offset] ) { itd = hStereoDft->hItd->itd_index[k_offset]; - if ( itd > 255 ) + move16(); + IF( GT_16( itd, 255 ) ) { - itd -= 256; + itd = sub( itd, 256 ); - if ( itd < 20 ) + IF( LT_16( itd, 20 ) ) { push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 1, 1 ); /* use Huffman*/ push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ push_indice( hBstr, IND_STEREO_DFT_ITD_COD, dft_code_itd[itd], dft_len_itd[itd] ); - ( *nb_bits ) += dft_len_itd[itd] + 2; + ( *nb_bits ) = add( *nb_bits, add( dft_len_itd[itd], 2 ) ); + move16(); } - else + ELSE { push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 0, 1 ); /* don't use Huffman */ push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_ITD_NBITS - 1 ); - ( *nb_bits ) += STEREO_DFT_ITD_NBITS + 1; + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_NBITS + 1 ); + move16(); } } - else + ELSE { - if ( itd < 20 ) + IF( LT_16( itd, 20 ) ) { push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 1, 1 ); /* use Huffman*/ push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 0, 1 ); /* positive */ push_indice( hBstr, IND_STEREO_DFT_ITD_COD, dft_code_itd[itd], dft_len_itd[itd] ); - ( *nb_bits ) += dft_len_itd[itd] + 2; + ( *nb_bits ) = add( *nb_bits, add( dft_len_itd[itd], 2 ) ); + move16(); } - else + ELSE { /* don't use Huffman and positive*/ push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_ITD_NBITS + 1 ); - ( *nb_bits ) += STEREO_DFT_ITD_NBITS + 1; + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_NBITS + 1 ); + move16(); } } } @@ -4548,68 +4757,458 @@ void stereo_dft_enc_write_BS( /* Side Gain flag 1 */ nb = 0; - if ( hStereoDft->side_gain_flag_1 > 0 ) + move16(); + IF( hStereoDft->side_gain_flag_1 > 0 ) { push_indice( hBstr, IND_STEREO_DFT_SIDEGAIN_FLAG, hStereoDft->side_gain_flag_1, 2 ); - nb += 2; + nb = add( nb, 2 ); } - else + ELSE { push_indice( hBstr, IND_STEREO_DFT_SIDEGAIN_FLAG, hStereoDft->side_gain_flag_1, STEREO_DFT_FLAG_BITS ); - nb += STEREO_DFT_FLAG_BITS; + nb = add( nb, STEREO_DFT_FLAG_BITS ); } no_GR_ord = 3; + move16(); - if ( hStereoDft->side_gain_flag_1 == 0 ) + IF( hStereoDft->side_gain_flag_1 == 0 ) { - nb += write_bitstream_adapt_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, encoded_ind_GR, hStereoDft->nbands, hStereoDft->side_gain_flag_2, no_GR_ord ); + nb = add( nb, write_bitstream_adapt_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, encoded_ind_GR, hStereoDft->nbands, hStereoDft->side_gain_flag_2, no_GR_ord ) ); } - else + ELSE{ + IF( EQ_16( hStereoDft->side_gain_flag_1, 2 ) ){ + nb = add( nb, write_bitstream_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_ECDiff, hStereoDft->nbands, hStereoDft->side_gain_flag_2 - no_GR_ord ) ); +} +ELSE +{ + FOR( b = 0; b < hStereoDft->nbands; b++ ) { - if ( hStereoDft->side_gain_flag_1 == 2 ) - { - nb += write_bitstream_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_ECDiff, hStereoDft->nbands, hStereoDft->side_gain_flag_2 - no_GR_ord ); - } - else - { - for ( b = 0; b < hStereoDft->nbands; b++ ) - { - /*ILD*/ - push_indice( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_EC[b], STEREO_DFT_SIDEGAIN_NBITS ); - nb += STEREO_DFT_SIDEGAIN_NBITS; - } - } + /*ILD*/ + push_indice( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_EC[b], STEREO_DFT_SIDEGAIN_NBITS ); + nb = add( nb, STEREO_DFT_SIDEGAIN_NBITS ); } +} +} - /* nb bits are used for side gain*/ - ( *nb_bits ) += nb; +/* nb bits are used for side gain*/ +( *nb_bits ) = add( *nb_bits, nb ); +move16(); #ifdef DEBUG_MODE_DFT_BITS - fprintf( SG_bits, "%d ", nb ); +fprintf( SG_bits, "%d ", nb ); #endif - nb = 0; +nb = 0; +move16(); - if ( core_brate == SID_2k40 ) +IF( EQ_32( core_brate, SID_2k40 ) ) +{ + stereo_dft_enc_sid_calc_coh_fx( hStereoDft, hCPE->hStereoCng->prev_cohBand_fx, &hCPE->hStereoCng->td_active, &hCPE->hStereoCng->first_SID, cohBand ); + + IF( LE_16( *nb_bits, ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 ) ) ) { - stereo_dft_enc_sid_calc_coh( hStereoDft, hCPE->hStereoCng->prev_cohBand, &hCPE->hStereoCng->td_active, &hCPE->hStereoCng->first_SID, cohBand ); + IF( NE_32( hStereoDft->hItd->itd_fx[k_offset], 0 ) ) + { + /* Re-quantize ITD with lower resolution for Stereo CNG */ + itd = hStereoDft->hItd->itd_index[k_offset]; + move16(); + if ( GT_16( itd, 255 ) ) + { + itd = sub( itd, 256 ); + } + itd = shr( itd, STEREO_DFT_SID_ITD_FAC ); - if ( *nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 ) ) + sid_itd = itd && 1; + move16(); + } + ELSE { - if ( hStereoDft->hItd->itd[k_offset] != 0 ) + sid_itd = 0; + move16(); + } + + push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, sid_itd, STEREO_DFT_ITD_MODE_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_ITD_MODE_NBITS ); /*ITD mode flag: 1bit*/ + move16(); + + IF( sid_itd ) + { + itd = hStereoDft->hItd->itd_index[k_offset]; + move16(); + IF( GT_16( itd, 255 ) ) { - /* Re-quantize ITD with lower resolution for Stereo CNG */ - itd = hStereoDft->hItd->itd_index[k_offset]; - if ( itd > 255 ) + itd = sub( itd, 256 ); + itd = shr( itd, STEREO_DFT_SID_ITD_FAC ); + + if ( GT_16( itd, ( ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1 ) ) ) { - itd -= 256; + itd = ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1; + move16(); } - itd = itd >> STEREO_DFT_SID_ITD_FAC; - sid_itd = itd && 1; + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_SID_ITD_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_SID_ITD_NBITS + 1 ); + move16(); } - else + ELSE { - sid_itd = 0; + itd = shr( itd, STEREO_DFT_SID_ITD_FAC ); + + if ( GT_16( itd, ( ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1 ) ) ) + { + itd = ( 1 << STEREO_DFT_SID_ITD_NBITS ) - 1; + move16(); + } + + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 0, 1 ); /* Positive */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_SID_ITD_NBITS ); + ( *nb_bits ) = add( *nb_bits, STEREO_DFT_SID_ITD_NBITS + 1 ); + move16(); + } + } + } +} + +/*------------------------------------------------------------------* + * write IPD indices + *-----------------------------------------------------------------*/ + +IF( NE_32( core_brate, SID_2k40 ) ) +{ + push_indice( hBstr, IND_STEREO_DFT_NO_IPD_FLAG, hStereoDft->no_ipd_flag, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); /*IPD mode flag: 1bit*/ + + IF( hStereoDft->no_ipd_flag == 0 ) + { + push_indice( hBstr, IND_STEREO_DFT_GIPD, hStereoDft->gipd_index, STEREO_DFT_GIPD_NBITS ); + nb = add( nb, STEREO_DFT_GIPD_NBITS ); + } +} +ELSE IF( LE_16( *nb_bits, ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_FLAG_BITS - STEREO_DFT_SID_GIPD_NBITS ) ) ) +{ + push_indice( hBstr, IND_STEREO_DFT_NO_IPD_FLAG, hStereoDft->no_ipd_flag, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); /*IPD mode flag: 1bit*/ + + IF( hStereoDft->no_ipd_flag == 0 ) + { + stereo_dft_quantize_ipd_fx( &hStereoDft->sid_gipd_fx, &hStereoDft->sid_gipd_fx, &sid_gIpd_index, STEREO_DFT_SID_GIPD_NBITS ); + push_indice( hBstr, IND_STEREO_DFT_GIPD, sid_gIpd_index, STEREO_DFT_SID_GIPD_NBITS ); + nb = add( nb, STEREO_DFT_SID_GIPD_NBITS ); + } +} + + +#ifdef DEBUG_MODE_DFT_BITS +fprintf( IPD_bits, "%d ", nb ); +#endif +( *nb_bits ) = add( *nb_bits, nb ); + +/*----------------------------------------------------------------* + * Residual prediction + *----------------------------------------------------------------*/ + +nb = 0; /* bits for residual pred gains */ +move16(); +IF( hStereoDft->res_pred_mode[k_offset] ) +{ + IF( hStereoDft->attackPresent == 0 ) + { + nbands = s_min( hStereoDft->nbands, STEREO_DFT_RES_PRED_BAND_MAX ); + b = hStereoDft->res_pred_band_min; + move16(); + + /*Adaptive SF*/ + IF( hStereoDft->hConfig->res_cod_mode == STEREO_DFT_RES_COD_OFF ) + { + /*read flag*/ + push_indice( hBstr, IND_STEREO_DFT_REVERB_MODE, hStereoDft->reverb_flag, STEREO_DFT_REVERB_MODE_NBITS ); + nb = add( nb, STEREO_DFT_REVERB_MODE_NBITS ); + IF( hStereoDft->reverb_flag ) + { + nbands = sub( nbands, STEREO_DFT_RES_PRED_BAND_MIN_CONST ); + } + } + + /* Res Pred Gain flag 0 */ + IF( hStereoDft->res_pred_flag_1 > 0 ) + { + push_indice( hBstr, IND_STEREO_DFT_RES_PRED_FLAG, hStereoDft->res_pred_flag_1, 2 ); + nb = add( nb, 2 ); /*pred gain mode flag: 2 bits*/ + } + ELSE + { + push_indice( hBstr, IND_STEREO_DFT_RES_PRED_FLAG, hStereoDft->res_pred_flag_1, STEREO_DFT_FLAG_BITS ); + nb = add( nb, STEREO_DFT_FLAG_BITS ); /*pred gain mode flag: 1bit*/ + } + + no_GR_ord = 2; + move16(); + IF( hStereoDft->res_pred_flag_1 == 0 ) + { + IF( EQ_16( encoded_ind_pred_GR[0], dft_maps_rpg[8 * NO_SYMB_GR_PRED_G] ) ) + { + nb = add( nb, write_GR1( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, encoded_ind_pred_GR, 1 ) ); + } + ELSE + { + nb = add( nb, write_bitstream_adapt_GR( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, encoded_ind_pred_GR, nbands - hStereoDft->res_pred_band_min, hStereoDft->res_pred_flag_2, 2 ) ); + } + } + ELSE + { + IF( EQ_16( hStereoDft->res_pred_flag_1, 2 ) ) + { + nb = add( nb, write_bitstream_GR( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, &hStereoDft->res_pred_index_ECDiff[hStereoDft->res_pred_band_min], nbands - hStereoDft->res_pred_band_min, hStereoDft->res_pred_flag_2 - no_GR_ord ) ); + } + ELSE + { + FOR( b = hStereoDft->res_pred_band_min; b < nbands; b++ ) + { + push_indice( hBstr, IND_STEREO_DFT_PRED_GAIN_COD, hStereoDft->res_pred_index_EC[b], STEREO_DFT_RES_GAINS_BITS ); + nb = add( nb, STEREO_DFT_RES_GAINS_BITS ); + } + } + } + } + ELSE + { + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, sub( hStereoDft->nbands, hStereoDft->res_pred_band_min ) ); + } +} +ELSE +{ + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, hStereoDft->nbands - hStereoDft->res_pred_band_min ); +} + +( *nb_bits ) = add( *nb_bits, nb ); + +IF( EQ_32( core_brate, SID_2k40 ) ) +{ + stereo_dft_enc_sid_coh_fx( hBstr, hCPE->hStereoCng->mem_cohBand_fx, hStereoDft->nbands, nb_bits, cohBand ); +} + + +return; +} +#else +void stereo_dft_enc_write_BS( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + int16_t *nb_bits /* o : number of bits written */ +) +{ + int16_t b, k_offset, itd, nb, nbands, sp_aud_decision0; + int16_t NFFT_inner, nbands_full; + int16_t no_GR_ord; + int16_t encoded_ind_GR[STEREO_DFT_BAND_MAX]; + int16_t encoded_ind_pred_GR[STEREO_DFT_BAND_MAX]; + int16_t sid_gIpd_index, sid_itd; + float cohBand[STEREO_DFT_BAND_MAX / 2]; + BSTR_ENC_HANDLE hBstr; + STEREO_DFT_ENC_DATA_HANDLE hStereoDft; + int32_t core_brate; + + /*------------------------------------------------------------------* + * Initialization + *-----------------------------------------------------------------*/ + + hStereoDft = hCPE->hStereoDft; + hBstr = hCPE->hMetaData; + core_brate = hCPE->hCoreCoder[0]->core_brate; + + sp_aud_decision0 = 0; + if ( hCPE->last_element_mode == IVAS_CPE_DFT ) + { + sp_aud_decision0 = hCPE->hCoreCoder[0]->sp_aud_decision0; + } + + *nb_bits = 0; + k_offset = STEREO_DFT_OFFSET; + + nbands_full = hStereoDft->nbands; + + if ( core_brate == FRAME_NO_DATA || core_brate == SID_2k40 ) + { + NFFT_inner = min( STEREO_DFT_N_32k_ENC, STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k ); + hStereoDft->band_res[k_offset] = hStereoDft->hConfig->band_res; + hStereoDft->res_pred_mode[k_offset] = 0; + hStereoDft->res_cod_mode[k_offset] = 0; + } + else + { + NFFT_inner = STEREO_DFT_N_MAX_ENC * inner_frame_tbl[hCPE->hCoreCoder[0]->bwidth] / L_FRAME48k; + } + + /* set number of bands according to bandwidth after BWD */ +#ifndef IVAS_FLOAT_FIXED + hStereoDft->nbands = stereo_dft_band_config( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); +#else + hStereoDft->nbands = stereo_dft_band_config_fx( hStereoDft->band_limits, hStereoDft->band_res[k_offset], NFFT_inner, ENC ); +#endif + + if ( core_brate == FRAME_NO_DATA ) + { + /* No data frame */ + ( *nb_bits ) = 0; + return; + } + + /* attack present */ + /* attackPresent not sent in inactive frames, receiver assumes = 0 */ + if ( core_brate != SID_2k40 ) + { + push_indice( hBstr, IND_STEREO_DFT_ATTACK_PRESENT, hStereoDft->attackPresent, 1 ); + ( *nb_bits )++; + } + + /* Writing coding residual coding mode into bitstream */ + if ( hStereoDft->hConfig->ada_wb_res_cod_mode && hCPE->hCoreCoder[0]->bwidth == WB ) + { + push_indice( hBstr, IND_STEREO_DFT_RES_COD, hStereoDft->res_cod_mode[k_offset], 1 ); + ( *nb_bits )++; + hStereoDft->res_cod_band_max = dft_band_res_cod[hStereoDft->hConfig->band_res][hStereoDft->res_cod_mode[k_offset]]; + hStereoDft->res_pred_band_min = max( STEREO_DFT_RES_PRED_BAND_MIN, hStereoDft->res_cod_band_max ); + } + + + if ( nbands_full < hStereoDft->nbands ) + { + hStereoDft->reverb_flag = 0; + } + + /* Side gains */ + hStereoDft->side_gain_flag_1 = 0; /* EC coding by default */ + side_gain_mode_decision( hStereoDft, encoded_ind_GR, sp_aud_decision0, hCPE->hCoreCoder[0]->last_core_brate ); + + /* residual pred. gains */ + hStereoDft->res_pred_flag_1 = 0; /* EC coding by default */ + + res_pred_gain_mode_decision( hStereoDft, encoded_ind_pred_GR, k_offset, hCPE->hCoreCoder[0]->last_core_brate ); + + /*------------------------------------------------------------------* + * write ITD indices + *-----------------------------------------------------------------*/ + + if ( core_brate != SID_2k40 ) + { + push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, ( hStereoDft->hItd->itd[k_offset] != 0 ), STEREO_DFT_ITD_MODE_NBITS ); + ( *nb_bits ) += STEREO_DFT_ITD_MODE_NBITS; /*ITD mode flag: 1bit*/ + } + + if ( core_brate != SID_2k40 ) + { + if ( hStereoDft->hItd->itd[k_offset] ) + { + itd = hStereoDft->hItd->itd_index[k_offset]; + if ( itd > 255 ) + { + itd -= 256; + + if ( itd < 20 ) + { + push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 1, 1 ); /* use Huffman*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, dft_code_itd[itd], dft_len_itd[itd] ); + ( *nb_bits ) += dft_len_itd[itd] + 2; + } + else + { + push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 0, 1 ); /* don't use Huffman */ + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 1, 1 ); /* negative */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_ITD_NBITS - 1 ); + ( *nb_bits ) += STEREO_DFT_ITD_NBITS + 1; + } + } + else + { + if ( itd < 20 ) + { + push_indice( hBstr, IND_STEREO_DFT_ITD_HUFF, 1, 1 ); /* use Huffman*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_NEG, 0, 1 ); /* positive */ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, dft_code_itd[itd], dft_len_itd[itd] ); + ( *nb_bits ) += dft_len_itd[itd] + 2; + } + else + { + /* don't use Huffman and positive*/ + push_indice( hBstr, IND_STEREO_DFT_ITD_COD, itd, STEREO_DFT_ITD_NBITS + 1 ); + ( *nb_bits ) += STEREO_DFT_ITD_NBITS + 1; + } + } + } + } + +#ifdef DEBUG_MODE_DFT_BITS + fprintf( ITD_bits, "%d ", *nb_bits ); +#endif + + /*------------------------------------------------------------------* + * write Side gain indices + *-----------------------------------------------------------------*/ + + /* Side Gain flag 1 */ + nb = 0; + if ( hStereoDft->side_gain_flag_1 > 0 ) + { + push_indice( hBstr, IND_STEREO_DFT_SIDEGAIN_FLAG, hStereoDft->side_gain_flag_1, 2 ); + nb += 2; + } + else + { + push_indice( hBstr, IND_STEREO_DFT_SIDEGAIN_FLAG, hStereoDft->side_gain_flag_1, STEREO_DFT_FLAG_BITS ); + nb += STEREO_DFT_FLAG_BITS; + } + + no_GR_ord = 3; + + if ( hStereoDft->side_gain_flag_1 == 0 ) + { + nb += write_bitstream_adapt_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, encoded_ind_GR, hStereoDft->nbands, hStereoDft->side_gain_flag_2, no_GR_ord ); + } + else + { + if ( hStereoDft->side_gain_flag_1 == 2 ) + { + nb += write_bitstream_GR( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_ECDiff, hStereoDft->nbands, hStereoDft->side_gain_flag_2 - no_GR_ord ); + } + else + { + for ( b = 0; b < hStereoDft->nbands; b++ ) + { + /*ILD*/ + push_indice( hBstr, IND_STEREO_DFT_SIDEGAINS, hStereoDft->side_gain_index_EC[b], STEREO_DFT_SIDEGAIN_NBITS ); + nb += STEREO_DFT_SIDEGAIN_NBITS; + } + } + } + + /* nb bits are used for side gain*/ + ( *nb_bits ) += nb; +#ifdef DEBUG_MODE_DFT_BITS + fprintf( SG_bits, "%d ", nb ); +#endif + nb = 0; + + if ( core_brate == SID_2k40 ) + { + stereo_dft_enc_sid_calc_coh( hStereoDft, hCPE->hStereoCng->prev_cohBand, &hCPE->hStereoCng->td_active, &hCPE->hStereoCng->first_SID, cohBand ); + + if ( *nb_bits <= ( ( IVAS_SID_5k2 - SID_2k40 ) / FRAMES_PER_SEC - SID_FORMAT_NBITS - STEREO_DFT_ITD_MODE_NBITS - STEREO_DFT_SID_ITD_NBITS - 1 ) ) + { + if ( hStereoDft->hItd->itd[k_offset] != 0 ) + { + /* Re-quantize ITD with lower resolution for Stereo CNG */ + itd = hStereoDft->hItd->itd_index[k_offset]; + if ( itd > 255 ) + { + itd -= 256; + } + itd = itd >> STEREO_DFT_SID_ITD_FAC; + + sid_itd = itd && 1; + } + else + { + sid_itd = 0; } push_indice( hBstr, IND_STEREO_DFT_ITD_MODE, sid_itd, STEREO_DFT_ITD_MODE_NBITS ); @@ -4767,7 +5366,7 @@ void stereo_dft_enc_write_BS( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_enc_compute_prm() @@ -5994,7 +6593,82 @@ static void stereo_dft_enc_compute_prm( * * *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void side_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_GR[], + const Word16 sp_aud_decision0, /* i : Speech/audio decision 0 */ + const Word32 last_core_brate /* i : Last core bitrate */ +) +{ + Word16 try_diff, nb_diff, no_GR_ord, n_bits, i; + + try_diff = sp_aud_decision0; + move16(); + IF( try_diff ) + { + IF( EQ_16( hStereoDft->side_gain_counter, STEREO_DFT_FEC_THRESHOLD ) ) + { + try_diff = 0; + move16(); + hStereoDft->side_gain_counter = 0; + move16(); + } + } + ELSE + { + hStereoDft->side_gain_counter = 0; + move16(); + } + + /* If last frame SID/NO_DATA do not use differential coding */ + if ( LE_32( last_core_brate, SID_2k40 ) ) + { + try_diff = 0; + move16(); + } + no_GR_ord = 3; + move16(); + hStereoDft->side_gain_flag_2 = adapt_GR_ief_fx( hStereoDft->side_gain_index_EC, hStereoDft->side_gain_index_ECDiff, hStereoDft->side_gain_index_ECprevious, + hStereoDft->nbands, NO_SYMB_GR_SIDE_G, &n_bits, encoded_ind_GR, dft_maps_sg, no_GR_ord, &nb_diff, + hStereoDft->side_gain_counter, &hStereoDft->side_gain_bitdiff_lp_fx, &hStereoDft->q_side_gain_bitdiff_lp, try_diff ); + move16(); + + FOR( i = 0; i < hStereoDft->nbands; i++ ) + { + hStereoDft->side_gain_index_ECprevious[i] = hStereoDft->side_gain_index_EC[i]; + move16(); + } + + IF( GT_16( n_bits, sub( imult1616( hStereoDft->nbands, STEREO_DFT_SIDE_GAIN_NBITS ), 1 ) ) ) + { + /* use fixed rate */ + hStereoDft->side_gain_flag_1 = 3; + move16(); + hStereoDft->side_gain_counter = 0; + move16(); + } + ELSE + { + IF( GE_32( hStereoDft->side_gain_flag_2, no_GR_ord ) ) + { + hStereoDft->side_gain_flag_1 = 2; + move16(); + hStereoDft->side_gain_counter = add( hStereoDft->side_gain_counter, 1 ); + move16(); + } + ELSE + { + hStereoDft->side_gain_flag_1 = 0; + move16(); + hStereoDft->side_gain_counter = 0; + move16(); + } + } + return; +} +#else static void side_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ int16_t encoded_ind_GR[], @@ -6024,16 +6698,10 @@ static void side_gain_mode_decision( try_diff = 0; } no_GR_ord = 3; -#ifdef IVAS_FLOAT_FIXED - hStereoDft->side_gain_flag_2 = adapt_GR_ief_fx( hStereoDft->side_gain_index_EC, hStereoDft->side_gain_index_ECDiff, hStereoDft->side_gain_index_ECprevious, - hStereoDft->nbands, NO_SYMB_GR_SIDE_G, &n_bits, encoded_ind_GR, dft_maps_sg, no_GR_ord, &nb_diff, - hStereoDft->side_gain_counter, &hStereoDft->side_gain_bitdiff_lp_fx, &hStereoDft->q_side_gain_bitdiff_lp, try_diff ); -#else + hStereoDft->side_gain_flag_2 = adapt_GR_ief( hStereoDft->side_gain_index_EC, hStereoDft->side_gain_index_ECDiff, hStereoDft->side_gain_index_ECprevious, hStereoDft->nbands, NO_SYMB_GR_SIDE_G, &n_bits, encoded_ind_GR, dft_maps_sg, no_GR_ord, &nb_diff, hStereoDft->side_gain_counter, &hStereoDft->side_gain_bitdiff_lp, try_diff ); -#endif - for ( i = 0; i < hStereoDft->nbands; i++ ) { @@ -6062,7 +6730,7 @@ static void side_gain_mode_decision( return; } - +#endif /*---------------------------------------------------------------------* * res_pred_gain_mode_decision() @@ -6070,6 +6738,103 @@ static void side_gain_mode_decision( * *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void res_pred_gain_mode_decision_fx( + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ + Word16 encoded_ind_pred_GR[], + const Word16 k_offset, /* i : Parameter offset */ + const Word32 last_core_brate /* i : Last core bitrate */ +) +{ + Word16 nb_diff, try_diff, no_GR_ord, i, n_bits; + Word16 nbands; + + /* Residual Prediction Gain */ + IF( hStereoDft->res_pred_mode[k_offset] ) + { + IF( hStereoDft->attackPresent == 0 ) + { + nbands = s_min( hStereoDft->nbands, STEREO_DFT_RES_PRED_BAND_MAX ); + + if ( hStereoDft->reverb_flag ) + { + nbands = sub( nbands, STEREO_DFT_RES_PRED_BAND_MIN_CONST ); + } + + try_diff = 1; + move16(); + IF( EQ_16( hStereoDft->res_pred_counter, STEREO_DFT_FEC_THRESHOLD ) ) + { + try_diff = 0; + move16(); + hStereoDft->res_pred_counter = 0; + move16(); + } + + /* If last frame SID/NO_DATA do not use differential coding */ + IF( LE_32( last_core_brate, SID_2k40 ) ) + { + try_diff = 0; + move16(); + } + + no_GR_ord = 2; + move16(); + + hStereoDft->res_pred_flag_2 = adapt_GR_rpg1_ief( &hStereoDft->res_pred_index_EC[hStereoDft->res_pred_band_min], &hStereoDft->res_pred_index_ECDiff[hStereoDft->res_pred_band_min], &hStereoDft->res_pred_index_ECprevious[hStereoDft->res_pred_band_min], nbands - hStereoDft->res_pred_band_min, NO_SYMB_GR_PRED_G, &n_bits, encoded_ind_pred_GR, dft_maps_rpg, &nb_diff, no_GR_ord, try_diff ); + move16(); + + FOR( i = 0; i < nbands; i++ ) + { + hStereoDft->res_pred_index_ECprevious[i] = hStereoDft->res_pred_index_EC[i]; + move16(); + } + + FOR( ; i < hStereoDft->nbands; i++ ) + { + hStereoDft->res_pred_index_ECprevious[i] = 0; + move16(); + } + + IF( GT_16( n_bits, sub( imult1616( sub( nbands, hStereoDft->res_pred_band_min ), STEREO_DFT_RES_GAINS_BITS ), 1 ) ) ) + { + hStereoDft->res_pred_flag_1 = 3; + move16(); + hStereoDft->res_pred_counter = 0; + move16(); + } + ELSE + { + IF( GT_16( hStereoDft->res_pred_flag_2, 1 ) ) + { + /* differential coding */ + hStereoDft->res_pred_flag_1 = 2; + move16(); + hStereoDft->res_pred_counter = add( hStereoDft->res_pred_counter, 1 ); + move16(); + } + ELSE + { + hStereoDft->res_pred_counter = 0; + move16(); + hStereoDft->res_pred_flag_1 = 0; + move16(); + } + } + } + ELSE + { + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, hStereoDft->nbands ); + } + } + ELSE + { + set16_fx( hStereoDft->res_pred_index_ECprevious, 0, hStereoDft->nbands ); + } + + return; +} +#else static void res_pred_gain_mode_decision( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i : DFT stereo encoder handle */ int16_t encoded_ind_pred_GR[], @@ -6151,7 +6916,7 @@ static void res_pred_gain_mode_decision( return; } - +#endif /*------------------------------------------------------------------------- * stereo_dft_calc_mean_bipd() diff --git a/lib_enc/ivas_stereo_dft_enc_itd.c b/lib_enc/ivas_stereo_dft_enc_itd.c index 2115cc652..70820aaee 100644 --- a/lib_enc/ivas_stereo_dft_enc_itd.c +++ b/lib_enc/ivas_stereo_dft_enc_itd.c @@ -1151,7 +1151,7 @@ static Word32 peak_detect_fx( // else if ( detected_itd_flag == 0 && *max_max > 1.5f * avg_max && *prev_max > 1.5f * *prev_avg_max && abs( *index - *prev_index ) <= 2 ) ELSE IF( detected_itd_flag == 0 && BASOP_Util_Cmp_Mant32Exp( *max_max, 0, Mpy_32_32( 1610612736, avg_max ), add( sum_max_e, 1 ) ) > 0 && BASOP_Util_Cmp_Mant32Exp( *prev_max, 0, Mpy_32_32( 1610612736, *prev_avg_max ), add( *prev_avg_max_e, 1 ) ) > 0 && LE_16( abs_s( sub( *index, *prev_index ) ), 2 ) ) { - wfac = 1610612736; // 1.5f in Q29 + wfac = 805306368; // 1.5f in Q29 move32(); } ELSE @@ -2013,8 +2013,6 @@ void stereo_dft_enc_compute_itd_fx( test(); IF( hCPE->hCoreCoder[0]->Opt_DTX_ON && EQ_16( hCPE->element_mode, IVAS_CPE_DFT ) ) { - Word16 xspec_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC]; - set16_fx( xspec_smooth_fx_tmp_e, hStereoDft->xspec_smooth_fx_e, STEREO_DFT_N_32k_ENC ); Word16 Spd_L_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC / 2], Spd_R_smooth_fx_tmp_e[STEREO_DFT_N_32k_ENC / 2]; set16_fx( Spd_L_smooth_fx_tmp_e, hStereoDft->Spd_L_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); set16_fx( Spd_R_smooth_fx_tmp_e, hStereoDft->Spd_R_smooth_fx_e, STEREO_DFT_N_32k_ENC / 2 ); @@ -2029,6 +2027,7 @@ void stereo_dft_enc_compute_itd_fx( { /* Reset cross spectrum when there is hangover */ set32_fx( hStereoDft->xspec_smooth_fx, 0, STEREO_DFT_N_32k_ENC ); + set16_fx( hStereoDft->xspec_smooth_fx_e, 0, STEREO_DFT_N_32k_ENC ); hStereoDft->resetFrames = 0; move16(); hStereoDft->currentNumUpdates = 0; @@ -2053,12 +2052,12 @@ void stereo_dft_enc_compute_itd_fx( { /* Low pass filter cross L/R power spectrum */ // hStereoDft->xspec_smooth[2 * i] = ( 1.f - cng_xcorr_filt ) * hStereoDft->xspec_smooth[2 * i] + cng_xcorr_filt * xcorr[2 * i]; - hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->xspec_smooth_fx[2 * i] ), xspec_smooth_fx_tmp_e[2 * i], - Mpy_32_32( cng_xcorr_filt, xcorr[2 * i] ), xcorr_e[2 * i], &xspec_smooth_fx_tmp_e[2 * i] ); + hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->xspec_smooth_fx[2 * i] ), hStereoDft->xspec_smooth_fx_e[2 * i], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i] ), xcorr_e[2 * i], &hStereoDft->xspec_smooth_fx_e[2 * i] ); move32(); // hStereoDft->xspec_smooth[2 * i + 1] = ( 1.f - cng_xcorr_filt ) * hStereoDft->xspec_smooth[2 * i + 1] + cng_xcorr_filt * xcorr[2 * i + 1]; - hStereoDft->xspec_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->xspec_smooth_fx[2 * i + 1] ), xspec_smooth_fx_tmp_e[2 * i + 1], - Mpy_32_32( cng_xcorr_filt, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xspec_smooth_fx_tmp_e[2 * i + 1] ); + hStereoDft->xspec_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hStereoDft->xspec_smooth_fx[2 * i + 1] ), hStereoDft->xspec_smooth_fx_e[2 * i + 1], + Mpy_32_32( cng_xcorr_filt, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &hStereoDft->xspec_smooth_fx_e[2 * i + 1] ); move32(); /* Low pass filter L/R power spectrum */ @@ -2127,18 +2126,18 @@ void stereo_dft_enc_compute_itd_fx( { // mvr2r( hStereoDft->xspec_smooth, hItd->xcorr_smooth, NFFT ); Copy32( hStereoDft->xspec_smooth_fx, hItd->xcorr_smooth_fx, NFFT ); - Copy( xspec_smooth_fx_tmp_e, xcorr_smooth_fx_tmp_e, NFFT ); + Copy( hStereoDft->xspec_smooth_fx_e, xcorr_smooth_fx_tmp_e, NFFT ); } FOR( i = 1; i < NFFT / 2; i++ ) { /* Low pass filter cross L/R power spectrum */ // hStereoDft->xspec_smooth[2 * i] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->xspec_smooth[2 * i] + XSPEC_ALPHA * xcorr[2 * i]; - hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i] ), xspec_smooth_fx_tmp_e[2 * i], - Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i] ), xcorr_e[2 * i], &xspec_smooth_fx_tmp_e[2 * i] ); + hStereoDft->xspec_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i] ), hStereoDft->xspec_smooth_fx_e[2 * i], + Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i] ), xcorr_e[2 * i], &hStereoDft->xspec_smooth_fx_e[2 * i] ); move32(); // hStereoDft->xspec_smooth[2 * i + 1] = ( 1.f - XSPEC_ALPHA ) * hStereoDft->xspec_smooth[2 * i + 1] + XSPEC_ALPHA * xcorr[2 * i + 1]; - hStereoDft->xspec_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i + 1] ), xspec_smooth_fx_tmp_e[2 * i + 1], - Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &xspec_smooth_fx_tmp_e[2 * i + 1] ); + hStereoDft->xspec_smooth_fx[2 * i + 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( ( MAX_32 - XSPEC_ALPHA_Q31 ), hStereoDft->xspec_smooth_fx[2 * i + 1] ), hStereoDft->xspec_smooth_fx_e[2 * i + 1], + Mpy_32_32( XSPEC_ALPHA_Q31, xcorr[2 * i + 1] ), xcorr_e[2 * i + 1], &hStereoDft->xspec_smooth_fx_e[2 * i + 1] ); move32(); // hItd->xcorr_smooth[2 * i] = ( 1.f - cng_xcorr_filt ) * hItd->xcorr_smooth[2 * i] + cng_xcorr_filt * xcorr[2 * i]; hItd->xcorr_smooth_fx[2 * i] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( L_sub( MAX_32, cng_xcorr_filt ), hItd->xcorr_smooth_fx[2 * i] ), xcorr_smooth_fx_tmp_e[2 * i], @@ -2223,19 +2222,6 @@ void stereo_dft_enc_compute_itd_fx( /* RESCALING TO COMMON EXP */ max_exp = MIN_16; move16(); - FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) - { - max_exp = s_max( max_exp, xspec_smooth_fx_tmp_e[i] ); - } - hStereoDft->xspec_smooth_fx_e = max_exp; - move16(); - FOR( i = 0; i < STEREO_DFT_N_32k_ENC; i++ ) - { - hStereoDft->xspec_smooth_fx[i] = L_shr_r( hStereoDft->xspec_smooth_fx[i], sub( hStereoDft->xspec_smooth_fx_e, xspec_smooth_fx_tmp_e[i] ) ); - move32(); - } - max_exp = MIN_16; - move16(); FOR( i = 0; i < STEREO_DFT_N_32k_ENC / 2; i++ ) { max_exp = s_max( max_exp, Spd_L_smooth_fx_tmp_e[i] ); diff --git a/lib_enc/ivas_stereo_eclvq_enc.c b/lib_enc/ivas_stereo_eclvq_enc.c index 8fecfc414..39ededb64 100644 --- a/lib_enc/ivas_stereo_eclvq_enc.c +++ b/lib_enc/ivas_stereo_eclvq_enc.c @@ -34,11 +34,13 @@ #include "options.h" #include #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_enc.h" #include #include "prot.h" +#include "prot_fx.h" #include "wmc_auto.h" /* used only for norm_s in the code_length_from_count function */ #include "stl.h" @@ -50,30 +52,61 @@ * * ---------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED static double log_base2( double x ) { return log( x ) * INV_LOG_2; } +#endif /*--------------------------------------------------------------- * get_sign() * * * ---------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static Word16 get_sign_fx( Word16 n ) +{ + return extract_l( L_shr( (UWord16) n, 15 ) ); /* extract the sign bit */ +} +#else static int16_t get_sign( int16_t n ) { return (uint16_t) n >> 15; /* extract the sign bit */ } - +#endif /*--------------------------------------------------------------- * ECSQ_quantize_vector() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void ECSQ_quantize_vector_fx( + const Word32 *input, + const Word16 input_e, + const Word32 global_gain, // Q15 + const Word16 N, + Word16 *output ) +{ + Word16 i; + Word32 inv_global_gain; + Word16 inv_global_gain_e; + + // inv_global_gain = 1.0f / global_gain; + inv_global_gain = BASOP_Util_Divide3232_Scale_cadence( ONE_IN_Q15, global_gain, &inv_global_gain_e ); + inv_global_gain = L_shl( inv_global_gain, inv_global_gain_e ); // Q31 + FOR( i = 0; i < N; ++i ) + { + // output[i] = (int16_t) round_f( input[i] * inv_global_gain ); + output[i] = extract_l( L_shr_r( Mpy_32_32( input[i], inv_global_gain ), sub( 31, input_e ) ) ); + move16(); + } + return; +} +#else void ECSQ_quantize_vector( const float *input, const float global_gain, @@ -91,6 +124,7 @@ void ECSQ_quantize_vector( return; } +#endif /*--------------------------------------------------------------- * ECSQ_compute_optimal_gain() @@ -98,7 +132,43 @@ void ECSQ_quantize_vector( * compute the optimal global gain for dequantization of output * if all the values in output are zero, it returns 0 * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +Word32 ECSQ_compute_optimal_gain_fx( // Q15 + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word16 *output ) +{ + Word16 i; + Word32 sum_sq_output; + Word32 sum_input_output; + Word32 optimal_global_gain; + Word16 optimal_global_gain_e; + + sum_sq_output = 0; + move32(); + sum_input_output = 0; + move32(); + FOR( i = 0; i < N; ++i ) + { + // sum_sq_output += (float) output[i] * (float) output[i]; + sum_sq_output = L_add( sum_sq_output, L_shl( L_mult0( output[i], output[i] ), 15 ) ); // Q15 + // sum_input_output += input[i] * (float) output[i]; + sum_input_output = L_add( sum_input_output, L_shr( W_extract_l( W_mult0_32_32( input[i], output[i] ) ), sub( 16, input_e ) ) ); // Q15 + } + optimal_global_gain = 0; + move32(); + IF( sum_sq_output != 0 ) + { + // optimal_global_gain = sum_input_output / sum_sq_output; + optimal_global_gain = BASOP_Util_Divide3232_Scale_cadence( sum_input_output, sum_sq_output, &optimal_global_gain_e ); + optimal_global_gain = L_shr( optimal_global_gain, sub( 16, optimal_global_gain_e ) ); // Q15 + } + + return optimal_global_gain; +} +#else float ECSQ_compute_optimal_gain( const float *input, const int16_t N, @@ -125,6 +195,7 @@ float ECSQ_compute_optimal_gain( return optimal_global_gain; } +#endif /*--------------------------------------------------------------- * ECSQ_quantize_gain() @@ -132,6 +203,30 @@ float ECSQ_compute_optimal_gain( * quantize global gain * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 ECSQ_quantize_gain_fx( + Word32 global_gain ) // Q15 +{ + Word16 index; + + // global_gain = max(global_gain, 1.0f); /* because always index >= 0 anyway */ + global_gain = L_max( global_gain, ONE_IN_Q15 ); + + /* min gain = 1 (index 0), max gain ~= 29145 (index 126), domain range ~= 90 dB, resolution 90 / 127 ~= 0.7 dB */ + /* value 127 (ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO) is reserved and indicates that all values in the vector are zero */ + + // index = (int16_t) ( ECLVQ_GLOBAL_GAIN_FACTOR * log10f( global_gain ) + 0.4898f ); + index = extract_l( L_shr( L_add( Mpy_32_32( ECLVQ_GLOBAL_GAIN_FACTOR_Q26, BASOP_Util_Log10( global_gain, 16 ) ), 513592 /*0.4898f in Q20*/ ), 20 ) ); + + /* for MSE quantization, the value f in (0, 1) is the middle between consecutive quantization points in the linear scale */ + /* 10 ^ (inv_global_gain_factor * f) - 1 = 10 ^ inv_global_gain_factor - 10 ^ (inv_global_gain_factor * f) */ + /* f = 0.5102, and when applying floor to convert to integer, 1 - f = 0.4898 must be used as the offset */ + + index = s_min( s_max( index, 0 ), 126 ); + + return index; +} +#else static int16_t ECSQ_quantize_gain( float global_gain ) { @@ -153,13 +248,34 @@ static int16_t ECSQ_quantize_gain( return index; } +#endif /*--------------------------------------------------------------- * arith_encode_bit() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_bit_fx( + ECSQ_instance *ecsq_inst, + const Word16 bit ) +{ + RangeUniEncState *rc_st_enc; + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, 1024 ); /* 1024 eq 1 << 10, 22Q10 fixed-point representation */ + move32(); + + IF( ecsq_inst->encoding_active ) + { + /* call to the actual AC */ + rc_uni_enc_encode_bits( rc_st_enc, bit, 1 ); + } + + return; +} +#else static void arith_encode_bit( ECSQ_instance *ecsq_inst, const int16_t bit ) @@ -178,13 +294,33 @@ static void arith_encode_bit( return; } - +#endif /*--------------------------------------------------------------- * arith_encode_bits() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_bits_fx( + ECSQ_instance *ecsq_inst, + const UWord16 n, + Word16 size ) +{ + RangeUniEncState *rc_st_enc; + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, L_shl( size, 10 ) ); /* 22Q10 fixed-point representation */ + move32(); + + IF( ecsq_inst->encoding_active ) + { + rc_uni_enc_encode_bits( rc_st_enc, n, size ); + } + return; +} +#else static void arith_encode_bits( ECSQ_instance *ecsq_inst, const uint16_t n, @@ -203,14 +339,36 @@ static void arith_encode_bits( return; } - +#endif /*--------------------------------------------------------------- * code_length_from_count() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 code_length_from_count_fx( // Q10 + const Word16 c ) +{ + /* compute the approximation of code length, 14 - log2(c), in 22Q10 fixed-point representation */ + /* with c in {1, ..., 2 ^ 14}, representing a probability count in 14-bit AC implementations */ + Word16 c_norm; + Word16 res; + +#define WMC_TOOL_SKIP + c_norm = norm_s( (Word16) c ); /* equivalent with 14 - floor(log_base2(c)) */ +#undef WMC_TOOL_SKIP + + /* compute linear approximation of log2(1 + x), for x in [0, 1], using a look-up table with 64 entries */ + /* normalize to {16384, ..., 32767}, subtract MSB bit, and convert to Q6 for indexing log2_1px_table */ + res = sub( shl( c_norm, 10 ), log2_1px_table[( ( c << c_norm ) - ( 1 << 14 ) + ( 1 << 7 ) ) >> 8] ); + + /* |(14 - log2(c)) - res / (1 << 10)| < 0.0113, for c in {1, ..., 2 ^ 14} */ + /* complexity: 1 norm_s, 2 adds, 3 shifts, 1 table lookup */ + return res; +} +#else static int16_t code_length_from_count( const int16_t c ) { @@ -232,13 +390,43 @@ static int16_t code_length_from_count( /* complexity: 1 norm_s, 2 adds, 3 shifts, 1 table lookup */ return res; } - +#endif /*--------------------------------------------------------------- * arith_encode_bit_prob() * * encoding for one bit with the probabilies prob_0 = count0 / 2 ^ ECSQ_PROB_BITS and prob_1 = 1 - prob_0 * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_bit_prob_fx( + ECSQ_instance *ecsq_inst, + const Word16 count0, + const Word16 bit ) +{ + Word16 count; + RangeUniEncState *rc_st_enc; + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + + count = sub( ECSQ_PROB_TOTAL, count0 ); + + IF( bit == 0 ) + { + count = count0; + move16(); + } + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, code_length_from_count_fx( count ) ); /* 22Q10 fixed-point representation */ + move32(); + + IF( ecsq_inst->encoding_active ) + { + /* call to the actual AC */ + rc_uni_enc_encode_fast( rc_st_enc, bit * count0, count, 14 ); + } + + return; +} +#else static void arith_encode_bit_prob( ECSQ_instance *ecsq_inst, const int16_t count0, @@ -266,13 +454,41 @@ static void arith_encode_bit_prob( return; } - +#endif /*--------------------------------------------------------------- * arith_encode_prob() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_prob_fx( + ECSQ_instance *ecsq_inst, + const UWord16 table[], + const Word16 table_size, + const Word16 symbol ) +{ + Word16 count; + RangeUniEncState *rc_st_enc; + + rc_st_enc = (RangeUniEncState *) ecsq_inst->ac_handle; + + count = table_size; /* just to avoid warning when DEBUGGING is deactivated */ + move16(); + + count = sub( table[symbol], table[symbol + 1] ); + + ecsq_inst->bit_count_estimate = L_add( ecsq_inst->bit_count_estimate, code_length_from_count_fx( count ) ); /* 22Q10 fixed-point representation */ + move16(); + + IF( ecsq_inst->encoding_active ) + { + /* call to the actual AC */ + rc_uni_enc_encode_fast( rc_st_enc, ECSQ_PROB_TOTAL - table[symbol], count, 14 ); + } + return; +} +#else static void arith_encode_prob( ECSQ_instance *ecsq_inst, const uint16_t table[], @@ -298,13 +514,46 @@ static void arith_encode_prob( return; } +#endif /*--------------------------------------------------------------- * arith_encode_elias_mod() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_elias_mod_fx( + ECSQ_instance *ecsq_inst, + const Word16 n ) +{ + Word16 i; + + IF( LE_16( n, 1 ) ) + { + /* code for 0 is 10 and code for 1 is 11 */ + arith_encode_bit_fx( ecsq_inst, 1 ); + arith_encode_bit_fx( ecsq_inst, n ); + } + ELSE /* n >= 2 */ + { + /* code consists of n_bits zero bits, an one bit, and n_bits data bits */ + Word16 n_bits; + /* n_bits is floor(log_2(n)), the number of bits after the leading one bit */ + n_bits = sub( 30, norm_l( n ) ); + FOR( i = 0; i < n_bits; i++ ) + { + arith_encode_bit_fx( ecsq_inst, 0 ); + } + arith_encode_bit_fx( ecsq_inst, 1 ); + + /* encode the n_bits data bits at once */ + arith_encode_bits_fx( ecsq_inst, n - ( 1 << n_bits ), n_bits ); + } + + return; +} +#else static void arith_encode_elias_mod( ECSQ_instance *ecsq_inst, const int16_t n ) @@ -336,13 +585,34 @@ static void arith_encode_elias_mod( return; } +#endif /*--------------------------------------------------------------- * arith_encode_prob_escape() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void arith_encode_prob_escape_fx( + ECSQ_instance *ecsq_inst, + const UWord16 table[], + const Word16 table_size, + const Word16 symbol ) +{ + IF( LT_16( symbol, sub( table_size, 1 ) ) ) + { + arith_encode_prob_fx( ecsq_inst, table, table_size, symbol ); + } + ELSE + { + arith_encode_prob_fx( ecsq_inst, table, table_size, sub( table_size, 1 ) ); /* escape symbol */ + /* encode the additional value using a modified Elias integer code */ + arith_encode_elias_mod_fx( ecsq_inst, sub( symbol, sub( table_size, 1 ) ) ); + } + return; +} +#else static void arith_encode_prob_escape( ECSQ_instance *ecsq_inst, const uint16_t table[], @@ -362,14 +632,87 @@ static void arith_encode_prob_escape( return; } - +#endif /*--------------------------------------------------------------- * get_best_param() * * * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word16 get_best_param_fx( + Word16 *x, + const Word16 start_offset, + const Word16 stop_offset, + Word32 *avg_abs_sum, // Q10 + Word16 *N0 ) +{ + Word16 v; + Word16 val; + Word32 sum_abs; // Q10 + Word16 count; + Word16 count0; + Word16 param; + Word16 L_tmp_e; + + const Word16 offset = INV_LOG_2_FX; /* offset = 1 / ln(2) and log2(offset) ~ 0.528766 */ + + sum_abs = 0; + move16(); + count = add( sub( stop_offset, start_offset ), 1 ); + count0 = 0; + move16(); + + /* compute sum(abs(x[v])) and sum(x[v] == 0) */ + FOR( v = start_offset; v <= stop_offset; ++v ) + { + + val = x[v]; + move16(); + sum_abs = L_add( sum_abs, L_shl( abs_s( val ), 10 ) ); // Q10 + IF( val == 0 ) + { + ++count0; + move16(); + } + } + + + /* the vector has at most ECSQ_NONZERO_MAX values of +-1 and the rest are zeros */ + test(); + IF( LE_16( sub( count, count0 ), ECSQ_NONZERO_MAX ) && EQ_32( sum_abs, L_shl( sub( count, count0 ), 10 ) ) ) + { + //*avg_abs_sum = ( sum_abs + 0.25f * count0 ) / count; + *avg_abs_sum = BASOP_Util_Divide3232_Scale_cadence( L_add( sum_abs, L_shl( count0, 8 ) ), L_shl( count, 10 ), &L_tmp_e ); + move32(); + *avg_abs_sum = L_shr_r( *avg_abs_sum, sub( 21, L_tmp_e ) ); // Q10 + move32(); + *N0 = count0; + move16(); + + return ECSQ_ALL_ZERO_PARAM; + } + + //*avg_abs_sum = ( sum_abs + 0.25f * count0 ) / count; + *avg_abs_sum = BASOP_Util_Divide3232_Scale_cadence( L_add( sum_abs, L_shl( count0, 8 ) ), L_shl( count, 10 ), &L_tmp_e ); + move32(); + *avg_abs_sum = L_shr_r( *avg_abs_sum, sub( 21, L_tmp_e ) ); // Q10 + move32(); + *N0 = count0; + move16(); + /* the best Laplace integer parameter is floor(log2(avg_abs_sum) + log2(offset)) */ + // param = (int16_t) floor( log_base2( *avg_abs_sum * offset ) ); + param = sub( 31, norm_l( L_sub( L_shr( Mpy_32_16_1( *avg_abs_sum, offset ), 10 - 1 ), 1 ) ) ); + // sub( 31, norm_l( L_sub( n, 1 ) ) ) + + /* limit param value to the available exponent range */ + param = s_max( ECSQ_ALL_ZERO_PARAM + 1, param ); + param = s_min( param, ECSQ_ALL_ZERO_PARAM + ECSQ_PARAM_COUNT - 1 ); + + return param; +} +#else static int16_t get_best_param( int16_t *x, const int16_t start_offset, @@ -424,7 +767,7 @@ static int16_t get_best_param( return param; } - +#endif /*--------------------------------------------------------------- * get_est_size() @@ -433,7 +776,81 @@ static int16_t get_best_param( * ---------------------------------------------------------------*/ #define ECSQ_log2TB_FIRST_PARAM -2 +#ifdef IVAS_FLOAT_FIXED +static Word32 get_est_size_fx( // Q10 + const Word16 N, + Word32 avg_abs_sum, // Q10 + const Word16 N0, + Word16 param ) +{ + Word32 size; // Q10 + // Word32 two_to_param; + // Word16 two_to_param_e; + + // two_to_param = (float) ( 1 << abs( param ) ); + // two_to_param = 1 << abs_s( param ) ; + // if ( param < 0 ) + //{ + // //two_to_param = 1.0f / two_to_param; + // two_to_param = BASOP_Util_Divide3232_Scale_cadence( 1, two_to_param,&two_to_param_e); + // } + + IF( NE_16( param, ECSQ_ALL_ZERO_PARAM ) ) /* not all values are zeros */ + { + Word16 index; + index = sub( param, ECSQ_log2TB_FIRST_PARAM ); + index = s_min( index, ECSQ_log2TB_SIZE - 2 ); + + + /* the estimated size in bits is N * log2(2 * 2 ^ param) + */ + /* + N * log2(e) * (avg_abs_sum / 2 ^ param) - (N - N0) * log2(T(2 ^ param)) - */ + /* - N0 * log2(T(2 * 2 ^ param)) */ + // size = N * ( 1 + param + INV_LOG_2 * ( avg_abs_sum / two_to_param ) ); + size = W_extract_l( W_mult0_32_32( N, L_add( L_shl( add( 1, param ), 10 ), Mpy_32_16_1( L_shr( avg_abs_sum, sub( param, 1 /*compesating for INV_LOG_2_FX*/ ) ), INV_LOG_2_FX ) ) ) ); // Q10 + // size -= ( N - N0 ) * log2TB[index]; + size = L_sub( size, Mpy_32_32( L_shl( sub( N, N0 ), 10 ), log2TB_Q31[index] ) ); // Q10 + // size -= N0 * log2TB[index + 1]; + size = L_sub( size, Mpy_32_32( L_shl( N0, 10 ), log2TB_Q31[index + 1] ) ); // Q10 + } + ELSE + { + /* used for all zero values or for very low entropy with number of nonzeros <= ECSQ_NONZERO_MAX */ + Word16 nonzero; + Word32 required_avg_abs_sum; // Q10 + Word16 required_avg_abs_sum_e; + + nonzero = sub( N, N0 ); + + // required_avg_abs_sum = ( nonzero + 0.25f * N0 ) / N; /* the vector must have nonzero +-1 and N0 zeros */ + required_avg_abs_sum = BASOP_Util_Divide3232_Scale_cadence( L_add( L_shl( nonzero, 10 ), L_shl( N0, 8 ) ), L_shl( N, 10 ), &required_avg_abs_sum_e ); /* the vector must have nonzero +-1 and N0 zeros */ + required_avg_abs_sum = L_shr_r( required_avg_abs_sum, sub( 21, required_avg_abs_sum_e ) ); // Q10 + + test(); + IF( EQ_32( avg_abs_sum, required_avg_abs_sum ) && LE_16( nonzero, ECSQ_NONZERO_MAX ) ) + { + // size = 2.0f; /* log_base2(1 + ECSQ_NONZERO_MAX), indicate the nonzero count */ + size = 2 << 10; /* log_base2(1 + ECSQ_NONZERO_MAX), indicate the nonzero count */ + move32(); + + /* the number of bits for the nonzero mask is log2(nchoosek(N, nonzero)) */ + // size += ECSQ_log2_fact[N] - ECSQ_log2_fact[N - nonzero] - ECSQ_log2_fact[nonzero]; + size = L_add( size, L_sub( L_sub( ECSQ_log2_fact_Q10[N], ECSQ_log2_fact_Q10[N - nonzero] ), ECSQ_log2_fact_Q10[nonzero] ) ); + + // size += (float) nonzero; /* indicate the signs for nonzero values */ + size = L_add( size, L_shl( nonzero, 10 ) ); /* indicate the signs for nonzero values */ + } + ELSE + { + /* the method cannot be used, return a huge value so that it will never be chosen */ + // size = 1.0e11f; + size = MAX_32; + move32(); + } + } + return size; +} +#else static float get_est_size( const int16_t N, float avg_abs_sum, @@ -491,14 +908,213 @@ static float get_est_size( return size; } - +#endif /*--------------------------------------------------------------- * ECSQ_encode_raw() * * encode input, which contains a concatenation of quantized RE8 integer-valued vectors; * the return value is the approximate number of bits written, expressed in 22Q10 fixed-point representation * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static Word32 ECSQ_encode_raw_fx( + ECSQ_instance *ecsq_inst, + Word16 *input, + const Word16 N ) +{ + int32_t bit_count_estimate_initial; + + Word32 total_size; // Q10 + Word16 segment_count; + + Word16 seg_length, seg_start, seg_stop, segment, seg_count0; + Word32 est_size; + + Word16 est_param, first_param, last_param, param; + Word32 best_size, test_size; // Q10 + Word16 best_param, best_params[ECSQ_VECTOR_SIZE_MAX / ECSQ_SEGMENT_SIZE]; + Word16 saved_seg_count0[ECSQ_VECTOR_SIZE_MAX / ECSQ_SEGMENT_SIZE]; + + Word32 avg_abs_sum; // Q10 + // const Word32 scale_Q10 = ONE_IN_Q21;// 1.0f / 1024.0f + Word16 i, idx, shift, val, sym, nonzero, left0, left1, count, count0, lsbs; + Word16 param_zb, best_param_zb; /* zero-based parameter index for coding */ + const UWord16 *tab_vals, *tab_abs_lsbs; + + bit_count_estimate_initial = ecsq_inst->bit_count_estimate; + + + total_size = 0; + move32(); + // segment_count = ( N + ECSQ_SEGMENT_SIZE - 1 ) / ECSQ_SEGMENT_SIZE; + segment_count = shr( add( N, ECSQ_SEGMENT_SIZE - 1 ), 3 ); + + FOR( segment = 0; segment < segment_count; ++segment ) + { + seg_start = imult1616( segment, ECSQ_SEGMENT_SIZE ); + seg_stop = sub( s_min( add( seg_start, ECSQ_SEGMENT_SIZE ), N ), 1 ); + seg_length = add( sub( seg_stop, seg_start ), 1 ); + + est_param = get_best_param_fx( input, seg_start, seg_stop, &avg_abs_sum, &seg_count0 ); + saved_seg_count0[segment] = seg_count0; + move16(); + + /* find the best param around est_param for the current segment count */ + best_size = MAX_32 - 1; // 1.0e10f ? + move32(); + best_param = -1000; + move16(); + + IF( EQ_16( est_param, ECSQ_ALL_ZERO_PARAM ) ) /* all values are zero */ + { + first_param = ECSQ_ALL_ZERO_PARAM; + move16(); + last_param = ECSQ_ALL_ZERO_PARAM + 2 * ECSQ_PARAM_SEARCH_RANGE; + move16(); + } + ELSE + { + first_param = s_max( ECSQ_ALL_ZERO_PARAM, sub( est_param, ECSQ_PARAM_SEARCH_RANGE ) ); + last_param = s_min( add( est_param, ECSQ_PARAM_SEARCH_RANGE ), ECSQ_ALL_ZERO_PARAM + ECSQ_PARAM_COUNT - 1 ); + } + + FOR( param = first_param; param <= last_param; ++param ) + { + param_zb = sub( param, ECSQ_ALL_ZERO_PARAM ); + count = ECSQ_tab_param[ecsq_inst->config_index][param_zb] - ECSQ_tab_param[ecsq_inst->config_index][param_zb + 1]; + // test_size = scale_Q10 * code_length_from_count( count ); + test_size = code_length_from_count_fx( count ); // Q10 + + test_size = L_add_sat( test_size, get_est_size_fx( seg_length, avg_abs_sum, seg_count0, param ) ); // if test_size > best_size we don't select + + IF( LT_32( test_size, best_size ) ) + { + best_param = param; + move16(); + best_size = test_size; + move32(); + } + } + + best_params[segment] = best_param; + total_size = L_add( total_size, best_size ); + } + + IF( !ecsq_inst->encoding_active ) /* only size estimation is needed */ + { + // est_size = (int32_t) ( total_size * 1024.0 + 0.5 ); /* 22Q10 fixed-point representation */ + est_size = total_size; /* 22Q10 fixed-point representation */ + move32(); + + return est_size; + } + + /* encode with the best parameters: best_params[] */ + FOR( segment = 0; segment < segment_count; ++segment ) + { + seg_start = imult1616( segment, ECSQ_SEGMENT_SIZE ); + seg_stop = add( seg_start, ECSQ_SEGMENT_SIZE - 1 ); + seg_length = ECSQ_SEGMENT_SIZE; + IF( EQ_16( segment, sub( segment_count, 1 ) ) ) + { + seg_stop = sub( N, 1 ); + seg_length = add( sub( seg_stop, seg_start ), 1 ); + } + + best_param_zb = sub( best_params[segment], ECSQ_ALL_ZERO_PARAM ); + shift = s_max( 0, sub( best_param_zb, 3 ) ); /* first nonzero shift of 1 is used for param 3 */ + + arith_encode_prob_fx( ecsq_inst, ECSQ_tab_param[ecsq_inst->config_index], ECSQ_PARAM_COUNT, best_param_zb ); + + /* encode the actual values if not using the ECSQ_ALL_ZERO_PARAM parameter */ + IF( best_param_zb != 0 ) + { + tab_vals = ECSQ_tab_vals[best_param_zb - 1]; + idx = s_min( shift, 4 ); + tab_abs_lsbs = ECSQ_tab_abs_lsbs[idx]; + + FOR( i = seg_start; i <= seg_stop; ++i ) + { + val = input[i]; + move16(); + sym = abs_s( val ); + + IF( shift != 0 ) + { + lsbs = s_and( sym, sub( shl( 1, shift ), 1 ) ); + sym = shr( sym, shift ); + + arith_encode_prob_escape_fx( ecsq_inst, tab_vals, ECSQ_TAB_VALS_SIZE, sym ); + + test(); + IF( ( sym > 0 ) || GT_16( shift, 4 ) ) + { + arith_encode_bits_fx( ecsq_inst, lsbs, shift ); + } + ELSE /* (sym == 0) && (shift <= 4) */ + { + arith_encode_prob_fx( ecsq_inst, tab_abs_lsbs, shl( 1, shift ), lsbs ); + } + } + ELSE /* shift == 0 */ + { + arith_encode_prob_escape_fx( ecsq_inst, tab_vals, ECSQ_TAB_VALS_SIZE, sym ); + } + + IF( val != 0 ) + { + arith_encode_bit_fx( ecsq_inst, get_sign_fx( val ) ); + } + } + } + ELSE + { + nonzero = sub( seg_length, saved_seg_count0[segment] ); + + + arith_encode_bits_fx( ecsq_inst, nonzero, 2 ); /* log_base2(ECSQ_NONZERO_MAX + 1) == 2 */ + + left1 = nonzero; + move16(); + left0 = sub( seg_length, nonzero ); + + FOR( i = seg_start; i <= seg_stop; ++i ) + { + val = input[i]; + move16(); + sym = abs_s( val ); + + + IF( left1 == 0 ) + { + } + ELSE IF( left0 == 0 ) + { + } + ELSE + { + count0 = imult1616( left0, ECSQ_tab_inverse[left0 + left1] ); /* left0 * round(ECSQ_PROB_TOTAL / (left0 + left1)) */ + arith_encode_bit_prob_fx( ecsq_inst, count0, sym ); + } + IF( sym != 0 ) + { + arith_encode_bit_fx( ecsq_inst, get_sign_fx( val ) ); + --left1; + move16(); + } + ELSE + { + --left0; + move16(); + } + } + } + } + + + return L_sub( ecsq_inst->bit_count_estimate, bit_count_estimate_initial ); +} +#else static int32_t ECSQ_encode_raw( ECSQ_instance *ecsq_inst, int16_t *input, @@ -679,7 +1295,7 @@ static int32_t ECSQ_encode_raw( return ecsq_inst->bit_count_estimate - bit_count_estimate_initial; } - +#endif /*--------------------------------------------------------------- * ECSQ_encode_target_SNR() @@ -693,6 +1309,185 @@ static int32_t ECSQ_encode_raw( #define ECSQ_MAX_BITS_ITERATIONS 2 +#ifdef IVAS_FLOAT_FIXED +Word32 ECSQ_encode_target_SNR_fx( + ECSQ_instance *ecsq_inst, + const Word32 *input, + const Word16 input_e, + const Word16 N, + const Word32 target_SNR, // Q25 + const Word16 max_bits, + Word32 *output, + Word16 *global_gain_index_output ) +{ + Word16 global_gain_index; + Word16 global_gain_index_last; /* used to potentially save one call to ECSQ_quantize_vector */ + Word16 quantized_input[ECSQ_VECTOR_SIZE_MAX]; + Word16 saved_encoding_active; + Word32 saved_bit_count_estimate; + Word32 test_size /*Q10*/, adjust_size; + Word16 i, iteration; + Word32 global_gain /*Q15*/, adjust_global_gain_index; + Word16 global_gain_e; + Word32 max_bits_fixpt; + Word32 sum_squared, target_ratio, target_sum_squared_error; + Word16 sum_squared_e, target_ratio_e, target_sum_squared_error_e; + // const Word32 global_gain_step = 1165018877; // powf( 10.0f, ECLVQ_INV_GLOBAL_GAIN_FACTOR ) in Q30 + Word32 L_tmp1; + Word16 L_tmp1_e; + + // max_bits_fixpt = max_bits * 1024; /* max_bits_fixpt is in 22Q10 fixed-point representation */ + max_bits_fixpt = L_shl( max_bits, 10 ); /* max_bits_fixpt is in 22Q10 fixed-point representation */ + + IF( LE_32( target_SNR, 0 ) ) + { + /* a target SNR of 0.0 dB is already achieved by quantizing all values in the vector to zero */ + *global_gain_index_output = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + IF( output != NULL ) + { + set32_fx( output, 0, N ); + } + + return 0; /* nothing is coded when global gain index is ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO */ + } + + sum_squared = 0; + move32(); + sum_squared_e = 0; + move16(); + FOR( i = 0; i < N; ++i ) + { + // sum_squared += input[i] * input[i]; + sum_squared = BASOP_Util_Add_Mant32Exp( sum_squared, sum_squared_e, Mpy_32_32( input[i], input[i] ), shl( input_e, 1 ), &sum_squared_e ); + } + + // if ( sum_squared < 0.25f ) /* all the values in the input vector will always be quantized to zero */ + IF( BASOP_Util_Cmp_Mant32Exp( sum_squared, sum_squared_e, ONE_IN_Q29, 0 ) < 0 ) /* all the values in the input vector will always be quantized to zero */ + { + /* the condition above holds because sum(input[i] ^ 2) < 0.25 => max(abs(input[i])) < 0.5 */ + *global_gain_index_output = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + move16(); + IF( output != NULL ) + { + set32_fx( output, 0, N ); + } + + return 0; /* nothing is coded when global gain index is ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO */ + } + + /* save internal state and activate size evaluation only */ + saved_encoding_active = ecsq_inst->encoding_active; + move32(); + saved_bit_count_estimate = ecsq_inst->bit_count_estimate; + move32(); + ecsq_inst->encoding_active = 0; + move16(); + + /* target_ratio is the target ratio between the sum squared values of input and sum squared values of quantization error */ + // target_ratio = powf( 10.0f, target_SNR / 10.0f ); + L_tmp1 = BASOP_Util_Divide3232_Scale_cadence( target_SNR, 10, &L_tmp1_e ); + L_tmp1_e = add( L_tmp1_e, 6 - 31 ); + target_ratio = BASOP_Util_fPow( 10 << 27, 4, L_tmp1, L_tmp1_e, &target_ratio_e ); + // target_sum_squared_error = sum_squared / target_ratio; + target_sum_squared_error = BASOP_Util_Divide3232_Scale_cadence( sum_squared, target_ratio, &target_sum_squared_error_e ); + target_sum_squared_error_e = add( target_sum_squared_error_e, sub( sum_squared_e, target_ratio_e ) ); + + /* the mean of squared quantization error for uniform scalar quantization is 1 / 12, approximately 0.0833 */ + /* when including global_gain, the relationship is target_sum_squared_error ~ (0.0833 * N) * global_gain ^ 2 */ + /* the representable range for global_gain is from 1 (global_gain_index 0) to 29145 (global_gain_index 126) inclusive */ + // global_gain = sqrtf( target_sum_squared_error / ( 0.0833f * (float) N ) ); + global_gain = BASOP_Util_Divide3232_Scale_cadence( target_sum_squared_error, L_mult0( 5459 /*0.0833f in Q16*/, N ), &global_gain_e ); + global_gain_e = add( global_gain_e, sub( target_sum_squared_error_e, 15 ) ); + global_gain = L_shr( global_gain, sub( 16, global_gain_e ) ); // Q15 + /* quantize the estimated global_gain */ + global_gain_index = ECSQ_quantize_gain_fx( global_gain ); + + iteration = 0; + move16(); + + /* do the quantization with the dequantized estimated global_gain_index found */ + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); // Q15 + global_gain_index_last = global_gain_index; + move16(); + ECSQ_quantize_vector_fx( input, input_e, global_gain, N, quantized_input ); + + test_size = ECSQ_encode_raw_fx( ecsq_inst, quantized_input, N ); + + ++iteration; + move16(); + Word16 tmp_e; + WHILE( GT_32( test_size, max_bits_fixpt ) && LT_16( iteration, ECSQ_MAX_BITS_ITERATIONS ) ) + { + test(); + adjust_size = L_sub( test_size, max_bits_fixpt ); + /* assume doubling the quantization step size will reduce the entropy with (up to) one bit */ + // adjust_global_gain_index = (int16_t) ceil( adjust_size / ( 1024.0f * N * log_base2( global_gain_step ) ) ); + adjust_global_gain_index = BASOP_Util_Divide3232_Scale_cadence( adjust_size, N, &tmp_e ); + adjust_global_gain_index = Mpy_32_32( adjust_global_gain_index, 17816838 /*/ ( 1024.0f * log_base2( global_gain_step ) )*/ ); + adjust_global_gain_index = extract_l( L_shr( L_add( adjust_global_gain_index, L_shl( 1, sub( 31, tmp_e ) ) ), sub( 31, tmp_e ) ) ); + global_gain_index = s_min( add( global_gain_index, (Word16) adjust_global_gain_index ), 126 ); + + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); // Q15 + global_gain_index_last = global_gain_index; + move16(); + ECSQ_quantize_vector_fx( input, input_e, global_gain, N, quantized_input ); + + test_size = ECSQ_encode_raw_fx( ecsq_inst, quantized_input, N ); + + ++iteration; + move16(); + } + + IF( GT_32( test_size, max_bits_fixpt ) ) + { + /* further increase the quantization step with the smallest increment for global_gain_index */ + global_gain_index = s_min( global_gain_index + 1, 126 ); + } + + /* restore internal state */ + ecsq_inst->encoding_active = saved_encoding_active; + move16(); + ecsq_inst->bit_count_estimate = saved_bit_count_estimate; + move32(); + + /* do the quantization with the dequantized final global_gain_index found */ + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); // Q15 + + IF( global_gain_index != global_gain_index_last ) + { + ECSQ_quantize_vector_fx( input, input_e, global_gain, N, quantized_input ); + } + + global_gain = ECSQ_compute_optimal_gain_fx( input, input_e, N, quantized_input ); + + IF( global_gain == 0 ) /* all values in quantized_input are zero */ + { + *global_gain_index_output = ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO; + move16(); + IF( output != NULL ) + { + set32_fx( output, 0, N ); + } + + return 0; /* nothing is coded when global gain index is ECSQ_GLOBAL_GAIN_INDEX_ALL_ZERO */ + } + + global_gain_index = ECSQ_quantize_gain_fx( global_gain ); + *global_gain_index_output = global_gain_index; + move16(); + + + IF( output != NULL ) + { + global_gain = ECSQ_dequantize_gain_fx( global_gain_index ); + ECSQ_dequantize_vector_fx( quantized_input, global_gain, N, output ); + } + + ECSQ_encode_raw_fx( ecsq_inst, quantized_input, N ); + + return L_sub( ecsq_inst->bit_count_estimate, saved_bit_count_estimate ); +} +#else int32_t ECSQ_encode_target_SNR( ECSQ_instance *ecsq_inst, const float *input, @@ -832,3 +1627,4 @@ int32_t ECSQ_encode_target_SNR( return ecsq_inst->bit_count_estimate - saved_bit_count_estimate; } +#endif diff --git a/lib_enc/ivas_stereo_icbwe_enc.c b/lib_enc/ivas_stereo_icbwe_enc.c index 1c5d7de02..bfdd2bf7c 100644 --- a/lib_enc/ivas_stereo_icbwe_enc.c +++ b/lib_enc/ivas_stereo_icbwe_enc.c @@ -638,7 +638,7 @@ void stereo_icBWE_init_enc_fx( set16_fx( hStereoICBWE->mem_decim_shb_ch0_fx, 0, shl( L_FILT_MAX, 1 ) ); /* SHB ref channel */ - set32_fx( hStereoICBWE->mem_shb_speech_ref_fx, 0, L_LOOK_16k ); + set16_fx( hStereoICBWE->mem_shb_speech_ref_fx, 0, L_LOOK_16k ); /* SHB non-ref channel */ set32_fx( hStereoICBWE->mem_shb_speech_nonref_fx, 0, L_LOOK_16k ); diff --git a/lib_enc/nelp_enc_fx.c b/lib_enc/nelp_enc_fx.c index 576a9ea20..9df21a200 100644 --- a/lib_enc/nelp_enc_fx.c +++ b/lib_enc/nelp_enc_fx.c @@ -34,6 +34,7 @@ #include "control.h" #include "options.h" /* Compilation switches */ #include "cnst.h" /* Common constants */ +#include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #include "rom_com.h" @@ -1095,3 +1096,821 @@ void nelp_encoder_fx( return; } + +void nelp_encoder_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state */ + Word16 *in_fx, /* i : residual signal */ + Word16 *exc_fx, /* o : NELP quantized excitation signal */ + Word16 *qIn1, + Word16 reduce_gains ) +{ + Word16 i, j; + Word16 *ptr_fx = exc_fx; + Word16 lag = 25; /* to cover 25*9 + 31 */ + move16(); + Word16 sqrt_inv_lag = 6554; /* sqrt(1/lag) in Q15 */ + move16(); + Word16 sqrt_inv_lframe_lag = 5885; /* sqrt(1/(L_FRAME-lag*9)) */ + move16(); + Word16 Gains_fx[10], gain_fac_fx; + Word16 iG1_fx, iG2_fx[2]; + Word16 fid; + Word16 fdbck_fx; + Word32 var_dB_fx; + Word32 E1_fx = 0, EL1_fx = 0, EH1_fx = 0, E2_fx = 0, E3_fx = 0, EL2_fx = 0, EH2_fx = 0; + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + Word32 RL_fx = 0, RH_fx = 0; + move32(); + move32(); + Word16 R_fx = 0; + move16(); + Word16 filtRes_fx[L_FRAME]; + Word16 ptr_tmp_fx[L_FRAME]; + + Word16 qE1 = 0, qE2 = 0, qE3 = 0, qEL1 = 0, qEL2 = 0, qEH1 = 0, qEH2 = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 qIn = 0, qGain = 0, qf = 0, qf1 = 0, qNelpGain = 0; + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 exp1, exp2, tmp1, tmp2; + Word16 f_Noise, etmp, e_Noise; + Word16 max1 = 0; + move16(); + Word32 l_nelp_gain_mem; + Word32 Ltemp = 0, Ltemp1 = 0, L_tmp = 0, L_const_1; + move32(); + move32(); + move32(); + Word16 BP1_ORDER; + Word16 rf_flag; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + SC_VBR_ENC_HANDLE hSC_VBR = st_fx->hSC_VBR; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + RF_ENC_HANDLE hRF = st_fx->hRF; + + rf_flag = st_fx->rf_mode; + move16(); + + test(); + if ( EQ_16( hSC_VBR->last_nelp_mode, 1 ) && NE_16( st_fx->bwidth, st_fx->last_bwidth ) ) + { + hSC_VBR->last_nelp_mode = 0; + move16(); + } + + qIn = *qIn1; + move16(); + test(); + IF( EQ_16( st_fx->bwidth, NB ) ) + { + IF( hSC_VBR->last_nelp_mode != 1 ) + { + BP1_ORDER = 7; + move16(); + set32_fx( hSC_VBR->bp1_filt_mem_nb_fx, 0, BP1_ORDER * 2 ); + hSC_VBR->qprevGain_fx = 0; + move16(); + } + } + ELSE IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + IF( hSC_VBR->last_nelp_mode != 1 ) + { + BP1_ORDER = 4; + move16(); + set16_fx( hSC_VBR->bp1_filt_mem_wb_fx, 0, i_mult( BP1_ORDER, 2 ) ); + } + } + + IF( NE_16( hSC_VBR->last_nelp_mode, 1 ) ) + { + test(); + IF( st_fx->bwidth == WB || EQ_16( st_fx->bwidth, SWB ) ) + { + set16_fx( hSC_VBR->shape1_filt_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->shape2_filt_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->shape3_filt_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txlpf1_filt1_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txlpf1_filt2_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txhpf1_filt1_mem_fx, 0, 10 ); + set16_fx( hSC_VBR->txhpf1_filt2_mem_fx, 0, 10 ); + hSC_VBR->qprevIn_fx = 0; + move16(); + hSC_VBR->qprevGain_fx = 0; + move16(); + } + } + + /* Start Unvoiced/NELP Processing */ + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + qE1 = qIn; + move16(); + E1_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + E1_fx = L_mac0_o( E1_fx, in_fx[i], in_fx[i], &Overflow ); /*Q(qE1+qE1) */ +#else + E1_fx = L_mac0( E1_fx, in_fx[i], in_fx[i] ); /*Q(qE1+qE1) */ +#endif + } + + qE1 = shl( qE1, 1 ); + + qf = qIn; + move16(); + Scale_sig( hSC_VBR->txlpf1_filt1_mem_fx, 10, ( qf - hSC_VBR->qprevIn_fx ) ); + pz_filter_sp_fx( txlpf1_num_coef_fx, txlpf1_den_coef_fx, in_fx, filtRes_fx, hSC_VBR->txlpf1_filt1_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + + qEL1 = qf; + move16(); + EL1_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EL1_fx = L_mac0_o( EL1_fx, filtRes_fx[i], filtRes_fx[i], &Overflow ); /*Q(2*qIn) */ +#else + EL1_fx = L_mac0( EL1_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qIn) */ +#endif + } + qEL1 = shl( qEL1, 1 ); + + qf = qIn; + move16(); + Scale_sig( hSC_VBR->txhpf1_filt1_mem_fx, 10, qf - hSC_VBR->qprevIn_fx ); + pz_filter_sp_fx( txhpf1_num_coef_fx, txhpf1_den_coef_fx, in_fx, filtRes_fx, hSC_VBR->txhpf1_filt1_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + hSC_VBR->qprevIn_fx = qf; + move16(); + + qEH1 = qf; + move16(); + EH1_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EH1_fx = L_mac0_o( EH1_fx, filtRes_fx[i], filtRes_fx[i], &Overflow ); /*Q(2*qEH1) */ +#else + EH1_fx = L_mac0( EH1_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEH1) */ +#endif + } + qEH1 = shl( qEH1, 1 ); + move16(); + } + + qGain = qIn; + move16(); + qGain = shl( qGain, 1 ); + move16(); + + FOR( i = 0; i < 9; i++ ) + { + Ltemp = L_deposit_l( 0 ); + FOR( j = (Word16) ( i * lag ); j < (Word16) ( ( i + 1 ) * lag ); j++ ) + { +#ifdef BASOP_NOGLOB + Ltemp = L_mac0_o( Ltemp, in_fx[j], in_fx[j], &Overflow ); /*Q(2*qGain) */ +#else + Ltemp = L_mac0( Ltemp, in_fx[j], in_fx[j] ); /*Q(2*qGain) */ +#endif + } + + /*Gains[i] = (float) sqrt(Gains[i]/lag); */ + IF( Ltemp != 0 ) + { + exp1 = norm_l( Ltemp ); + tmp1 = extract_h( L_shl( Ltemp, exp1 ) ); /*2*qGain+exp1-16 */ + exp1 = sub( exp1, 30 - qGain ); /* */ + + tmp1 = div_s( 16384, tmp1 ); /*14-2*qGain-exp1+16 */ + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + L_tmp = Mult_32_16( L_tmp, sqrt_inv_lag ); +#ifdef BASOP_NOGLOB + Ltemp = L_shl_sat( L_tmp, sub( exp1, 12 ) ); /*Q3 */ +#else + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); /*Q3 */ +#endif + } +#ifdef BASOP_NOGLOB + Gains_fx[i] = round_fx_sat( Ltemp ); +#else + Gains_fx[i] = round_fx( Ltemp ); +#endif + move16(); + } + + + Ltemp = L_deposit_l( 0 ); + FOR( j = i_mult( i, lag ); j < L_FRAME; j++ ) + { +#ifdef BASOP_NOGLOB + Ltemp = L_mac0_o( Ltemp, in_fx[j], in_fx[j], &Overflow ); /*Q(2*qGain) */ +#else + Ltemp = L_mac0( Ltemp, in_fx[j], in_fx[j] ); /*Q(2*qGain) */ +#endif + } + + /*Gains[i] = (float) sqrt(Gains[i]/(L_FRAME-(lag*i))); */ + IF( Ltemp != 0 ) + { + exp1 = norm_l( Ltemp ); + tmp1 = extract_h( L_shl( Ltemp, exp1 ) ); + exp1 = sub( exp1, 30 - qGain ); /* */ + + tmp1 = div_s( 16384, tmp1 ); + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + L_tmp = Mult_32_16( L_tmp, sqrt_inv_lframe_lag ); +#ifdef BASOP_NOGLOB + Ltemp = L_shl_sat( L_tmp, sub( exp1, 12 ) ); +#else + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); +#endif + } + +#ifdef BASOP_NOGLOB + Gains_fx[i] = round_fx_sat( Ltemp ); +#else + Gains_fx[i] = round_fx( Ltemp ); +#endif + move16(); + + IF( EQ_16( reduce_gains, 1 ) ) + { + FOR( i = 0; i < 10; i++ ) + { + Gains_fx[i] = mult( Gains_fx[i], 19661 ); + move16(); + } + } + + + qGain = 3; + move16(); + IF( NE_16( hSC_VBR->last_nelp_mode, 1 ) ) /* if prev frame was not NELP then init mem*/ + { + hSC_VBR->nelp_gain_mem_fx = Gains_fx[0]; + move16(); + qNelpGain = qGain; + move16(); + } + + /* tmp = (float) (20.0 * (log10 (Gains[0]) - log10 (st->nelp_gain_mem) ) ); */ + /* var_dB = tmp * tmp; */ + L_tmp = L_deposit_l( Gains_fx[0] ); + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qGain ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*log(2) in Q13 format = Q0 format */ + /*tmp1 = round_fx(L_shl(Ltemp,12)); Q12 */ + + L_tmp = L_deposit_l( hSC_VBR->nelp_gain_mem_fx ); /*Q0 */ + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qNelpGain ); + tmp2 = Log2_norm_lc( L_tmp ); + Ltemp1 = Mpy_32_16( exp2, tmp2, 9864 ); /*log(2) in Q13 format = Q0 format */ + Ltemp1 = L_sub( Ltemp, Ltemp1 ); /*Q16 */ + Ltemp = Mult_32_16( Ltemp1, 20480 ); /*Q11 (20 in Q10) */ + L_tmp = L_shl( Ltemp, 12 ); /*Q23 */ + var_dB_fx = Mult_32_32( L_tmp, L_tmp ); /*Q15 */ + + FOR( i = 1; i < 10; i++ ) + { + L_tmp = L_deposit_l( Gains_fx[i] ); + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qGain ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*log(2) in Q13 format = Q0 format */ + + L_tmp = L_deposit_l( Gains_fx[i - 1] ); /*Q0 */ + L_tmp = L_max( L_tmp, 1 ); + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( sub( 30, exp2 ), qGain ); + tmp2 = Log2_norm_lc( L_tmp ); + Ltemp1 = Mpy_32_16( exp2, tmp2, 9864 ); /*log(2) in Q13 format = Q0 format */ + Ltemp1 = L_sub( Ltemp, Ltemp1 ); /*Q16 */ + Ltemp = Mult_32_16( Ltemp1, 20480 ); /*Q11 (20 in Q10) */ + L_tmp = L_shl( Ltemp, 12 ); /*Q23 */ + L_tmp = Mult_32_32( L_tmp, L_tmp ); /*Q15 */ + var_dB_fx = L_add( L_tmp, var_dB_fx ); /*Q15 */ + } + + IF( NE_16( hSC_VBR->last_nelp_mode, 1 ) ) + { + /*var_dB *= 0.111f; */ + var_dB_fx = Mult_32_16( var_dB_fx, 3637 ); /*0.111 in Q15 */ + } + ELSE + { + /*var_dB *= 0.1f; */ + var_dB_fx = Mult_32_16( var_dB_fx, 3277 ); /*0.1 in Q15 */ + } + + max1 = 0; + move16(); + FOR( i = 0; i < 10; i++ ) + { + max1 = s_max( max1, abs_s( Gains_fx[i] ) ); + } + + qf = norm_s( max1 ); + test(); + IF( ( qf == 0 ) && ( max1 == 0 ) ) + { + qf = 15; + move16(); + } + qf = sub( qf, 1 ); + qGain = add( qGain, qf ); + + Scale_sig( Gains_fx, 10, qf ); + + L_tmp = L_sub( var_dB_fx, 655360 ); /* 20 in Q15 */ + Ltemp = L_shr_r( L_tmp, 2 ); /*Q15 */ + { + /*exp = pow(2, x*log2(e)) */ + L_tmp = Mult_32_16( Ltemp, 23637 ); /*15 + 14 -15 ->Q14 */ + L_tmp = L_shl( L_tmp, 2 ); /*Q16 */ + f_Noise = L_Extract_lc( L_tmp, &e_Noise ); /*Q16 */ + etmp = extract_l( Pow2( 14, f_Noise ) ); /* Put 14 as exponent */ + e_Noise = sub( e_Noise, 14 ); /* Retreive exponent of etmp */ + + + IF( e_Noise > 0 ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_shl_sat( etmp, e_Noise ); /* Result in Q30 */ + L_tmp = L_add_sat( 1, L_tmp ); +#else + L_tmp = L_shl( etmp, e_Noise ); /* Result in Q30 */ + L_tmp = L_add( 1, L_tmp ); +#endif + + + exp1 = norm_l( L_tmp ); + tmp1 = extract_h( L_shl( L_tmp, exp1 ) ); /*exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(exp1-16)-> 30+15-exp1 */ + fdbck_fx = mult( 26870, tmp1 ); /*45-exp1+15-15=>45-exp1 */ + fdbck_fx = shr_r( fdbck_fx, 14 ); + exp1 = sub( 31, exp1 ); + } + ELSE + { + L_tmp = L_shl( etmp, add( e_Noise, 14 ) ); /* Result in Q30 */ + L_tmp = L_add( 16384, L_tmp ); + + exp1 = norm_l( L_tmp ); + tmp1 = extract_h( L_shl( L_tmp, exp1 ) ); /*14+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(14+exp1-16)-> 16+15-exp1 */ + fdbck_fx = mult( 26870, tmp1 ); /*31-exp1+15-15=>31-exp1 */ + exp1 = sub( 31, exp1 ); + } + } + + IF( EQ_16( exp1, 31 ) ) + { + L_const_1 = 0x7fffffff; + move32(); + } + ELSE + { + L_const_1 = L_shl( 1, exp1 ); + } + + l_nelp_gain_mem = L_deposit_l( hSC_VBR->nelp_gain_mem_fx ); + IF( NE_16( qNelpGain, qGain ) ) + { + l_nelp_gain_mem = L_shl( l_nelp_gain_mem, sub( qGain, qNelpGain ) ); + } + + FOR( i = 0; i < 10; i++ ) + { + /*Gains[i] = (float)((1.0f - fdbck) * Gains[i] + fdbck * st->nelp_gain_mem); */ + L_tmp = L_sub( L_const_1, L_deposit_l( fdbck_fx ) ); /*31-exp1 */ + L_tmp = Mult_32_16( L_tmp, Gains_fx[i] ); /*exp1+qGain-15=>exp1-15+qGain */ + Ltemp1 = Mult_32_16( l_nelp_gain_mem, fdbck_fx ); /*exp1+qGain-15 */ + L_tmp = L_add( L_tmp, Ltemp1 ); + L_tmp = L_shr_r( L_tmp, ( exp1 - 15 ) ); +#ifdef BASOP_NOGLOB + Gains_fx[i] = round_fx_sat( L_shl_sat( L_tmp, 16 ) ); +#else + Gains_fx[i] = round_fx( L_shl( L_tmp, 16 ) ); +#endif + move16(); + l_nelp_gain_mem = L_tmp; + } + + hSC_VBR->nelp_gain_mem_fx = round_fx( L_shl( l_nelp_gain_mem, 16 ) ); + move16(); + + Scale_sig( &hSC_VBR->nelp_gain_mem_fx, 1, -qGain ); + Scale_sig( Gains_fx, 10, -qGain ); + qGain = 0; + move16(); + + quantize_uvg_fx( Gains_fx, &iG1_fx, iG2_fx, Gains_fx, st_fx->bwidth ); + + IF( EQ_16( rf_flag, 1 ) ) + { + hRF->rf_indx_nelp_iG1[0] = iG1_fx; + move16(); + hRF->rf_indx_nelp_iG2[0][0] = iG2_fx[0]; + move16(); + hRF->rf_indx_nelp_iG2[0][1] = iG2_fx[1]; + move16(); + } + ELSE + { + push_indice( hBstr, IND_IG1, iG1_fx, 5 ); + push_indice( hBstr, IND_IG2A, iG2_fx[0], 6 ); + push_indice( hBstr, IND_IG2B, iG2_fx[1], 6 ); + } + + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + gain_fac_fx = 19005; + move16(); /* 1.16f in Q14 */ + } + ELSE + { + gain_fac_fx = 22446; + move16(); /* 1.37f in Q14 */ + } + + /* Normalize Gains_fx[10] with headroom 4 */ + /* This fills up qGain with some new value */ + normalize_arr( Gains_fx, &qGain, 10, 4 ); + + generate_nelp_excitation_fx( &( hSC_VBR->nelp_enc_seed ), Gains_fx, ptr_fx, gain_fac_fx ); + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + BP1_ORDER = 4; + move16(); + Scale_sig( hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER * 2, qGain - hSC_VBR->qprevGain_fx ); /*qf-qAdj */ + pz_filter_sp_fx( bp1_num_coef_wb_fx, bp1_den_coef_wb_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_wb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, 2 ); + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + } + ELSE IF( EQ_16( st_fx->bwidth, NB ) ) + { + BP1_ORDER = 7; + move16(); + Scale_sig32( hSC_VBR->bp1_filt_mem_nb_fx, BP1_ORDER * 2, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_dp_fx( bp1_num_coef_nb_fx_order7, bp1_den_coef_nb_fx_order7, ptr_fx, ptr_tmp_fx, hSC_VBR->bp1_filt_mem_nb_fx, BP1_ORDER, BP1_ORDER, L_FRAME, ( sub( 16, BP1_COEF_NB_QF_ORDER7 ) ) ); + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + Scale_sig( ptr_fx, L_FRAME, -1 ); /* bring exc to qgain-1 */ + *qIn1 = sub( qGain, 1 ); /* use this temp only in the parent */ + } + + E3_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + E3_fx = L_mac_sat( E3_fx, ptr_fx[i], ptr_fx[i] ); /*Q1 */ +#else + E3_fx = L_mac( E3_fx, ptr_fx[i], ptr_fx[i] ); /*Q1 */ +#endif + } + qE3 = add( shl( qGain, 1 ), 1 ); + + test(); + IF( EQ_16( st_fx->bwidth, WB ) || EQ_16( st_fx->bwidth, SWB ) ) + { + Scale_sig( hSC_VBR->shape1_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape1_num_coef_fx, shape1_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape1_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + qf = qGain; + move16(); + E2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( ptr_fx[i], ptr_fx[i] ); /*Q(2*qE2+1) */ + Ltemp = L_shr_r( Ltemp, 4 ); + E2_fx = L_add( E2_fx, Ltemp ); + } + qE2 = sub( shl( qf, 1 ), 4 ); + + test(); + IF( E1_fx == 0 ) + { + R_fx = 0; + move16(); + } + ELSE IF( ( E2_fx == 0 ) && ( E1_fx != 0 ) ) + { + exp1 = norm_l( E1_fx ); + tmp1 = extract_h( L_shl( E1_fx, exp1 ) ); /*qE1+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE1+exp1-16)-> 30-qE1-exp1 */ + exp1 = sub( exp1, 30 - qE1 ); + + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); + R_fx = round_fx( Ltemp ); + } + ELSE + { + exp1 = norm_l( E1_fx ); + tmp1 = extract_h( L_shl( E1_fx, exp1 ) ); /*qE1+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE1+exp1-16)-> 30-qE1-exp1 */ + L_tmp = Mult_32_16( E2_fx, tmp1 ); /*qE2+30-qE1-exp1-15=>15+qE2-qE1-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qE2-qE1-exp1+exp2 */ + exp2 = add( 15, add( sub( sub( qE2, qE1 ), exp1 ), exp2 ) ); + L_tmp = Isqrt_lc( L_tmp, &exp2 ); /*Q(31+exp2) */ + R_fx = round_fx( L_tmp ); + exp1 = sub( 8, exp2 ); + } + + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( R_fx, ptr_fx[i] ); + Ltemp = L_shr_r( Ltemp, exp1 ); +#ifdef BASOP_NOGLOB + filtRes_fx[i] = round_fx_sat( L_shl_sat( Ltemp, 16 ) ); +#else + filtRes_fx[i] = round_fx( L_shl( Ltemp, 16 ) ); +#endif + move16(); + } + + qf1 = qGain; + move16(); + Scale_sig( hSC_VBR->txlpf1_filt2_mem_fx, 10, ( qf1 - hSC_VBR->qprevGain_fx ) ); + + pz_filter_sp_fx( txlpf1_num_coef_fx, txlpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, hSC_VBR->txlpf1_filt2_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + Copy( ptr_tmp_fx, filtRes_fx, L_FRAME ); + + qEL2 = qf1; + move16(); + EL2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EL2_fx = L_mac0_sat( EL2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEL2) */ +#else + EL2_fx = L_mac0( EL2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEL2) */ +#endif + } + qEL2 = shl( qEL2, 1 ); + + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( R_fx, ptr_fx[i] ); + Ltemp = L_shr_r( Ltemp, exp1 ); +#ifdef BASOP_NOGLOB + filtRes_fx[i] = round_fx_sat( L_shl_sat( Ltemp, 16 ) ); +#else + filtRes_fx[i] = round_fx( L_shl( Ltemp, 16 ) ); +#endif + move16(); + } + + qf = qGain; + move16(); + Scale_sig( hSC_VBR->txhpf1_filt2_mem_fx, 10, ( qf - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( txhpf1_num_coef_fx, txhpf1_den_coef_fx, filtRes_fx, ptr_tmp_fx, hSC_VBR->txhpf1_filt2_mem_fx, 10, 10, L_FRAME, 3 ); /*1 = (16-qformat of shape1 cofficient) */ + + Copy( ptr_tmp_fx, filtRes_fx, L_FRAME ); + + qEH2 = qf; + move16(); + EH2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { +#ifdef BASOP_NOGLOB + EH2_fx = L_mac0_sat( EH2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEH2) */ +#else + EH2_fx = L_mac0( EH2_fx, filtRes_fx[i], filtRes_fx[i] ); /*Q(2*qEH2) */ +#endif + } + qEH2 = shl( qEH2, 1 ); + IF( EL2_fx == 0 ) + { + exp2 = norm_l( EL1_fx ); + L_tmp = L_shl( EL1_fx, exp2 ); + exp2 = sub( sub( 30, exp2 ), qEL1 ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q15 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RL_fx = L_mult0( tmp1, 10 ); + } + ELSE + { + exp1 = norm_l( EL2_fx ); + tmp1 = extract_h( L_shl( EL2_fx, exp1 ) ); /*qEL2+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qEL2+exp1-16)-> 30-qEL2-exp1 */ + L_tmp = Mult_32_16( EL1_fx, tmp1 ); /*qEL1+30-qEL2-exp1-15=>15+qE1-qEL2-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEL1-qEL2-exp1+exp2 */ + exp2 = sub( 30, add( sub( sub( add( 30, qEL1 ), qEL2 ), exp1 ), exp2 ) ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q15 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RL_fx = L_mult0( tmp1, 10 ); + } + + IF( EH2_fx == 0 ) + { + exp2 = norm_l( EH2_fx ); + L_tmp = L_shl( EH2_fx, exp2 ); + exp2 = sub( sub( 30, exp2 ), qEH2 ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q13 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RH_fx = L_mult0( tmp1, 10 ); + } + ELSE + { + exp1 = norm_l( EH2_fx ); + tmp1 = extract_h( L_shl( EH2_fx, exp1 ) ); /*qEH2+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qEH2+exp1-16)-> 30-qEH2-exp1 */ + L_tmp = Mult_32_16( EH1_fx, tmp1 ); /*15+qEH1-qEH2-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qEH1-qEH2-exp1+exp2 */ + exp2 = sub( 30, add( 30, add( sub( sub( qEH1, qEH2 ), exp1 ), exp2 ) ) ); + tmp1 = Log2_norm_lc( L_tmp ); + Ltemp = Mpy_32_16( exp2, tmp1, 9864 ); /*10*log(2) in Q13 format = Q0 format */ +#ifdef BASOP_NOGLOB + tmp1 = round_fx_sat( L_shl_sat( Ltemp, 12 ) ); /* Q12 */ +#else + tmp1 = round_fx( L_shl( Ltemp, 12 ) ); /* Q12 */ +#endif + RH_fx = L_mult0( tmp1, 10 ); + } + + fid = 0; + move16(); + IF( LT_32( RL_fx, -12288 ) ) /* -3 in Q12 */ + { + fid = 1; + move16(); + } + ELSE IF( LT_32( RH_fx, -12288 ) ) /* -3 in Q12 */ + { + fid = 2; + move16(); + } + + IF( rf_flag == 0 ) + { + + SWITCH( fid ) + { + case 1: + /* Update other filter memory */ + Scale_sig( hSC_VBR->shape3_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + /* filter the residual to desired shape */ + Scale_sig( hSC_VBR->shape2_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + BREAK; + case 2: + /* Update other filter memory */ + Scale_sig( hSC_VBR->shape2_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + /* filter the residual to desired shape */ + Scale_sig( hSC_VBR->shape3_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, ptr_tmp_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + Copy( ptr_tmp_fx, ptr_fx, L_FRAME ); + + BREAK; + default: + Scale_sig( hSC_VBR->shape2_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape2_num_coef_fx, shape2_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape2_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + Scale_sig( hSC_VBR->shape3_filt_mem_fx, 10, ( qGain - hSC_VBR->qprevGain_fx ) ); + pz_filter_sp_fx( shape3_num_coef_fx, shape3_den_coef_fx, ptr_fx, filtRes_fx, hSC_VBR->shape3_filt_mem_fx, 10, 10, L_FRAME, 1 ); /*1 = (16-qformat of shape1 cofficient) */ + + BREAK; + } + + qE2 = qGain; + move16(); + + E2_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME; i++ ) + { + Ltemp = L_mult0( ptr_fx[i], ptr_fx[i] ); /*Q(2*qE2+1) */ + Ltemp = L_shr_r( Ltemp, 4 ); + E2_fx = L_add( E2_fx, Ltemp ); + } + qE2 = sub( shl( qE2, 1 ), 4 ); + + test(); + IF( E3_fx == 0 ) + { + R_fx = 0; + move16(); + } + ELSE IF( ( E2_fx == 0 ) && ( E3_fx != 0 ) ) + { + exp1 = norm_l( E3_fx ); + tmp1 = extract_h( L_shl( E3_fx, exp1 ) ); /*qE3+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE3+exp1-16)-> 30-qE3-exp1 */ + exp1 = sub( exp1, 30 - qE3 ); + + L_tmp = L_deposit_h( tmp1 ); + L_tmp = Isqrt_lc( L_tmp, &exp1 ); + Ltemp = L_shl( L_tmp, sub( exp1, 12 ) ); + R_fx = round_fx( Ltemp ); + } + ELSE + { + exp1 = norm_l( E3_fx ); + tmp1 = extract_h( L_shl( E3_fx, exp1 ) ); /*qE3+exp1-16 */ + tmp1 = div_s( 16384, tmp1 ); /*14-(qE3+exp1-16)-> 30-qE3-exp1 */ + L_tmp = Mult_32_16( E2_fx, tmp1 ); /*qE2+30-qE3-exp1-15=>15+qE2-qE3-exp1 */ + + exp2 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp2 ); /*15+qE2-qE3-exp1+exp2 */ + exp2 = sub( 30, add( sub( sub( add( 15, qE2 ), qE3 ), exp1 ), exp2 ) ); + L_tmp = Isqrt_lc( L_tmp, &exp2 ); /*Q(31+exp2) */ + R_fx = round_fx( L_tmp ); + exp1 = sub( sub( sub( 31, exp2 ), 16 ), 7 ); + } + + FOR( i = 0; i < L_FRAME; i++ ) + { + L_tmp = L_mult0( R_fx, ptr_fx[i] ); + L_tmp = L_shr_r( L_tmp, exp1 + 1 ); + ptr_fx[i] = round_fx( L_shl( L_tmp, 16 ) ); + } + *qIn1 = sub( qGain, 1 ); + } + + IF( EQ_16( rf_flag, 1 ) ) + { + hRF->rf_indx_nelp_fid[0] = fid; + move16(); + } + ELSE + { + push_indice( hBstr, IND_NELP_FID, fid, 2 ); + } + } + + hSC_VBR->qprevGain_fx = qGain; + move16(); + + IF( rf_flag == 0 ) + { + FOR( i = 0; i < L_FRAME; i++ ) + { + exc_fx[i] = ptr_fx[i]; + move16(); + } + } + + return; +} diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index 2f889cf0c..d78ab652d 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -594,6 +594,20 @@ void swb_tbe_enc_fx( const Word16 pitch_buf[] /* i : pitch for each subframe */ ); +void swb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: IC-BWE state structure */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb */ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2 * Q_new */ + const Word16 voice_factors_fx[], /* i : voicing factors Q15 */ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc */ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6 */ +); + void tbe_write_bitstream_fx( Encoder_State *st_fx /* i/o: encoder state structure */ ); @@ -1001,6 +1015,7 @@ void RunTransientDetection_ivas_fx( * @return average temporal flatness measure with exponent AVG_FLAT_E */ Word16 GetTCXAvgTemporalFlatnessMeasure_fx( struct TransientDetection const *pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks ); +Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( TRAN_DET_HANDLE pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks ); /** Get the maximum energy change using subblock energies aligned with the TCX. * @param pTransientDetection Structure that contains transient detectors to be run. @@ -1696,6 +1711,22 @@ void encod_nelp_fx( ); +void encod_nelp_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word16 *speech_fx, /* i : input speech */ + const Word16 Aw_fx[], /* i : weighted A(z) unquantized for subframes */ + const Word16 Aq_fx[], /* i : 12k8 Lp coefficient */ + Word16 *res_fx, /* o : residual signal */ + Word16 *synth_fx, /* o : core synthesis */ + Word16 *tmp_noise_fx, /* o : long-term noise energy */ + Word16 *exc_fx, /* i/o: current non-enhanced excitation */ + Word16 *exc2_fx, /* i/o: current enhanced excitation */ + Word16 *pitch_buf_fx, /* o : floating pitch values for each subframe */ + Word16 *voice_factors_fx, /* o : voicing factors */ + Word16 *bwe_exc_fx, /* o : excitation for SWB TBE */ + Word16 Q_new, + Word16 shift ); + Word16 encod_tran_fx( Encoder_State *st_fx, /* i/o: state structure */ const Word16 speech_fx[], /* i : i speech */ @@ -2346,6 +2377,20 @@ void tcx_ltp_encode_fx( Word16 tcxltp_on, Word16 *A, Word16 lpcorder ); +void tcx_ltp_encode_ivas_fx( + Encoder_State *st, + const Word16 tcxMode, + const Word16 L_frame, + Word16 *speech_fx, + Word16 *speech_ltp_fx, + const Word16 *wsp_fx, + const Word16 Top[], + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *A_fx, + const Word16 disable_ltp, + const Word16 element_mode ); + void init_coder_ace_plus_fx( Encoder_State *st, const Word32 last_total_brate, /* i : last total bitrate */ @@ -2640,6 +2685,20 @@ void IGFEncApplyMono_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in: | Word16 last_core_acelp /**< in: Q0 | indictaor if last frame was acelp coded */ ); +#ifdef IVAS_FLOAT_FIXED +void IGFEncApplyMono_ivas_fx( Encoder_State *st, /* i : Encoder state */ + const int16_t igfGridIdx, /* i : IGF grid index */ + Word32 *pMDCTSpectrum_fx, /* i/o: MDCT spectrum */ + Word16 e_mdct, /* i : exponent of pMDCTspectrum */ + Word32 *pPowerSpectrum_fx, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ + Word16 e_ps, /* i : exponent of pPowerSpectrum */ + const int16_t isTCX20, /* i : flag indicating if the input is TCX20 or TCX10/2xTCX5 */ + const int8_t isTNSActive, /* i : flag indicating if the TNS is active */ + const int16_t sp_aud_decision0, /* i : first stage switching decision */ + const int16_t vad_hover_flag /* i : VAD hangover flag */ +); +#endif + #ifdef IVAS_FLOAT_FIXED void IGFEncConcatenateBitstream_ivas_fx( const IGF_ENC_INSTANCE_HANDLE hIGFEnc, /* i : instance handle of IGF Encoder */ const Word16 bsBits, /* i : number of IGF bits written to list of indices */ diff --git a/lib_enc/speech_music_classif_fx.c b/lib_enc/speech_music_classif_fx.c index b9d4237a8..4e0d9bade 100644 --- a/lib_enc/speech_music_classif_fx.c +++ b/lib_enc/speech_music_classif_fx.c @@ -19,6 +19,7 @@ #ifdef IVAS_FLOAT_FIXED #include #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "prot.h" #endif @@ -34,6 +35,13 @@ #define LOG_PROB_CONST 11292 /*0.5f * N_FEATURES * LOG_PI2 in Q10 */ #define DLP_BIAS 0.138121f #define DLP_BIAS_FX 72415 /*Q19*/ + +#define TON_ALPHA_FX 31130 /* 0.95f in Q15 */ +#define THR_MASS_MAX_FX 3565158 /* 0.85f in Q22 */ +#define THR_MASS_MIN_FX 3145728 /* 0.75f in Q22 */ +#define THR_MASS_STEP_UP_FX 41943 /* 0.01f in Q22 */ +#define THR_MASS_STEP_DN_FX 83886 /* 0.02f in Q22 */ + /*---------------------------------------------------------------------* * Local functions *---------------------------------------------------------------------*/ @@ -1503,6 +1511,7 @@ static Word16 attack_det_fx( /* o : attack flag return attack; } + #ifdef IVAS_FLOAT_FIXED /* -------------------------------------------------------------------- - * *ivas_smc_gmm() @@ -2394,8 +2403,354 @@ Word16 ivas_smc_gmm_fx( return dec; } + #endif -#ifdef IVAS_CODE +#ifdef IVAS_FLOAT_FIXED +/*---------------------------------------------------------------------* + * var_cor_calc_ivas_fx() + * + * Calculate variance of correlation + *---------------------------------------------------------------------*/ + +static void var_cor_calc_ivas_fx( + const Word16 old_corr, /* Q15 */ + Word16 *mold_corr, /* Q15 */ + Word16 var_cor_t[], /* Q11 */ + Word16 *high_stable_cor ) +{ + Word16 i, var_cor; + + /* update buffer of old correlation values */ + FOR( i = VAR_COR_LEN - 1; i > 0; i-- ) + { + var_cor_t[i] = var_cor_t[i - 1]; /*Q11*/ + move16(); + } + var_cor_t[i] = shr( old_corr, 4 ); /* Q11 */ + move16(); + + /* calculate variance of correlation */ + var_cor = var_fx( var_cor_t, 11, VAR_COR_LEN ); + + *high_stable_cor = 0; + move16(); + test(); + IF( GT_16( *mold_corr, 26214 ) && LT_16( var_cor, 1 ) ) + { + *high_stable_cor = 1; + move16(); + } + + /* update average correlation */ + /*st->mold_corr = 0.1f * st->old_corr + 0.9f * st->mold_corr;*/ + *mold_corr = mac_r( L_mult( 3277, old_corr ), 29491, *mold_corr ); /*Q15 */ + move16(); + + return; +} + +/*---------------------------------------------------------------------* + * attack_det_fx() + * + * Attack detection + *---------------------------------------------------------------------*/ + +static Word16 attack_det_ivas_fx( /* o : attack flag */ + const Word16 *inp, /* i : input signal */ + const Word16 Qx, + const Word16 last_clas, /* i : last signal clas */ + const Word16 localVAD, /* i : local VAD flag */ + const Word16 coder_type, /* i : coder type */ + const Word32 total_brate, /* i : total bitrate */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 clas, /* i : signal class */ + Word32 finc_prev[], /* i/o: previous finc, (2 * Qx) */ + Word32 *lt_finc, /* i/o: long-term mean finc, (2 * Qx) */ + Word16 *last_strong_attack /* i/o: last strong attack flag */ +) +{ + Word16 i, j, tmp, tmp1, attack, exp1; + Word32 L_tmp, etmp, etmp2, finc[ATT_NSEG], mean_finc; + Word16 att_3lsub_pos; + Word16 attack1; + Word64 W_tmp = 0; + move64(); + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + att_3lsub_pos = ATT_3LSUB_POS; + move16(); + if ( GE_32( total_brate, ACELP_24k40 ) ) + { + att_3lsub_pos = ATT_3LSUB_POS_16k; + move16(); + } + + /* compute energy per section */ + FOR( i = 0; i < ATT_NSEG; i++ ) + { + L_tmp = L_mult0( inp[i * ATT_SEG_LEN], inp[i * ATT_SEG_LEN] ); /*2*Qx */ + + FOR( j = 1; j < ATT_SEG_LEN; j++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_mac0_o( L_tmp, inp[i * ATT_SEG_LEN + j], inp[i * ATT_SEG_LEN + j], &Overflow ); /*2*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_mac0( L_tmp, inp[i * ATT_SEG_LEN + j], inp[i * ATT_SEG_LEN + j] ); /*2*Qx */ +#endif /* BASOP_NOGLOB */ + } + + finc[i] = L_tmp; + move32(); + } + + attack = maximum_32_fx( finc, ATT_NSEG, &etmp ); + attack1 = attack; + move16(); + + test(); + IF( EQ_16( localVAD, 1 ) && EQ_16( coder_type, GENERIC ) ) + { + /*----------------------------------------------------------------------* + * Detect if there is a strong onset in the last subframe + * - if detected, TC is used to better code the onset + *----------------------------------------------------------------------*/ + + /* compute mean energy in the first three subframes */ + exp1 = norm_s( att_3lsub_pos ); + tmp = div_s( shl( 1, sub( 14, exp1 ) ), att_3lsub_pos ); /*Q(29-exp1) */ + +#ifdef BASOP_NOGLOB + L_tmp = L_shr_o( finc[0], Qx, &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shr( finc[0], Qx ); /*Qx */ +#endif /* BASOP_NOGLOB */ + + FOR( i = 1; i < att_3lsub_pos; i++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_add_o( L_tmp, L_shr_o( finc[i], Qx, &Overflow ), &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_add( L_tmp, L_shr( finc[i], Qx ) ); /*Qx */ +#endif /* BASOP_NOGLOB */ + } + L_tmp = Mult_32_16( L_tmp, tmp ); /*Q(14-exp1+Qx) */ + etmp = L_shl( L_tmp, sub( exp1, 14 ) ); /*Qx */ + + tmp1 = sub( ATT_NSEG, attack ); + exp1 = norm_s( tmp1 ); + tmp = div_s( shl( 1, sub( 14, exp1 ) ), tmp1 ); /*Q(29-exp1) */ + +#ifdef BASOP_NOGLOB + L_tmp = L_shr_o( finc[attack], Qx, &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shr( finc[attack], Qx ); /*Qx */ +#endif /* BASOP_NOGLOB */ + FOR( i = 1; i < tmp1; i++ ) + { +#ifdef BASOP_NOGLOB + L_tmp = L_add_o( L_tmp, L_shr_o( finc[i + attack], Qx, &Overflow ), &Overflow ); /*Qx */ +#else /* BASOP_NOGLOB */ + L_tmp = L_add( L_tmp, L_shr( finc[i + attack], Qx ) ); /*Qx */ +#endif /* BASOP_NOGLOB */ + } + L_tmp = Mult_32_16( L_tmp, tmp ); /*Q(14-exp1+Qx) */ + etmp2 = L_shl( L_tmp, sub( exp1, 14 ) ); /*Qx */ + + /* and compare them */ + if ( GT_32( etmp, L_shr( etmp2, 3 ) ) ) + { + /* stop, if the attack is not sufficiently strong */ + attack = 0; + move16(); + } + + test(); + if ( EQ_16( last_clas, VOICED_CLAS ) && GT_32( L_add( L_shl( etmp, 4 ), L_shl( etmp, 2 ) ), etmp2 ) ) + { + /* stop, if the signal was voiced and the attack is not sufficiently strong */ + attack = 0; + move16(); + } + + /* compare also wrt. other sections (reduces a misclassification) */ + IF( attack > 0 ) + { + etmp2 = L_add( finc[attack], 0 ); + etmp = Mult_32_16( etmp2, 16384 ); /* etmp2 / 2.0 = (etmp2*0.5) */ + FOR( i = 2; i < ATT_3LSUB_POS - 2; i++ ) + { + IF( GT_32( finc[i], etmp ) ) + { + attack = 0; + move16(); + BREAK; + } + } + } + + test(); + test(); + test(); + IF( attack == 0 && GT_16( element_mode, EVS_MONO ) && ( LT_16( clas, VOICED_TRANSITION ) || EQ_16( clas, ONSET ) ) ) + { + Copy32( finc, finc_prev, attack1 ); + + /* compute mean energy before the attack */ + etmp = L_shr( sum32_fx( finc_prev, ATT_NSEG ), 5 ); /*ATT_NSEG == 32*/ + + etmp2 = finc[attack1]; + move32(); + test(); + test(); + if ( ( LT_32( L_shl( etmp, 4 ), etmp2 ) ) || ( LT_32( L_add( L_shl( etmp, 3 ), L_shl( etmp, 2 ) ), etmp2 ) && EQ_16( last_clas, UNVOICED_CLAS ) ) ) + { + attack = attack1; + move16(); + } + test(); + if ( GT_32( *lt_finc, Mpy_32_32( etmp2, 107374182 /* 1.f/20 in Q31 */ ) ) || *last_strong_attack ) + { + attack = 0; + move16(); + } + } + *last_strong_attack = attack; + move16(); + } + ELSE IF( attack > 0 ) + { + etmp2 = L_add( finc[attack], 0 ); + etmp = Mult_32_16( etmp2, 25206 ); /* etmp2 / 1.3 = (etmp2*0.76923) */ + FOR( i = 2; i < att_3lsub_pos - 2; i++ ) + { + /*if( i != attack && finc[i] * 1.3f > etmp2 ) -> finc[i] > (etmp2*0.76923) */ + test(); + IF( NE_16( i, attack ) && GT_32( finc[i], etmp ) ) + { + attack = 0; + move16(); + BREAK; + } + } + *last_strong_attack = 0; + move16(); + } + + /* updates */ + Copy32( finc, finc_prev, ATT_NSEG ); + + /* Calculating mean of finc */ + FOR( i = 0; i < ATT_NSEG; i++ ) + { + W_tmp = W_add( W_tmp, (Word64) finc[i] ); + } + mean_finc = W_extract_l( W_shr( W_tmp, 5 ) ); + + //*lt_finc = 0.95f * *lt_finc + 0.05f * mean( finc, ATT_NSEG ); + *lt_finc = L_add( Mpy_32_32( *lt_finc, 2040109466 /* 0.95 in Q31 */ ), Mpy_32_32( mean_finc, 107374182 /* 0.05f in Q31 */ ) ); + move32(); + + return attack; +} + +/*---------------------------------------------------------------------* + * tonal_det() + * + * Tonal detector based on spectral stability and harmonicity + *---------------------------------------------------------------------*/ + +static Word32 tonal_det_fx( + const Word16 S[], // Q7 + Word16 vad_flag, + Word32 tod_S_map_lt[], // Q22 + Word32 *tod_thr_lt, // Q22 + Word16 *tod_weight, // Q15 + Word32 *tod_S_mass_prev, // Q22 + Word32 *tod_S_mass_lt // Q22 +) +{ + Word16 i; + Word32 S_mass, alpha; + Word32 L_tmp; + Word64 W_tmp; + + /* update the adaptive weight */ + *tod_weight = add( mult( TON_ALPHA_FX, *tod_weight ), imult1616( ( 32767 - TON_ALPHA_FX ), vad_flag ) ); + move16(); + IF( GT_16( *tod_weight, TON_ALPHA_FX ) ) + { + *tod_weight = TON_ALPHA_FX; + move16(); + } + ELSE IF( LT_16( *tod_weight, ( 32767 - TON_ALPHA_FX ) ) ) + { + *tod_weight = 32767 - TON_ALPHA_FX; + move16(); + } + + /* calculate LT spectral correlation in each band up to 4KHz */ + W_tmp = 0; + move64(); + FOR( i = 0; i < TOD_NSPEC; i++ ) + { + tod_S_map_lt[i] = L_add( Mpy_32_16_1( tod_S_map_lt[i], *tod_weight ), L_mult0( sub( 32767, *tod_weight ), S[i] ) ); // Q22 + move16(); + + W_tmp = W_add( W_tmp, (Word64) ( tod_S_map_lt[i] ) ); // Q22 + } + // S_mass /= TOD_NSPEC; + L_tmp = W_extract_l( W_tmp ); // Q22 + S_mass = ( Mpy_32_32( L_tmp, TOD_NSPEC_INV_Q31 ) ); // Q22 + + IF( GT_32( S_mass, *tod_S_mass_prev ) ) + { + alpha = 1503238554; /* 0.7f in Q31 */ + move16(); + } + ELSE + { + alpha = 644245094; /* 0.3f in Q31 */ + move16(); + } + *tod_S_mass_prev = S_mass; + *tod_S_mass_lt = L_add( Mpy_32_32( alpha, *tod_S_mass_lt ), Mpy_32_32( L_sub( ONE_IN_Q31, alpha ), S_mass ) ); // Q22 + S_mass = *tod_S_mass_lt; + move16(); + move16(); + move16(); + + /* updating adaptive decision threshold */ + IF( GT_32( S_mass, *tod_thr_lt ) ) + { + *tod_thr_lt = L_sub( *tod_thr_lt, THR_MASS_STEP_DN_FX ); + move16(); + } + ELSE + { + *tod_thr_lt = L_add( *tod_thr_lt, THR_MASS_STEP_UP_FX ); + move16(); + } + + if ( GT_32( *tod_thr_lt, THR_MASS_MAX_FX ) ) + { + *tod_thr_lt = THR_MASS_MAX_FX; + move16(); + } + + if ( LT_32( *tod_thr_lt, THR_MASS_MIN_FX ) ) + { + *tod_thr_lt = THR_MASS_MIN_FX; + move16(); + } + + return S_mass; /* Q22 */ +} + + /*---------------------------------------------------------------------* * ivas_smc_mode_selection() * @@ -2406,236 +2761,270 @@ Word16 ivas_smc_gmm_fx( * 1 - 1 -> TCX *---------------------------------------------------------------------*/ -void ivas_smc_mode_selection( - Encoder_State *st, /* i/o: encoder state structure */ - const int32_t element_brate, /* i : element bitrate */ - int16_t smc_dec, /* i : raw decision of the 1st stage classifier*/ - const float relE, /* i : relative frame energy */ - const float Etot, /* i : total frame energy */ - int16_t *attack_flag, /* i/o: attack flag (GSC or TC) */ - const float *inp, /* i : input signal */ - const float S_map[], /* i : short-term correlation map */ - const int16_t flag_spitch /* i : flag to indicate very short stable pitch*/ +void ivas_smc_mode_selection_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word32 element_brate, /* i : element bitrate */ + Word16 smc_dec, /* i : raw decision of the 1st stage classifier*/ + const Word16 relE, /* i : relative frame energy, Q8 */ + const Word16 Etot, /* i : total frame energy, Q8 */ + Word16 *attack_flag, /* i/o: attack flag (GSC or TC) */ + const Word16 *inp, /* i : input signal */ + const Word16 Q_new, /* i : Q of input signal */ + const Word16 S_map[], /* i : short-term correlation map, Q7 */ + const Word16 flag_spitch /* i : flag to indicate very short stable pitch*/ ) { - int16_t attack; - float ton; - int16_t i; - float S_p2a, S_max, S_ave; - float thr_sp2a; + Word16 attack; + Word32 ton; + Word16 i; + Word32 S_p2a, S_max, S_ave = 0; + Word32 thr_sp2a; + move32(); SP_MUS_CLAS_HANDLE hSpMusClas = st->hSpMusClas; /* initialization */ *attack_flag = 0; st->sp_aud_decision2 = 0; + move16(); + move16(); /* signal stability estimation */ - stab_est( Etot, hSpMusClas->gsc_lt_diff_etot, &hSpMusClas->gsc_mem_etot, &hSpMusClas->gsc_nb_thr_3, &hSpMusClas->gsc_nb_thr_1, hSpMusClas->gsc_thres, &hSpMusClas->gsc_last_music_flag, st->vad_flag ); + stab_est_fx( Etot, hSpMusClas->gsc_lt_diff_etot_fx, &hSpMusClas->gsc_mem_etot_fx, &hSpMusClas->gsc_nb_thr_3, &hSpMusClas->gsc_nb_thr_1, hSpMusClas->gsc_thres_fx, &hSpMusClas->gsc_last_music_flag, st->vad_flag ); /* calculate variance of correlation */ - var_cor_calc( st->old_corr, &hSpMusClas->mold_corr, hSpMusClas->var_cor_t, &hSpMusClas->high_stable_cor ); + var_cor_calc_ivas_fx( st->old_corr_fx, &hSpMusClas->mold_corr_fx, hSpMusClas->var_cor_t_fx, &hSpMusClas->high_stable_cor ); /* attack detection */ - attack = attack_det( inp, st->clas, st->localVAD, st->coder_type, 0, st->element_mode, st->clas, hSpMusClas->finc_prev, &hSpMusClas->lt_finc, &hSpMusClas->last_strong_attack ); + attack = attack_det_ivas_fx( inp, Q_new, st->clas, st->localVAD, st->coder_type, 0, st->element_mode, st->clas, hSpMusClas->finc_prev_fx, &hSpMusClas->lt_finc_fx, &hSpMusClas->last_strong_attack ); /* tonal detector */ - ton = tonal_det( S_map, st->vad_flag, hSpMusClas->tod_S_map_lt, &hSpMusClas->tod_thr_lt, &hSpMusClas->tod_weight, &hSpMusClas->tod_S_mass_prev, &hSpMusClas->tod_S_mass_lt ); - + ton = tonal_det_fx( S_map, st->vad_flag, hSpMusClas->tod_S_map_lt_fx, &hSpMusClas->tod_thr_lt_fx, &hSpMusClas->tod_weight_fx, &hSpMusClas->tod_S_mass_prev_fx, &hSpMusClas->tod_S_mass_lt_fx ); // Q22 /* calculate spectral peak-to-average ratio */ - for ( i = 0; i < TOD_NSPEC; i++ ) + FOR( i = 0; i < TOD_NSPEC; i++ ) { - st->hSpMusClas->tod_lt_Bin_E[i] = P2A_FACT * st->hSpMusClas->tod_lt_Bin_E[i] + ( 1 - P2A_FACT ) * st->Bin_E[i]; + // st->hSpMusClas->tod_lt_Bin_E[i] = P2A_FACT * st->hSpMusClas->tod_lt_Bin_E[i] + ( 1 - P2A_FACT ) * st->Bin_E[i]; + st->hSpMusClas->tod_lt_Bin_E_fx[i] = Madd_32_16( Mpy_32_16_1( st->hSpMusClas->tod_lt_Bin_E_fx[i], P2A_FACT_FX_Q15 ), st->Bin_E_fx[i], ( 32767 - P2A_FACT_FX_Q15 ) ); // Q = Q_new + Q_SCALE - 2 } - maximum( st->hSpMusClas->tod_lt_Bin_E, TOD_NSPEC, &S_max ); - S_ave = sum_f( st->hSpMusClas->tod_lt_Bin_E, TOD_NSPEC ) / TOD_NSPEC; - S_p2a = S_max - S_ave; + maximum_32_fx( st->hSpMusClas->tod_lt_Bin_E_fx, TOD_NSPEC, &S_max ); + // S_ave = sum_f( st->hSpMusClas->tod_lt_Bin_E_fx, TOD_NSPEC ) / TOD_NSPEC; + FOR( i = 0; i < TOD_NSPEC; i++ ) + { + S_ave = L_add( S_ave, st->hSpMusClas->tod_lt_Bin_E_fx[i] ); + } + S_ave = Mpy_32_32( S_ave, TOD_NSPEC_INV_Q31 ); + S_p2a = L_sub( S_max, S_ave ); - thr_sp2a = THR_P2A; - if ( element_brate <= IVAS_16k4 ) + IF( LE_32( element_brate, IVAS_16k4 ) ) { - thr_sp2a = THR_P2A_HIGH; + thr_sp2a = L_shl( THR_P2A_HIGH_FX, add( Q_new, Q_SCALE - 2 ) ); // Q = Q_new + Q_SCALE - 2 + } + ELSE + { + thr_sp2a = L_shl( THR_P2A_FX, add( Q_new, Q_SCALE - 2 ) ); // Q = Q_new + Q_SCALE - 2 } /* initial 3-way selection of coding modes (ACELP/GSC/TCX) */ - if ( relE > -10.0f && ( S_p2a > thr_sp2a || ton > hSpMusClas->tod_thr_lt ) ) + test(); + test(); + IF( GT_16( relE, -2560 /* -10.0f in Q8 */ ) && ( GT_32( S_p2a, thr_sp2a ) || GT_32( ton, hSpMusClas->tod_thr_lt_fx ) ) ) { /* select TCX to encode extremely peaky signals or strongly tonal signals */ st->sp_aud_decision1 = 1; st->sp_aud_decision2 = 1; + move16(); + move16(); } - else if ( smc_dec == SPEECH ) + ELSE IF( smc_dec == SPEECH ) { /* select ACELP to encode speech */ st->sp_aud_decision1 = 0; st->sp_aud_decision2 = 0; + move16(); + move16(); } - else if ( smc_dec == SPEECH_OR_MUSIC ) + ELSE IF( EQ_16( smc_dec, SPEECH_OR_MUSIC ) ) { /* select GSC to encode "unclear" segments (classifier's score on the borderline) */ st->sp_aud_decision1 = 1; st->sp_aud_decision2 = 0; + move16(); + move16(); } - else + ELSE { /* select TCX to encode music */ st->sp_aud_decision1 = 1; st->sp_aud_decision2 = 1; + move16(); + move16(); } /* change decision from GSC to ACELP/TCX in some special cases */ - if ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) + test(); + IF( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) { - if ( hSpMusClas->ener_RAT < 0.18f && hSpMusClas->lt_dec_thres > 15.0f ) + test(); + test(); + IF( LT_16( hSpMusClas->ener_RAT_fx, 5898 /* 0.18f in Q15 */ ) && GT_16( hSpMusClas->lt_dec_thres_fx, 7680 /* 15.0f in Q9 */ ) ) { /* prevent GSC on strong music with almost no content below 1kHz */ st->sp_aud_decision2 = 1; + move16(); } - else if ( flag_spitch ) + ELSE IF( flag_spitch ) { /* prevent GSC on signals with very short and stable high pitch period */ - if ( hSpMusClas->wdlp_0_95_sp < 2.5f ) + IF( LT_16( hSpMusClas->wdlp_0_95_sp_fx, 640 /* 2.5f in Q8 */ ) ) { /* select ACELP instead */ st->sp_aud_decision1 = 0; + move16(); } - else + ELSE { /* select TCX instead */ st->sp_aud_decision2 = 1; + move16(); } } - else if ( hSpMusClas->high_stable_cor && st->pitch[0] >= 130 ) + ELSE IF( hSpMusClas->high_stable_cor && GE_16( st->pitch[0], 130 ) ) { /* prevent GSC in highly correlated signal with low energy variation */ /* this is basically a patch against bassoon-type of music */ st->sp_aud_decision2 = 1; + move16(); } } /* change decision from GSC to ACELP TC during attacks/onsets */ - if ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) + test(); + IF( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) { - if ( ( hSpMusClas->gsc_lt_diff_etot[MAX_LT - 1] > 4.5f ) && - ( hSpMusClas->gsc_lt_diff_etot[MAX_LT - 1] - hSpMusClas->gsc_lt_diff_etot[MAX_LT - 2] > 10.0f ) ) + test(); + IF( GT_16( hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT - 1], 1152 /*4.5f in Q8*/ ) && + ( GT_16( sub( hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT - 1], hSpMusClas->gsc_lt_diff_etot_fx[MAX_LT - 2] ), 2560 /* 10.0f in Q8 */ ) ) ) { - if ( st->tc_cnt == 1 ) + IF( EQ_16( st->tc_cnt, 1 ) ) { /* do ACELP TC coding instead of GC/VC if onset has been already declared before */ st->sp_aud_decision1 = 0; st->coder_type = TRANSITION; + move16(); + move16(); } - else + ELSE { - if ( attack >= ATT_3LSUB_POS ) + IF( GE_16( attack, ATT_3LSUB_POS ) ) { /* do ACELP TC coding also if attack is located in the last subframe */ st->sp_aud_decision1 = 0; - *attack_flag = attack + 1; + *attack_flag = add( attack, 1 ); st->coder_type = TRANSITION; + move16(); + move16(); + move16(); } - else if ( attack >= ATT_SEG_LEN / 2 ) + ELSE IF( GE_16( attack, ATT_SEG_LEN / 2 ) ) { /* do GSC coding if attack is located after the first quarter of the first subframe */ /* (pre-echo will be treated at the decoder side) */ *attack_flag = 31; - *attack_flag = attack + 1; + *attack_flag = add( attack, 1 ); + move16(); + move16(); } } } } - if ( st->localVAD == 1 && st->coder_type == GENERIC && attack > 0 /*&& *attack_flag < 32*/ /*&& st->tc_cnt != 2*/ && !( st->sp_aud_decision2 == 1 && ton > 0.65f ) ) + test(); + test(); + test(); + test(); + IF( EQ_16( st->localVAD, 1 ) && EQ_16( st->coder_type, GENERIC ) && attack > 0 /*&& *attack_flag < 32*/ /*&& st->tc_cnt != 2*/ && !( EQ_16( st->sp_aud_decision2, 1 ) && GT_32( ton, 2726298 /* 0.65f in Q22 */ ) ) ) { /* change ACELP coder_type to TC if attack has been detected */ st->sp_aud_decision1 = 0; st->sp_aud_decision2 = 0; st->coder_type = TRANSITION; - *attack_flag = attack + 1; + *attack_flag = add( attack, 1 ); + move16(); + move16(); + move16(); + move16(); } -#ifdef DEBUGGING - if ( st->idchan == 0 && st->coder_type != INACTIVE ) - { - if ( st->force == FORCE_GSC && element_brate < IVAS_24k4 ) - { - /* enforce GSC */ - st->sp_aud_decision1 = 1; - st->sp_aud_decision2 = 0; - } - else if ( st->force == FORCE_SPEECH && ( st->sp_aud_decision1 == 1 || st->sp_aud_decision2 == 1 ) ) - { - if ( element_brate < IVAS_24k4 ) - { - /* convert TCX to GSC */ - st->sp_aud_decision1 = 1; - st->sp_aud_decision2 = 0; - } - else - { - /* convert TCX to ACELP */ - st->sp_aud_decision1 = 0; - st->sp_aud_decision2 = 0; - } - } - else if ( st->force == FORCE_MUSIC ) - { - /* enforce TCX */ - st->sp_aud_decision1 = 1; - st->sp_aud_decision2 = 1; - } - } -#endif /* set GSC noisy speech flag on unvoiced SWB segments */ st->GSC_noisy_speech = 0; - if ( st->vad_flag == 1 && element_brate <= IVAS_16k4 && st->lp_noise > 30.0f && st->sp_aud_decision1 == 0 && st->bwidth >= SWB && st->coder_type_raw == UNVOICED ) + move16(); + test(); + test(); + test(); + test(); + test(); + if ( EQ_16( st->vad_flag, 1 ) && LE_32( element_brate, IVAS_16k4 ) && GT_16( st->lp_noise_fx, 7680 /* 30.0f in Q8 */ ) && st->sp_aud_decision1 == 0 && GE_16( st->bwidth, SWB ) && EQ_16( st->coder_type_raw, UNVOICED ) ) { st->GSC_noisy_speech = 1; + move16(); } /* set GSC submode */ - if ( st->element_mode > EVS_MONO && ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) && st->total_brate > STEREO_GSC_BIT_RATE_ALLOC ) /* below STEREO_GSC_BIT_RATE_ALLOC, fall back on normal GSC */ + test(); + test(); + test(); + IF( st->element_mode > EVS_MONO && ( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) && GT_32( st->total_brate, STEREO_GSC_BIT_RATE_ALLOC ) ) /* below STEREO_GSC_BIT_RATE_ALLOC, fall back on normal GSC */ { st->GSC_IVAS_mode = 1; - if ( st->hSpMusClas->wdlp_0_95_sp > 0.0f ) + move16(); + IF( st->hSpMusClas->wdlp_0_95_sp_fx > 0 ) { /* music-like content */ st->GSC_IVAS_mode = 3; + move16(); } - else if ( st->tc_cnt > 0 ) + ELSE IF( st->tc_cnt > 0 ) { /* likely presence of an onset, GSC bit allocation will be more focused on LF */ st->GSC_IVAS_mode = 2; + move16(); } - if ( st->coder_type_raw == UNVOICED && st->sp_aud_decision0 == 0 /*&& st->GSC_IVAS_mode < 3*/ ) + test(); + IF( EQ_16( st->coder_type_raw, UNVOICED ) && st->sp_aud_decision0 == 0 /*&& st->GSC_IVAS_mode < 3*/ ) { st->GSC_noisy_speech = 1; + move16(); } - else + ELSE { st->GSC_noisy_speech = 0; + move16(); } } /* set coder_type to AUDIO when GSC is selected (st->core will be set later in the decision matrix) */ - if ( ( st->sp_aud_decision1 == 1 && st->sp_aud_decision2 == 0 ) || st->GSC_noisy_speech ) + test(); + test(); + IF( ( EQ_16( st->sp_aud_decision1, 1 ) && st->sp_aud_decision2 == 0 ) || st->GSC_noisy_speech ) { st->coder_type = AUDIO; + move16(); + test(); if ( st->hGSCEnc != NULL && st->GSC_noisy_speech == 0 ) /* In case of GSC_noisy_speech, NOISE_LEVEL should remain at NOISE_LEVEL_SP3 */ { st->hGSCEnc->noise_lev = NOISE_LEVEL_SP0; + move16(); } } return; } - #endif /*---------------------------------------------------------------------* diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 483c73e38..3018245e2 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -127,8 +127,8 @@ typedef struct signal_buffers_enc_data_structure Word16 buf_speech_enc_pe[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; Word16 buf_synth[OLD_SYNTH_SIZE_ENC + L_FRAME32k]; Word16 buf_speech_enc[L_PAST_MAX_32k + L_FRAME32k + L_NEXT_MAX_32k]; - Word16 buf_wspeech_enc[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k]; /*normally there is a lookahead for 12k8 and 16k but L_FRAME_MAX=L_FRAME_16K+L_NEXT_16k*/ - + Word16 buf_wspeech_enc[L_FRAME16k + L_SUBFR + L_FRAME16k + L_NEXT_MAX_16k + 320]; /*normally there is a lookahead for 12k8 and 16k but L_FRAME_MAX=L_FRAME_16K+L_NEXT_16k*/ + /* increased by 320 to avoid memory overlap in ivas_find_wsp() and also to accomodate for the wspeech_enc */ } SIGNAL_BUFFERS_ENC_DATA, *SIGNAL_BUFFERS_ENC_HANDLE; @@ -152,12 +152,14 @@ typedef struct DelayBuffer *pDelayBuffer; /* Delay buffer. */ float subblockNrg_flt[NSUBBLOCKS + MAX_TD_DELAY]; /* Subblock energies with a delay buffering. */ Word32 subblockNrg[NSUBBLOCKS + MAX_TD_DELAY]; + Word16 subblockNrg_e; float accSubblockNrg_flt[NSUBBLOCKS + MAX_TD_DELAY + 1]; /* Recursively accumulated subblock energies with a delay buffering. At index i the value corresponds to the accumulated subblock energy up to i-1, including block i-1 and without block i. */ Word32 accSubblockNrg[NSUBBLOCKS + MAX_TD_DELAY + 1]; + Word16 accSubblockNrg_e; float subblockNrgChange_flt[NSUBBLOCKS + MAX_TD_DELAY]; /* subblockNrgChange[i] = max(subblockNrg[i]/subblockNrg[i-1], subblockNrg[i-1]/subblockNrg[i]) */ - Word16 subblockNrgChange[NSUBBLOCKS + MAX_TD_DELAY]; /* Q(15 - SUBBLOCK_NRG_CHANGE_E) */ + Word16 subblockNrgChange[NSUBBLOCKS + MAX_TD_DELAY]; /* Q7(15 - SUBBLOCK_NRG_CHANGE_E) */ int16_t nDelay; /* Size of the delay buffer in use, as number of subblocks. Maximum delay from all users of this buffer. */ int16_t nPartialDelay; /* Delay of the input (modulo pDelayBuffer->nSubblockSize), nPartialDelay <= pDelayBuffer->nDelay. */ @@ -460,6 +462,7 @@ typedef struct td_cng_enc_structure Word16 cng_Qexc_buf[HO_HIST_SIZE]; /* CNG and DTX - Q_exc buffer for storing */ int32_t cng_brate_buf[HO_HIST_SIZE]; /* CNG and DTX - buffer for storing last_active_brate */ float CNG_att; /* CNG and DTX - attenuation factor for CNG, in dB */ + Word16 CNG_att_fx; /* CNG and DTX - attenuation factor for CNG, in dB (Q7)*/ int16_t ho_16k_lsp[HO_HIST_SIZE]; /* CNG and DTX - 16k LSPs flags */ int16_t act_cnt2; /* CNG and DTX - counter of active frames for CNG_mode switching */ float ho_lsp_circ2[HO_HIST_SIZE * M]; /* CNG and DTX - second buffer of LSPs */ @@ -492,7 +495,6 @@ typedef struct td_cng_enc_structure int16_t shb_cng_ini_cnt; int16_t last_SID_bwidth; int16_t shb_NO_DATA_cnt; - Word16 CNG_att_fx; /* Q7 */ } TD_CNG_ENC_DATA, *TD_CNG_ENC_HANDLE; @@ -680,6 +682,10 @@ typedef struct igf_enc_private_data_struct IGFSCFENC_INSTANCE hIGFSCFArithEnc; #ifdef IVAS_FLOAT_FIXED Word16 prevSFM_FIR_SFB_TB_fx[IGF_MAX_SFB]; + Word16 prevSFB_FIR_TB_e[IGF_MAX_SFB]; + Word16 prevSFB_IIR_TB_e[IGF_MAX_SFB]; + Word16 prevSFB_FIR_SB_e[IGF_MAX_SFB]; + Word16 prevSFB_IIR_SB_e[IGF_MAX_SFB]; Word16 sfb_sb_e[IGF_MAX_SFB]; Word16 sfb_tb_e[IGF_MAX_SFB]; Word16 prevSFM_IIR_SFB_TB_fx[IGF_MAX_SFB]; @@ -954,6 +960,8 @@ typedef struct sp_mus_clas_structure float finc_prev[ATT_NSEG]; /* strong attack detection - previous finc */ float lt_finc; /* strong attack detection - long-term finc energy */ + Word32 finc_prev_fx[ATT_NSEG]; /* strong attack detection - previous finc, (Q_new * 2) */ + Word32 lt_finc_fx; /* strong attack detection - long-term finc energy, (Q_new * 2) */ int16_t last_strong_attack; /* strong attack detection - last strong attack flag */ float tod_lt_Bin_E[TOD_NSPEC]; /* tonal detector - long-term energy spectrum */ float tod_S_map_lt[TOD_NSPEC]; /* tonal detector - long-term correlation map */ @@ -961,6 +969,12 @@ typedef struct sp_mus_clas_structure float tod_weight; /* tonal detector - adaptive weight */ float tod_S_mass_prev; float tod_S_mass_lt; + Word32 tod_lt_Bin_E_fx[TOD_NSPEC]; /* tonal detector - long-term energy spectrum, Q_new + Q_SCALE - 2 */ + Word32 tod_S_map_lt_fx[TOD_NSPEC]; /* tonal detector - long-term correlation map, Q22 */ + Word32 tod_thr_lt_fx; /* tonal detector - adaptive threshold, Q22 */ + Word16 tod_weight_fx; /* tonal detector - adaptive weight, Q15 */ + Word32 tod_S_mass_prev_fx; /* Q22 */ + Word32 tod_S_mass_lt_fx; /* Q22 */ int16_t lt_music_hangover; float tonality2_buf[HANG_LEN_INIT]; @@ -1324,30 +1338,34 @@ typedef struct td_bwe_enc_structure Word16 old_input_fhb_fx_Q; float prev_lsp_shb[LPC_SHB_ORDER]; - Word16 prev_lsp_shb_fx[LPC_SHB_ORDER]; + Word16 prev_lsp_shb_fx[LPC_SHB_ORDER]; /* Q15 */ float state_ana_filt_shb[2 * ALLPASSSECTIONS_STEEP + 1]; /* states for the analysis filters */ float cldfbHBLT_flt; Word16 state_ana_filt_shb_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 cldfbHBLT; + Word16 cldfbHBLT; /* Q13 */ /* states for the filters used in generating SHB excitation from WB excitation*/ float mem_csfilt[2]; - Word32 mem_csfilt_fx[2]; /* Q(prev_Q_bwe_exc) */ - float mem_shb_res[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ - Word16 mem_shb_res_fx[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ - float old_EnvSHBres[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ - Word16 old_EnvSHBres_fx[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ - float old_mean_EnvSHBres; /* energy of the last subframe of the SHB residual signal from previous frame */ - Word16 old_mean_EnvSHBres_fx; /* energy of the last subframe of the SHB residual signal from previous frame */ - float prev_enr_EnvSHBres; /* energy of the residual SHB envelope from the previous frame */ - Word16 prev_enr_EnvSHBres_fx; /* energy of the residual SHB envelope from the previous frame */ - float prev_shb_env_tilt; /* tilt of the residual SHB envelope from the previous frame */ - Word16 prev_shb_env_tilt_fx; /* tilt of the residual SHB envelope from the previous frame */ - float prev_pow_exc16kWhtnd; /* power of the LB excitation signal in the previous frame */ - Word16 prev_pow_exc16kWhtnd_fx; /* power of the LB excitation signal in the previous frame */ - float prev_mix_factor; /* mixing factor in the previous frame */ - Word16 prev_mix_factor_fx; /* mixing factor in the previous frame */ - float prev_Env_error; /* error in SHB envelope modelling */ - Word16 prev_Env_error_fx; /* error in SHB envelope modelling */ + Word32 mem_csfilt_fx[2]; /* Q(prev_Q_bwe_exc) */ + float mem_shb_res[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ + Word16 mem_shb_res_fx[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ + Word32 mem_shb_res_32_fx[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ + float old_EnvSHBres[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ + Word16 old_EnvSHBres_fx[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ + float old_mean_EnvSHBres; /* energy of the last subframe of the SHB residual signal from previous frame */ + Word16 old_mean_EnvSHBres_fx; /* energy of the last subframe of the SHB residual signal from previous frame Q15 */ + float prev_enr_EnvSHBres; /* energy of the residual SHB envelope from the previous frame */ + Word32 prev_enr_EnvSHBres_fx; /* energy of the residual SHB envelope from the previous frame Q(31 - prev_enr_EnvSHBres_e) */ + Word16 prev_enr_EnvSHBres_e; + float prev_shb_env_tilt; /* tilt of the residual SHB envelope from the previous frame */ + Word16 prev_shb_env_tilt_fx; /* tilt of the residual SHB envelope from the previous frame Q(prev_shb_env_tilt_q) */ + Word16 prev_shb_env_tilt_q; + float prev_pow_exc16kWhtnd; /* power of the LB excitation signal in the previous frame */ + Word16 prev_pow_exc16kWhtnd_fx; /* power of the LB excitation signal in the previous frame */ + Word32 prev_pow_exc16kWhtnd_fx32; /* Use this power of the LB excitation signal in the previous frame Q0 */ + float prev_mix_factor; /* mixing factor in the previous frame */ + Word16 prev_mix_factor_fx; /* mixing factor in the previous frame Q15 */ + float prev_Env_error; /* error in SHB envelope modelling */ + Word16 prev_Env_error_fx; /* error in SHB envelope modelling */ /* states for the filters used in generating SHB signal from SHB excitation*/ float state_syn_shbexc[L_SHB_LAHEAD]; @@ -1386,12 +1404,12 @@ typedef struct td_bwe_enc_structure Word16 elliptic_bpf_2_48k_mem_fx_Q[4]; Word32 prev_fb_energy_fx; Word16 prev_fb_energy_fx_Q; - Word32 prev_gainFr_SHB_fx; - Word16 lsp_shb_slow_interpl_fx[LPC_SHB_ORDER]; - Word16 lsp_shb_fast_interpl_fx[LPC_SHB_ORDER]; + Word32 prev_gainFr_SHB_fx; /* Q18 */ + Word16 lsp_shb_slow_interpl_fx[LPC_SHB_ORDER]; /* Q15 */ + Word16 lsp_shb_fast_interpl_fx[LPC_SHB_ORDER]; /* Q15 */ Word16 shb_inv_filt_mem_fx[LPC_SHB_ORDER]; - Word16 lsp_shb_spacing_fx[3]; - Word16 prev_swb_GainShape_fx; + Word16 lsp_shb_spacing_fx[3]; /* Q15 */ + Word16 prev_swb_GainShape_fx; /* Q15 */ int16_t prev_frGainAtten; float prev_wb_GainShape_flt; @@ -1399,8 +1417,8 @@ typedef struct td_bwe_enc_structure float fb_state_lpc_syn[LPC_SHB_ORDER]; float fb_tbe_demph; float tilt_mem; - Word16 prev_wb_GainShape; /* Q15 */ - Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; + Word16 prev_wb_GainShape; /* Q15 */ + Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; /* Q15 */ Word16 fb_state_lpc_syn_fx[LPC_SHB_ORDER]; Word16 prev_Q_bwe_exc_fb; Word16 fb_tbe_demph_fx; @@ -1411,8 +1429,8 @@ typedef struct td_bwe_enc_structure float prev_tilt_para; float cur_sub_Aq[M + 1]; Word16 prev_lsf_diff_fx[LPC_SHB_ORDER - 2]; - Word16 prev_tilt_para_fx; - Word16 cur_sub_Aq_fx[M + 1]; + Word16 prev_tilt_para_fx; /* Q10 */ + Word16 cur_sub_Aq_fx[M + 1]; /* Q12 */ /* quantized data */ int16_t lsf_idx[NUM_Q_LSF]; @@ -1430,7 +1448,7 @@ typedef struct td_bwe_enc_structure int16_t idxGain; float dec_2_over_3_mem[L_FILT_2OVER3]; float dec_2_over_3_mem_lp[L_FILT_2OVER3_LP]; - Word16 dec_2_over_3_mem_fx[12]; + Word16 dec_2_over_3_mem_fx[L_FILT_2OVER3]; Word16 dec_2_over_3_mem_lp_fx[6]; float tbe_demph; @@ -1439,11 +1457,11 @@ typedef struct td_bwe_enc_structure float *ptr_mem_stp_swb; float gain_prec_swb; float mem_zero_swb[LPC_SHB_ORDER]; - Word16 tbe_demph_fx; - Word16 tbe_premph_fx; - Word16 mem_stp_swb_fx[LPC_SHB_ORDER]; + Word16 tbe_demph_fx; /* Q(prev_Q_bwe_exc - 16 - NOISE_QADJ) */ + Word16 tbe_premph_fx; /* Q(prev_Q_bwe_exc - 16) */ + Word16 mem_stp_swb_fx[LPC_SHB_ORDER]; /* Q(st->prev_Q_bwe_syn) */ Word16 *ptr_mem_stp_swb_fx; - Word16 gain_prec_swb_fx; + Word16 gain_prec_swb_fx; /* Q14 */ Word16 mem_zero_swb_fx[LPC_SHB_ORDER]; } TD_BWE_ENC_DATA, *TD_BWE_ENC_HANDLE; @@ -2034,6 +2052,7 @@ typedef struct enc_core_structure Word16 exp_old_inp_12k8; Word16 exp_old_inp_16k; Word16 exp_buf_wspeech_enc; + Word16 exp_buf_synth; #endif /*----------------------------------------------------------------------------------* diff --git a/lib_enc/swb_pre_proc.c b/lib_enc/swb_pre_proc.c index fe5c5d834..4e0997aa4 100644 --- a/lib_enc/swb_pre_proc.c +++ b/lib_enc/swb_pre_proc.c @@ -278,551 +278,698 @@ void wb_pre_proc( #ifdef IVAS_FLOAT_FIXED /*full implementation pending*/ void swb_pre_proc_ivas_fx( - Encoder_State *st, /* i/o: encoder state structure */ - float *new_swb_speech, /* o : original input signal at 32kHz */ - Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz */ - float *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz */ - float realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer */ - float imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer */ - CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ + Encoder_State *st, /* i/o: encoder state structure */ + Word16 *new_swb_speech, /* o : original input signal at 32kHz - Q0 */ + Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz - Q - q_reImBuffer */ + Word16 *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz- Q0 */ + Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer Q - q_reImbuffer */ + Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer Q - q_reImbuffer */ + Word16 q_reImBuffer, /* i : scale data of real and imag CLDFB buffers */ + CPE_ENC_HANDLE hCPE /* i/o: CPE encoder structure */ ) { - int16_t Sample_Delay_SWB_BWE, inner_frame, delay; + Word16 Sample_Delay_SWB_BWE, inner_frame, delay; TD_BWE_ENC_HANDLE hBWE_TD; FD_BWE_ENC_HANDLE hBWE_FD; - int32_t inner_Fs, input_Fs; - float old_input[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; - Word32 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; // fixed counterpart - float spchTmp[L_FRAME32k], spchTmp2[L_FRAME32k]; - int16_t i, j, L_resamp; - int16_t startB, endB; - float *realBufferFlipped[CLDFB_NO_COL_MAX]; - float *imagBufferFlipped[CLDFB_NO_COL_MAX]; - float realBufferTmp[CLDFB_NO_COL_MAX][20]; - float imagBufferTmp[CLDFB_NO_COL_MAX][20]; - int16_t ts, nB, uB; - float sign, lbEner, v, t, regression; - const float *thr, *regV; - int16_t Sample_Delay_SWB_BWE32k, lMemRecalc32k, dft_ovl32k; -#ifdef IVAS_FLOAT_FIXED - Word16 shb_speech_fx[L_FRAME16k]; -#endif - lMemRecalc32k = NS2SA( 32000, L_MEM_RECALC_NS ); + Word32 inner_Fs, input_Fs; + Word16 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; // fixed counterpart + Word32 old_input_fx_32[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; // fixed counterpart + Word16 spchTmp[L_FRAME32k], spchTmp2[L_FRAME32k]; + Word16 i, j, L_resamp; + Word16 startB, endB; + Word32 *realBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 *imagBufferFlipped[CLDFB_NO_COL_MAX]; + Word32 realBufferTmp[CLDFB_NO_COL_MAX][20]; + Word32 imagBufferTmp[CLDFB_NO_COL_MAX][20]; + Word16 ts, nB, uB; + Word32 v, t, regression; + Word16 t_16; + const Word32 *thr, *regV; + Word32 lbEner; + Word16 exp_lbEner = 0; + Word16 Sample_Delay_SWB_BWE32k, lMemRecalc32k, dft_ovl32k; + Word32 shb_speech_32[L_FRAME16k]; + Word32 one_by_50_Q31 = 42949673; + + lMemRecalc32k = NS2SA_FX2( 32000, L_MEM_RECALC_NS ); + move16(); // exp_lbEner + move16(); // lMemRecalc32k + move32(); // one_by_50_Q31 /* initialization */ hBWE_TD = st->hBWE_TD; hBWE_FD = st->hBWE_FD; input_Fs = st->input_Fs; - for ( j = 0; j < CLDFB_NO_COL_MAX; j++ ) + FOR( j = 0; j < CLDFB_NO_COL_MAX; j++ ) { - set_f( realBufferTmp[j], 0, 20 ); - set_f( imagBufferTmp[j], 0, 20 ); + set32_fx( realBufferTmp[j], 0, 20 ); + set32_fx( imagBufferTmp[j], 0, 20 ); realBufferFlipped[j] = realBufferTmp[j]; imagBufferFlipped[j] = imagBufferTmp[j]; } - set_f( old_input, 0.0f, NS2SA( 48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k ); + set16_fx( old_input_fx, 0, NS2SA_FX2( 48000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k ); - if ( input_Fs == 32000 ) + IF( EQ_32( st->input_Fs, 32000 ) ) { - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_12k8_NS ); - if ( st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + IF( EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_16k_NS ); + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_16k_NS ); + move16(); } - mvr2r( st->input - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); - mvr2r( st->input - L_FRAME32k, hBWE_FD->old_fdbwe_speech, L_FRAME32k ); + Copy( st->input_fx - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + Copy( st->input_fx - L_FRAME32k, hBWE_FD->old_fdbwe_speech_fx, L_FRAME32k ); - if ( st->element_mode == IVAS_CPE_TD && st->bwidth >= SWB ) + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) && GE_16( st->bwidth, SWB ) ) { - mvr2r( st->input - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->old_wtda_swb + L_FRAME32k - ( hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ), hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ), sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ) ); } - else if ( st->element_mode == IVAS_CPE_DFT && st->bwidth >= SWB ) + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && GE_16( st->bwidth, SWB ) ) { - mvr2r( st->input - hCPE->hStereoDft->dft_ovl, hBWE_FD->old_wtda_swb + L_FRAME32k - ( hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ), hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoDft->dft_ovl, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - sub( hCPE->hStereoDft->dft_ovl, Sample_Delay_SWB_BWE ), sub( hCPE->hStereoDft->dft_ovl, Sample_Delay_SWB_BWE ) ); } } - mvr2r( st->input, new_swb_speech, L_FRAME32k ); + Copy( st->input_fx, new_swb_speech, L_FRAME32k ); - if ( st->last_extl != SWB_BWE && st->last_extl != FB_BWE && st->extl != SWB_BWE_HIGHRATE ) + test(); + test(); + IF( NE_16( st->last_extl, SWB_BWE ) && NE_16( st->last_extl, FB_BWE ) && NE_16( st->extl, SWB_BWE_HIGHRATE ) ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); - if ( st->element_mode > EVS_MONO && st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + move16(); + test(); + IF( st->element_mode > EVS_MONO && EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE = NS2SA( 32000, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + move16(); } - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - Sample_Delay_SWB_BWE -= NS2SA( 32000, DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA_FX2( 32000, DELAY_FIR_RESAMPL_NS ) ); } - mvr2r( hBWE_FD->old_fdbwe_speech, &old_input[Sample_Delay_SWB_BWE], L_FRAME32k ); + Copy( hBWE_FD->old_fdbwe_speech_fx, &old_input_fx[Sample_Delay_SWB_BWE], L_FRAME32k ); - set_f( old_input, 0, Sample_Delay_SWB_BWE ); - mvr2r( hBWE_FD->old_fdbwe_speech + L_FRAME32k - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); - if ( st->extl != WB_BWE ) + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( hBWE_FD->old_fdbwe_speech_fx + L_FRAME32k - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + IF( NE_16( st->extl, WB_BWE ) ) { - mvr2r( old_input, hBWE_FD->old_wtda_swb, L_FRAME32k ); + Copy( old_input_fx, hBWE_FD->L_old_wtda_swb_fx, L_FRAME32k ); } } - if ( st->extl != SWB_BWE && st->extl != FB_BWE ) + test(); + IF( NE_16( st->extl, SWB_BWE ) && NE_16( st->extl, FB_BWE ) ) { - mvr2r( st->input, hBWE_FD->old_fdbwe_speech, L_FRAME32k ); + Copy( st->input_fx, hBWE_FD->old_fdbwe_speech_fx, L_FRAME32k ); } } - else /* 48 kHz */ + ELSE /* 48 kHz */ { - Sample_Delay_SWB_BWE32k = NS2SA( 32000, DELAY_FD_BWE_ENC_12k8_NS ); - Sample_Delay_SWB_BWE = NS2SA( 48000, DELAY_FD_BWE_ENC_12k8_NS ); - if ( st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE32k = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + Sample_Delay_SWB_BWE = NS2SA_FX2( 48000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + IF( EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE32k = NS2SA( 32000, DELAY_FD_BWE_ENC_16k_NS ); - Sample_Delay_SWB_BWE = NS2SA( 48000, DELAY_FD_BWE_ENC_16k_NS ); + Sample_Delay_SWB_BWE32k = NS2SA_FX2( 32000, DELAY_FD_BWE_ENC_16k_NS ); + move16(); + Sample_Delay_SWB_BWE = NS2SA_FX2( 48000, DELAY_FD_BWE_ENC_16k_NS ); + move16(); } dft_ovl32k = 0; - if ( st->element_mode == IVAS_CPE_DFT ) + move16(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - dft_ovl32k = (int16_t) ( STEREO_DFT_OVL_MAX * 32000 / 48000 ); + dft_ovl32k = (Word16) ( STEREO_DFT_OVL_MAX * 32000 / 48000 ); + move16(); } - if ( st->codec_mode == MODE1 ) + IF( EQ_16( st->codec_mode, MODE1 ) ) { - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - if ( st->element_mode == IVAS_CPE_TD ) + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) ) { } - else if ( st->bwidth == FB ) + ELSE IF( EQ_16( st->bwidth, FB ) ) { - mvr2r( st->input - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); + Copy( st->input_fx - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); } - mvr2r( st->input - L_FRAME48k, hBWE_FD->old_fdbwe_speech, L_FRAME48k ); + Copy( st->input_fx - L_FRAME48k, hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k ); - if ( st->element_mode == IVAS_CPE_TD && st->bwidth >= SWB ) + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) && GE_16( st->bwidth, SWB ) ) { - if ( st->bwidth == SWB ) + IF( EQ_16( st->bwidth, SWB ) ) { /* buffers hBWE_FD->old_input[] and hBWE_FD->old_wtda_swb[] need to be at 32 kHz (inner) sampling rate */ - decimate_2_over_3_allpass( st->input - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, spchTmp, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, spchTmp, hBWE_TD->dec_2_over_3_mem_fx, + allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); - mvr2r( spchTmp, hBWE_FD->old_wtda_swb + L_FRAME32k - ( lMemRecalc32k - Sample_Delay_SWB_BWE32k ), lMemRecalc32k - Sample_Delay_SWB_BWE32k ); - mvr2r( spchTmp + lMemRecalc32k - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input, Sample_Delay_SWB_BWE32k ); + Copy( spchTmp, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - sub( lMemRecalc32k, Sample_Delay_SWB_BWE32k ), sub( lMemRecalc32k, Sample_Delay_SWB_BWE32k ) ); + Copy( spchTmp + lMemRecalc32k - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE32k ); } - else /* FB_BWE */ + ELSE /* FB_BWE */ { - mvr2r( st->input - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->old_wtda_swb + L_FRAME48k - ( hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ), hCPE->hStereoTCA->lMemRecalc - Sample_Delay_SWB_BWE ); - mvr2r( st->input - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoTCA->lMemRecalc, hBWE_FD->L_old_wtda_swb_fx + L_FRAME48k - sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ), sub( hCPE->hStereoTCA->lMemRecalc, Sample_Delay_SWB_BWE ) ); + Copy( st->input_fx - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); } } - else if ( st->element_mode == IVAS_CPE_DFT && st->bwidth >= SWB ) + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && GE_16( st->bwidth, SWB ) ) { - if ( st->bwidth == SWB ) + IF( EQ_16( st->bwidth, SWB ) ) { - lerp_flt( st->input - hCPE->hStereoDft->dft_ovl, spchTmp, dft_ovl32k - Sample_Delay_SWB_BWE32k, hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); + lerp( st->input_fx - hCPE->hStereoDft->dft_ovl, spchTmp, dft_ovl32k - Sample_Delay_SWB_BWE32k, hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); - mvr2r( spchTmp, hBWE_FD->old_wtda_swb + L_FRAME32k - ( dft_ovl32k - Sample_Delay_SWB_BWE32k ), dft_ovl32k - Sample_Delay_SWB_BWE32k ); + Copy( spchTmp, hBWE_FD->L_old_wtda_swb_fx + L_FRAME32k - ( dft_ovl32k - Sample_Delay_SWB_BWE32k ), dft_ovl32k - Sample_Delay_SWB_BWE32k ); } - else + ELSE { - mvr2r( st->input - hCPE->hStereoDft->dft_ovl, hBWE_FD->old_wtda_swb + L_FRAME48k - ( hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ), hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); + Copy( st->input_fx - hCPE->hStereoDft->dft_ovl, hBWE_FD->L_old_wtda_swb_fx + L_FRAME48k - ( hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ), hCPE->hStereoDft->dft_ovl - Sample_Delay_SWB_BWE ); } } } - if ( ( st->extl != SWB_BWE && st->extl != FB_BWE && st->core == ACELP_CORE ) || ( st->element_mode == IVAS_CPE_DFT && st->core != ACELP_CORE ) /*resampling not needed for MDCT cores*/ ) + test(); + test(); + test(); + test(); + IF( ( NE_16( st->extl, SWB_BWE ) && NE_16( st->extl, FB_BWE ) && ( st->core == ACELP_CORE ) ) || ( EQ_16( st->element_mode, IVAS_CPE_DFT ) && ( st->core != ACELP_CORE ) ) /*resampling not needed for MDCT cores*/ ) { /* move the resampling out of the TDBWE path as new_swb_speech is not needed for TDBWE. */ - mvr2r( st->input, hBWE_FD->old_fdbwe_speech, L_FRAME48k ); + Copy( st->input_fx, hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k ); } - else + ELSE { - if ( st->last_extl != SWB_BWE && st->last_extl != FB_BWE ) + test(); + IF( NE_16( st->last_extl, SWB_BWE ) && NE_16( st->last_extl, FB_BWE ) ) { /* resample 48 kHz to 32kHz */ - if ( st->last_bwidth == FB ) + IF( EQ_16( st->last_bwidth, FB ) ) { inner_frame = L_FRAME48k; + move16(); inner_Fs = 48000; - mvr2r( hBWE_FD->old_fdbwe_speech, new_swb_speech, L_FRAME48k ); + move32(); + Copy( hBWE_FD->old_fdbwe_speech_fx, new_swb_speech, L_FRAME48k ); } - else + ELSE { inner_frame = L_FRAME32k; + move16(); inner_Fs = 32000; + move32(); - if ( st->element_mode != IVAS_CPE_DFT ) + IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) { - decimate_2_over_3_allpass( hBWE_FD->old_fdbwe_speech, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( hBWE_FD->old_fdbwe_speech_fx, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); } - else + ELSE { - lerp_flt( hBWE_FD->old_fdbwe_speech, new_swb_speech, inner_frame, L_FRAME48k ); + lerp( hBWE_FD->old_fdbwe_speech_fx, new_swb_speech, inner_frame, L_FRAME48k ); } - if ( st->element_mode == IVAS_CPE_DFT && st->idchan == 0 ) + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && st->idchan == 0 ) { - for ( i = 0; i < STEREO_DFT_OVL_32k; i++ ) + FOR( i = 0; i < STEREO_DFT_OVL_32k; i++ ) { - hCPE->hStereoDft->output_mem_dmx_32k[i] = new_swb_speech[inner_frame - STEREO_DFT_OVL_32k + i] * hCPE->hStereoDft->win_32k[STEREO_DFT_OVL_32k - 1 - i]; + hCPE->hStereoDft->output_mem_dmx_32k_fx[i] = Mpy_32_16_1( hCPE->hStereoDft->win_32k_fx[STEREO_DFT_OVL_32k - 1 - i], new_swb_speech[sub( add( inner_frame, i ), STEREO_DFT_OVL_32k )] ); + move32(); } } } - Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); - if ( st->element_mode > EVS_MONO && st->L_frame == L_FRAME16k ) + Sample_Delay_SWB_BWE = NS2SA_FX2( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + move16(); + test(); + IF( st->element_mode > EVS_MONO && EQ_16( st->L_frame, L_FRAME16k ) ) { - Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = NS2SA_FX2( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + move16(); } - if ( st->element_mode > EVS_MONO ) + IF( st->element_mode > EVS_MONO ) { - Sample_Delay_SWB_BWE -= NS2SA( inner_Fs, DELAY_FIR_RESAMPL_NS ); + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA_FX2( inner_Fs, DELAY_FIR_RESAMPL_NS ) ); } - mvr2r( new_swb_speech, &old_input[Sample_Delay_SWB_BWE], inner_frame ); - set_f( old_input, 0, Sample_Delay_SWB_BWE ); - mvr2r( new_swb_speech + inner_frame - Sample_Delay_SWB_BWE, hBWE_FD->old_input, Sample_Delay_SWB_BWE ); - mvr2r( old_input, hBWE_FD->old_wtda_swb, inner_frame ); + Copy( new_swb_speech, &old_input_fx[Sample_Delay_SWB_BWE], inner_frame ); + set16_fx( old_input_fx, 0, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech + inner_frame - Sample_Delay_SWB_BWE, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + Copy( old_input_fx, hBWE_FD->L_old_wtda_swb_fx, inner_frame ); } /* resample 48 kHz to 32kHz */ - if ( st->bwidth == FB ) + IF( EQ_16( st->bwidth, FB ) ) { - mvr2r( st->input, new_swb_speech, L_FRAME48k ); + Copy( st->input_fx, new_swb_speech, L_FRAME48k ); } - else + ELSE { - if ( st->element_mode == IVAS_CPE_TD ) + IF( EQ_16( st->element_mode, IVAS_CPE_TD ) ) { - float dec_2_over_3_mem_tmp[L_FILT_2OVER3], dec_2_over_3_mem_lp_tmp[L_FILT_2OVER3_LP]; + Word16 dec_2_over_3_mem_tmp[L_FILT_2OVER3], dec_2_over_3_mem_lp_tmp[L_FILT_2OVER3_LP]; - decimate_2_over_3_allpass( st->input, L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx, L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); - mvr2r( hBWE_TD->dec_2_over_3_mem, dec_2_over_3_mem_tmp, L_FILT_2OVER3 ); - mvr2r( hBWE_TD->dec_2_over_3_mem_lp, dec_2_over_3_mem_lp_tmp, L_FILT_2OVER3_LP ); + Copy( hBWE_TD->dec_2_over_3_mem_fx, dec_2_over_3_mem_tmp, L_FILT_2OVER3 ); + Copy( hBWE_TD->dec_2_over_3_mem_lp_fx, dec_2_over_3_mem_lp_tmp, L_FILT_2OVER3_LP ); - decimate_2_over_3_allpass( st->input + L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, new_swb_speech + L_FRAME32k - lMemRecalc32k, dec_2_over_3_mem_tmp, dec_2_over_3_mem_lp_tmp ); + decimate_2_over_3_allpass_fx( st->input_fx + L_FRAME48k - hCPE->hStereoTCA->lMemRecalc, hCPE->hStereoTCA->lMemRecalc, new_swb_speech + L_FRAME32k - lMemRecalc32k, dec_2_over_3_mem_tmp, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, dec_2_over_3_mem_lp_tmp ); } - else if ( st->element_mode != IVAS_CPE_DFT ) + ELSE IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) { - decimate_2_over_3_allpass( st->input, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); } - else /* IVAS_CPE_DFT */ + ELSE /* IVAS_CPE_DFT */ { - /*flt2fix*/ - f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); - f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); - f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); - f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); - /*flt2fix end*/ - Word16 out_start_ind, out_end_ind; stereo_dft_enc_synthesize_fx( hCPE->hStereoDft, new_swb_speech_fx, &out_start_ind, &out_end_ind, st->idchan, input_Fs, 32000, 0, NULL ); - - /*fix2flt*/ - hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); - hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); - fixedToFloat_arrL( new_swb_speech_fx + out_start_ind, new_swb_speech + out_start_ind, 16, out_end_ind - out_start_ind ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_res_8k_fx, hCPE->hStereoDft->output_mem_res_8k, 16, STEREO_DFT_OVL_8k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx, 16, STEREO_DFT_OVL_MAX ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_12k8_fx, hCPE->hStereoDft->output_mem_dmx_12k8, 16, STEREO_DFT_OVL_12k8 ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); - /*fix2flt end*/ - - mvr2r( new_swb_speech - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input, Sample_Delay_SWB_BWE32k ); + Copy_Scale_sig32_16( new_swb_speech_fx, new_swb_speech, q_reImBuffer, L_FRAME48k ); + Copy( new_swb_speech - Sample_Delay_SWB_BWE32k, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE32k ); } } } } - else + ELSE { /* resample 48 kHz to 32kHz */ - if ( st->bwidth == FB ) + IF( EQ_16( st->bwidth, FB ) ) { - mvr2r( st->input, new_swb_speech, L_FRAME48k ); + Copy( st->input_fx, new_swb_speech, L_FRAME48k ); } - else + ELSE { - decimate_2_over_3_allpass( st->input, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem, hBWE_TD->dec_2_over_3_mem_lp ); + decimate_2_over_3_allpass_fx( st->input_fx, L_FRAME48k, new_swb_speech, hBWE_TD->dec_2_over_3_mem_fx, allpass_poles_3_ov_2, decimate_3_ov_2_lowpass_num_fx, decimate_3_ov_2_lowpass_den_fx, hBWE_TD->dec_2_over_3_mem_lp_fx ); } } } - if ( ( st->core == ACELP_CORE && st->extl != SWB_BWE_HIGHRATE && st->extl != FB_BWE_HIGHRATE ) || - ( ( st->total_brate == ACELP_9k60 || st->rf_mode ) && st->bwidth == SWB && st->element_mode == EVS_MONO ) ) + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( st->core == ACELP_CORE ) && NE_16( st->extl, SWB_BWE_HIGHRATE ) && NE_16( st->extl, FB_BWE_HIGHRATE ) ) || + ( ( EQ_32( st->total_brate, ACELP_9k60 ) || st->rf_mode ) && EQ_16( st->bwidth, SWB ) && ( st->element_mode == EVS_MONO ) ) ) { - float CldfbHB = 0; Word32 CldfbHB_fx = 0; // fixed counterpart Word16 CldfbHB_fx_e = 0; // fixed counterpart +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + Word16 realQ_neg1, imagQ_neg1, exp = 0, Cldfbtemp1; + move32(); + move16(); + move16(); - if ( st->element_mode == IVAS_CPE_DFT ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - - /*flt2fix*/ - f2me_buf( hCPE->hStereoDft->DFT[0], hCPE->hStereoDft->DFT_fx[0], &hCPE->hStereoDft->DFT_fx_e[0], STEREO_DFT_N_MAX_ENC ); - f2me_buf( hCPE->hStereoDft->DFT[1], hCPE->hStereoDft->DFT_fx[1], &hCPE->hStereoDft->DFT_fx_e[1], STEREO_DFT_N_MAX_ENC ); - f2me( hCPE->hStereoDft->icbweRefEner, &hCPE->hStereoDft->icbweRefEner_fx, &hCPE->hStereoDft->icbweRefEner_fx_e ); - f2me( hCPE->hStereoDft->lbEner, &hCPE->hStereoDft->lbEner_fx, &hCPE->hStereoDft->lbEner_fx_e ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_res_8k, hCPE->hStereoDft->output_mem_res_8k_fx, 16, STEREO_DFT_OVL_8k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx, hCPE->hStereoDft->output_mem_dmx_fx, 16, STEREO_DFT_OVL_MAX ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_12k8, hCPE->hStereoDft->output_mem_dmx_12k8_fx, 16, STEREO_DFT_OVL_12k8 ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k, hCPE->hStereoDft->output_mem_dmx_16k_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb, hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, 16, STEREO_DFT_OVL_16k ); - floatToFixed_arrL( hCPE->hStereoDft->output_mem_dmx_32k, hCPE->hStereoDft->output_mem_dmx_32k_fx, 16, STEREO_DFT_OVL_32k ); - /*flt2fix end*/ - Word16 out_start_ind, out_end_ind; - CldfbHB_fx = stereo_dft_enc_synthesize_fx( hCPE->hStereoDft, old_input_fx + STEREO_DFT_OVL_16k, &out_start_ind, &out_end_ind, st->idchan, input_Fs, 16000, st->L_frame, &CldfbHB_fx_e ); - - /*fix2flt*/ - CldfbHB = me2f( CldfbHB_fx, CldfbHB_fx_e ); - hCPE->hStereoDft->icbweRefEner = me2f( hCPE->hStereoDft->icbweRefEner_fx, hCPE->hStereoDft->icbweRefEner_fx_e ); - hCPE->hStereoDft->lbEner = me2f( hCPE->hStereoDft->lbEner_fx, hCPE->hStereoDft->lbEner_fx_e ); - fixedToFloat_arrL( old_input_fx + STEREO_DFT_OVL_16k + out_start_ind, old_input + STEREO_DFT_OVL_16k + out_start_ind, 16, out_end_ind - out_start_ind ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_res_8k_fx, hCPE->hStereoDft->output_mem_res_8k, 16, STEREO_DFT_OVL_8k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_fx, hCPE->hStereoDft->output_mem_dmx, 16, STEREO_DFT_OVL_MAX ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_12k8_fx, hCPE->hStereoDft->output_mem_dmx_12k8, 16, STEREO_DFT_OVL_12k8 ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_fx, hCPE->hStereoDft->output_mem_dmx_16k, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_16k_shb_fx, hCPE->hStereoDft->output_mem_dmx_16k_shb, 16, STEREO_DFT_OVL_16k ); - fixedToFloat_arrL( hCPE->hStereoDft->output_mem_dmx_32k_fx, hCPE->hStereoDft->output_mem_dmx_32k, 16, STEREO_DFT_OVL_32k ); - /*fix2flt end*/ + Word16 exp_icbweRefEner_fx; + Copy_Scale_sig_16_32( (const Word16 *) &old_input_fx[0], &old_input_fx_32[0], NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k, Q16 ); + CldfbHB_fx = stereo_dft_enc_synthesize_fx( hCPE->hStereoDft, old_input_fx_32 + STEREO_DFT_OVL_16k, &out_start_ind, &out_end_ind, st->idchan, input_Fs, 16000, st->L_frame, &CldfbHB_fx_e ); + Copy_Scale_sig_32_16( (const Word32 *) &old_input_fx_32[0], &old_input_fx[0], NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k, -Q16 ); /* delay corresponding to CLDFB delay */ - mvr2r( old_input + STEREO_DFT_OVL_16k - 20, shb_speech, L_FRAME16k ); - mvr2r( old_input, hBWE_TD->old_speech_shb + L_LOOK_16k + L_SUBFR16k - ( STEREO_DFT_OVL_16k - 20 ), STEREO_DFT_OVL_16k - 20 ); - mvr2r( old_input, hCPE->hStereoICBWE->mem_shb_speech_ref, STEREO_DFT_OVL_16k - 20 ); + Copy( old_input_fx + STEREO_DFT_OVL_16k - 20, shb_speech, L_FRAME16k ); + Copy( old_input_fx, hBWE_TD->old_speech_shb_fx + L_LOOK_16k + L_SUBFR16k - ( STEREO_DFT_OVL_16k - 20 ), STEREO_DFT_OVL_16k - 20 ); + Copy( old_input_fx, hCPE->hStereoICBWE->mem_shb_speech_ref_fx, STEREO_DFT_OVL_16k - 20 ); - if ( CldfbHB <= 0 ) + IF( LE_32( CldfbHB_fx, 0 ) ) { - CldfbHB = 1.0f; + CldfbHB_fx = EPSILON_FX; + move32(); } - hBWE_TD->cldfbHBLT_flt = 0.9f * hBWE_TD->cldfbHBLT_flt + 0.1f * ( 0.221462f /*=1/log10(32768)*/ * ( log10f( CldfbHB ) - 1.0f ) ); - - lbEner = 0.05f * (float) sqrt( hCPE->hStereoDft->lbEner ); - hCPE->hStereoICBWE->icbweRefEner = 0.05f * (float) sqrt( hCPE->hStereoDft->icbweRefEner ); - lbEner = 0.05f * (float) sqrt( hCPE->hStereoDft->lbEner ); - thr = icbwe_thr_DFT; - regV = icbwe_regressionValuesDFT; + CldfbHB_fx = L_shl( CldfbHB_fx, exp ); /* CldfbHB_ener = CldfbHB_fl*2^(exp) */ +#if 0 + Cldfbtemp1 = ( Log2_norm_lc( CldfbHB_fx ) ); + Cldfbtemp1 = add( shr( Cldfbtemp1, 6 ), shl( sub( 30, sub( exp, 2 ) ), 9 ) ); /* Log2_norm_lc(CldfbHB_ener) = 2^15*(log2(CldfbHB_ener/2^30)) = 2^15*(log2(CldfbHB_fl*(2^-2)*2^exp/2^30)) = 2^15*(log2(CldfbHB_fl) + exp-2-30) => 2^(-6)*l2nc + 2^9(20-(exp-2)) = 2^9*log2(CldfbHB_fl), Q9 */ + CldfbHB_fx = L_mult( sub( Cldfbtemp1, 1741 /*3.401 Q9*/ ), 3495 ); /* 3495 = Q19 log10(2)*0.1/log10(32768), Q = 19+9+1 = 29 */ +#else + Cldfbtemp1 = Log2_norm_lc( CldfbHB_fx ); /* Log2_norm_lc(t) = 2^15*(log2(t/2^30)) */ + Cldfbtemp1 = sub( shr( Cldfbtemp1, 6 ), shl( add( sub( Q31 - Q30, CldfbHB_fx_e ), exp ), 9 ) ); + CldfbHB_fx = L_mult( Cldfbtemp1, 9864 ); /* Q9 + Q15 + Q1 = Q25 */ + CldfbHB_fx = Mpy_32_16_1( L_sub( CldfbHB_fx, 1 << Q25 ), 11611 /* 0.1 * 0.221462 in Q19 */ ); + /* Resulting Q = Q25 + Q19 - Q15 = Q29 */ +#endif + hBWE_TD->cldfbHBLT = mac_r( CldfbHB_fx, 29491 /*0.9 Q15*/, hBWE_TD->cldfbHBLT ); /* cldfbHBLT is in Q13 */ + move16(); + + exp_lbEner = hCPE->hStereoDft->lbEner_fx_e; + move32(); + lbEner = Mpy_32_16_1( Sqrt32( hCPE->hStereoDft->lbEner_fx, &exp_lbEner ), 1638 /* 0.05 in Q15 */ ); + exp_icbweRefEner_fx = hCPE->hStereoDft->icbweRefEner_fx_e; + move16(); + hCPE->hStereoICBWE->icbweRefEner_fx = Mpy_32_16_1( Sqrt32( hCPE->hStereoDft->icbweRefEner_fx, &exp_icbweRefEner_fx ), 1638 /* 0.05 in Q15 */ ); + move32(); + hCPE->hStereoICBWE->icbweRefEner_fx_e = exp_icbweRefEner_fx; + move16(); + // lbEner = 0.05f * (float) sqrt( hCPE->hStereoDft->lbEner ); + thr = icbwe_thr_DFT_fx; + regV = icbwe_regressionValuesDFT_fx; } - else + ELSE { - if ( st->L_frame == L_FRAME ) + IF( EQ_16( st->L_frame, L_FRAME ) ) { startB = 34; + move16(); endB = 14; - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + move16(); + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - for ( nB = startB, uB = 0; nB > endB; nB--, uB++ ) + uB = 0; + move16(); + FOR( nB = startB; nB > endB; nB-- ) { - sign = ( ts % 2 ) ? 1.0f : -1.0f; - realBufferFlipped[ts][uB] = -sign * realBuffer[ts][nB]; - imagBufferFlipped[ts][uB] = sign * imagBuffer[ts][nB]; + realBufferFlipped[ts][uB] = realBuffer[ts][nB]; + move32(); + if ( s_and( ts, 1 ) != 0 ) + { + realBufferFlipped[ts][uB] = L_negate( realBufferFlipped[ts][uB] ); + move32(); + } + imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + move32(); + if ( s_and( ts, 1 ) == 0 ) + { + imagBufferFlipped[ts][uB] = L_negate( imagBufferFlipped[ts][uB] ); + move32(); + } + uB = add( uB, 1 ); /* uB ++ */ } } } - else + ELSE { startB = 39; + move16(); endB = 19; - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + move16(); + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - for ( nB = startB, uB = 0; nB > endB; nB--, uB++ ) + uB = 0; + move16(); + FOR( nB = startB; nB > endB; nB-- ) { - realBufferFlipped[ts][uB] = -realBuffer[ts][nB]; + realBufferFlipped[ts][uB] = L_negate( realBuffer[ts][nB] ); + move32(); imagBufferFlipped[ts][uB] = imagBuffer[ts][nB]; + move32(); + uB = add( uB, 1 ); /* uB ++ */ } } } - for ( nB = 0; nB < 10; nB++ ) + FOR( nB = 0; nB < 10; nB++ ) { - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - CldfbHB += ( realBufferFlipped[ts][nB] * realBufferFlipped[ts][nB] + imagBufferFlipped[ts][nB] * imagBufferFlipped[ts][nB] ); + realQ_neg1 = extract_l( L_shr( realBufferFlipped[ts][nB], 16 ) ); + imagQ_neg1 = extract_l( L_shr( imagBufferFlipped[ts][nB], 16 ) ); /* Q(-1), headroom needed */ + +#ifdef BASOP_NOGLOB + CldfbHB_fx = L_mac0_o( CldfbHB_fx, realQ_neg1, realQ_neg1, &Overflow ); + CldfbHB_fx = L_mac0_o( CldfbHB_fx, imagQ_neg1, imagQ_neg1, &Overflow ); /* Q(-2) */ +#else + CldfbHB_fx = L_mac0( CldfbHB_fx, realQ_neg1, realQ_neg1 ); + CldfbHB_fx = L_mac0( CldfbHB_fx, imagQ_neg1, imagQ_neg1 ); /* Q(-2) */ +#endif } } - if ( CldfbHB <= 0 ) + CldfbHB_fx_e = sub( Q31, shl( sub( q_reImBuffer, Q16 ), 1 ) ); + exp = norm_l( CldfbHB_fx ); + CldfbHB_fx = L_shl( CldfbHB_fx, exp ); /* CldfbHB_ener = CldfbHB_fl*2^(exp) */ +#if 0 + Cldfbtemp1 = ( Log2_norm_lc( CldfbHB_fx ) ); + Cldfbtemp1 = add( shr( Cldfbtemp1, 6 ), shl( sub( 30, sub( exp, 2 ) ), 9 ) ); /* Log2_norm_lc(CldfbHB_ener) = 2^15*(log2(CldfbHB_ener/2^30)) = 2^15*(log2(CldfbHB_fl*(2^-2)*2^exp/2^30)) = 2^15*(log2(CldfbHB_fl) + exp-2-30) => 2^(-6)*l2nc + 2^9(20-(exp-2)) = 2^9*log2(CldfbHB_fl), Q9 */ + CldfbHB_fx = L_mult( sub( Cldfbtemp1, 1741 /*3.401 Q9*/ ), 3495 ); /* 3495 = Q19 log10(2)*0.1/log10(32768), Q = 19+9+1 = 29 */ +#else + Cldfbtemp1 = Log2_norm_lc( CldfbHB_fx ); /* Log2_norm_lc(t) = 2^15*(log2(t/2^30)) */ + Cldfbtemp1 = sub( shr( Cldfbtemp1, 6 ), shl( add( sub( Q31 - Q30, CldfbHB_fx_e ), exp ), 9 ) ); + CldfbHB_fx = L_mult( Cldfbtemp1, 9864 ); /* Q9 + Q15 + Q1 = Q25 */ + CldfbHB_fx = Mpy_32_16_1( L_sub( CldfbHB_fx, 1 << Q25 ), 11611 /* 0.1 * 0.221462 in Q19 */ ); + /* Resulting Q = Q25 + Q19 - Q15 = Q29 */ +#endif + hBWE_TD->cldfbHBLT = mac_r( CldfbHB_fx, 29491 /*0.9 Q15*/, hBWE_TD->cldfbHBLT ); /* cldfbHBLT is in Q13 */ + move32(); + + IF( CldfbHB_fx == 0 ) { - CldfbHB = 1.0f; + CldfbHB_fx = EPSILLON_FX; + move32(); } - hBWE_TD->cldfbHBLT_flt = 0.9f * hBWE_TD->cldfbHBLT_flt + 0.1f * ( 0.221462f /*=1/log10(32768)*/ * ( log10f( CldfbHB ) - 1.0f ) ); - if ( st->element_mode >= IVAS_CPE_DFT && hCPE->hStereoICBWE != NULL ) + test(); + IF( GE_16( st->element_mode, IVAS_CPE_DFT ) && hCPE->hStereoICBWE != NULL ) { - hCPE->hStereoICBWE->icbweRefEner = EPSILON; - for ( nB = 20; nB < 40; nB++ ) + Word32 icbweRefEner_fx = EPSILON_FX; + Word16 exp_icbweRefEner_fx = 0; + + move32(); + move16(); + FOR( nB = 20; nB < 40; nB++ ) { - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - hCPE->hStereoICBWE->icbweRefEner += ( realBuffer[ts][nB] * realBuffer[ts][nB] + imagBuffer[ts][nB] * imagBuffer[ts][nB] ); + realQ_neg1 = extract_l( L_shr( realBuffer[ts][nB], 16 ) ); + imagQ_neg1 = extract_l( L_shr( imagBuffer[ts][nB], 16 ) ); /* Q(-1), headroom needed */ + icbweRefEner_fx = L_mac0_o( icbweRefEner_fx, realQ_neg1, realQ_neg1, &Overflow ); + icbweRefEner_fx = L_mac0_o( icbweRefEner_fx, imagQ_neg1, imagQ_neg1, &Overflow ); /* Q(-2) */ } } - hCPE->hStereoICBWE->icbweRefEner = 0.05f * sqrtf( hCPE->hStereoICBWE->icbweRefEner ); + exp_icbweRefEner_fx = sub( Q31, shl( sub( q_reImBuffer, Q16 ), 1 ) ); + hCPE->hStereoICBWE->icbweRefEner_fx = Mpy_32_16_1( Sqrt32( icbweRefEner_fx, &exp_icbweRefEner_fx ), 1638 /* 0.05 in Q15 */ ); + move32(); + hCPE->hStereoICBWE->icbweRefEner_fx_e = exp_icbweRefEner_fx; + move16(); } - lbEner = EPSILON; - for ( nB = 0; nB < 20; nB++ ) + lbEner = EPSILON_FX; + move32(); + FOR( nB = 0; nB < 20; nB++ ) { - for ( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) + FOR( ts = 0; ts < CLDFB_NO_COL_MAX; ts++ ) { - lbEner += ( realBuffer[ts][nB] * realBuffer[ts][nB] + imagBuffer[ts][nB] * imagBuffer[ts][nB] ); + realQ_neg1 = extract_l( L_shr( realBuffer[ts][nB], 16 ) ); + imagQ_neg1 = extract_l( L_shr( imagBuffer[ts][nB], 16 ) ); /* Q(-1), headroom needed */ + + lbEner = L_mac0_o( lbEner, realQ_neg1, realQ_neg1, &Overflow ); + lbEner = L_mac0_o( lbEner, imagQ_neg1, imagQ_neg1, &Overflow ); /* Q(-2) */ } } - lbEner = 0.05f * sqrtf( lbEner ); - thr = icbwe_thr_TDM; - regV = icbwe_regressionValuesTDM; - - cldfbSynthesis_ivas( realBufferFlipped, imagBufferFlipped, shb_speech, -1, st->cldfbSynTd ); + exp_lbEner = sub( Q31, shl( sub( q_reImBuffer, Q16 ), 1 ) ); + lbEner = Mpy_32_16_1( Sqrt32( lbEner, &exp_lbEner ), 1638 /* 0.05 in Q15 */ ); + thr = icbwe_thr_TDM_fx; + regV = icbwe_regressionValuesTDM_fx; + + // Copy_Scale_sig_16_32((const Word16 *)&shb_speech[0], (Word32 *)&shb_speech_32[0], L_FRAME16k,Q16); + cldfbSynthesis_ivas_fx( realBufferFlipped, imagBufferFlipped, shb_speech_32, -1, st->cldfbSynTd ); + Copy_Scale_sig_32_16( (const Word32 *) &shb_speech_32[0], (Word16 *) &shb_speech[0], L_FRAME16k, negate( sub( q_reImBuffer, 1 ) ) ); } - if ( st->element_mode >= IVAS_CPE_DFT && hCPE->hStereoICBWE != NULL ) + IF( GE_16( st->element_mode, IVAS_CPE_DFT ) && hCPE->hStereoICBWE != NULL ) { + Word16 exp_t; hCPE->hStereoICBWE->MSFlag = 0; /* Init the multi-source flag */ - v = 0.3333f * sum_f( st->voicing, 3 ); - t = log10f( ( hCPE->hStereoICBWE->icbweRefEner + 1e-6f ) / ( lbEner + 1e-6f ) ); - + move16(); + v = Mpy_32_16_1( sum16_fx( st->voicing_fx, 3 ), 10923 /* 0.33333 in Q15 */ ); + + // t = log10f( ( hCPE->hStereoICBWE->icbweRefEner + 1e-6f ) / ( lbEner + 1e-6f ) ); + t = L_deposit_h( BASOP_Util_Divide3232_Scale( L_add( hCPE->hStereoICBWE->icbweRefEner_fx, EPSILON_FX ), L_add( lbEner, EPSILON_FX ), &exp_t ) ); + exp_t = add( exp_t, sub( hCPE->hStereoICBWE->icbweRefEner_fx_e, exp_lbEner ) ); + exp = norm_l( t ); + t = L_shl( t, exp ); + t_16 = Log2_norm_lc( t ); /* Log2_norm_lc(t) = 2^15*(log2(t/2^30)) */ + t_16 = sub( shr( t_16, 6 ), shl( add( sub( Q31 - Q30, exp_t ), exp ), 9 ) ); + t = L_mult( t_16, 9864 ); /* Q9 + Q15 + Q1 = Q25 */ /* Three Level Decision Tree to calculate a regression value first */ - if ( t < thr[0] ) /* level 1 */ + IF( LT_32( t, thr[0] ) ) /* level 1 */ { - if ( t < thr[1] ) /* level 2 */ + IF( LT_32( t, thr[1] ) ) /* level 2 */ { - regression = ( v < thr[3] ) ? regV[0] : regV[1]; /* level 3 */ + IF( LT_32( v, thr[3] ) ) + { + regression = regV[0]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[1]; + move32(); + } } - else + ELSE { - regression = ( v < thr[4] ) ? regV[2] : regV[3]; /* level 3 */ + IF( LT_32( v, thr[4] ) ) + { + regression = regV[2]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[3]; + move32(); + } } } - else + ELSE { - if ( t < thr[2] ) /* level 2 */ + IF( LT_32( t, thr[2] ) ) /* level 2 */ { - regression = ( v < thr[5] ) ? regV[4] : regV[5]; /* level 3 */ + IF( LT_32( v, thr[5] ) ) + { + regression = regV[4]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[5]; + move32(); + } } - else + ELSE { - regression = ( v < thr[6] ) ? regV[6] : regV[7]; /* level 3 */ + IF( LT_32( v, thr[6] ) ) + { + regression = regV[6]; /* level 3 */ + move32(); + } + ELSE + { + regression = regV[7]; + move32(); + } } } + test(); + test(); /* Convert the regression to a hard decision (classification) */ - if ( regression > 0.79f && !( st->bwidth < SWB || hCPE->hCoreCoder[0]->vad_flag == 0 ) ) + IF( GT_32( regression, 1696512081 /* 0.79f in Q31*/ ) && !( LT_16( st->bwidth, SWB ) || hCPE->hCoreCoder[0]->vad_flag == 0 ) ) { hCPE->hStereoICBWE->MSFlag = 1; + move16(); } } - if ( st->extl != WB_TBE && st->extl != SWB_TBE && st->extl != FB_TBE ) + test(); + test(); + IF( NE_16( st->extl, WB_TBE ) && NE_16( st->extl, SWB_TBE ) && NE_16( st->extl, FB_TBE ) ) { /* Update the previous superwideband speech buffer in case of a SWB_BWE frame - this code is in swb_tbe_enc */ delay = L_LOOK_16k + L_SUBFR16k; - mvr2r( shb_speech + L_FRAME16k - delay, hBWE_TD->old_speech_shb, delay ); + move16(); + Copy( shb_speech + sub( L_FRAME16k, delay ), hBWE_TD->old_speech_shb_fx, delay ); } } - else + ELSE { - if ( ( st->bwidth == FB || st->core == ACELP_CORE ) && ( st->element_mode == EVS_MONO ) ) + test(); + test(); + IF( ( EQ_16( st->bwidth, FB ) || st->core == ACELP_CORE ) && ( st->element_mode == EVS_MONO ) ) { -#ifdef IVAS_FLOAT_FIXED - InitSWBencBufferStates_fx( st->hBWE_TD, shb_speech_fx ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - /* To be removed */ - InitSWBencBufferStates( st->hBWE_TD, shb_speech ); -#endif -#else - InitSWBencBufferStates( st->hBWE_TD, shb_speech ); -#endif + InitSWBencBufferStates_fx( st->hBWE_TD, shb_speech ); } - else + ELSE { - if ( st->element_mode == IVAS_CPE_DFT ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - if ( st->L_frame == L_FRAME ) + IF( EQ_16( st->L_frame, L_FRAME ) ) { L_resamp = 560; /* 6.4 kHz core -> 6 - 14 kHz SHB target. 20 ms is 560 samples in 28 kHz sample rate */ + move16(); } - else + ELSE { L_resamp = 620; /* 8 kHz core -> 7.5 - 15.5 kHz SHB target. 20 ms is 620 samples in 31 kHz sample rate */ + move16(); } /* Dirty downsampling to match Nyquist to upper frequency limit of target */ - lerp_flt( st->input, new_swb_speech, L_resamp, (int16_t) ( input_Fs / 50 ) ); + lerp( st->input_fx, new_swb_speech, L_resamp, (int16_t) Mpy_32_32( input_Fs, one_by_50_Q31 ) ); /* flip the spectrum */ - mvr2r( new_swb_speech, spchTmp, L_resamp ); - for ( i = 0; i < L_resamp; i = i + 2 ) + Copy( new_swb_speech, spchTmp, L_resamp ); + FOR( i = 0; i < L_resamp; i = i + 2 ) { - spchTmp[i] = -spchTmp[i]; + spchTmp[i] = negate( spchTmp[i] ); + move16(); } /* Dirty upsampling to match Nyquist/2 to lower frequency limit of target (reversed spectrum)*/ - lerp_flt( spchTmp, spchTmp2, L_FRAME32k, L_resamp ); - mvr2r( spchTmp2, spchTmp, L_FRAME32k ); + lerp( spchTmp, spchTmp2, L_FRAME32k, L_resamp ); + Copy( spchTmp2, spchTmp, L_FRAME32k ); } - else + ELSE { /* flip the spectrum */ - mvr2r( new_swb_speech, spchTmp, L_FRAME32k ); + Copy( new_swb_speech, spchTmp, L_FRAME32k ); - for ( i = 0; i < L_FRAME32k; i = i + 2 ) + FOR( i = 0; i < L_FRAME32k; i = i + 2 ) { - spchTmp[i] = -spchTmp[i]; + spchTmp[i] = negate( spchTmp[i] ); + move16(); } } - Decimate_allpass_steep( spchTmp, hBWE_TD->state_ana_filt_shb, L_FRAME32k, shb_speech ); + Decimate_allpass_steep_fx( spchTmp, hBWE_TD->state_ana_filt_shb_fx, L_FRAME32k, shb_speech ); - mvr2r( shb_speech + L_FRAME16k - ( L_LOOK_16k + L_SUBFR16k ), hBWE_TD->old_speech_shb, L_LOOK_16k + L_SUBFR16k ); + Copy( shb_speech + L_FRAME16k - ( L_LOOK_16k + L_SUBFR16k ), hBWE_TD->old_speech_shb_fx, L_LOOK_16k + L_SUBFR16k ); /*Compute the past overlap for potential next iDFTs SHB*/ - if ( st->element_mode == IVAS_CPE_DFT ) + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) { - for ( i = 0; i < STEREO_DFT_OVL_16k; i++ ) + FOR( i = 0; i < STEREO_DFT_OVL_16k; i++ ) { - hCPE->hStereoDft->output_mem_dmx_16k_shb[i] = shb_speech[20 + i] * hCPE->hStereoDft->win_ana_16k[STEREO_DFT_OVL_16k - 1 - i] * hCPE->hStereoDft->win_ana_16k[STEREO_DFT_OVL_16k - 1 - i]; + hCPE->hStereoDft->output_mem_dmx_16k_shb_fx[i] = L_mult( shb_speech[20 + i], mult_r( hCPE->hStereoDft->win_ana_16k_fx[STEREO_DFT_OVL_16k - 1 - i], hCPE->hStereoDft->win_ana_16k_fx[STEREO_DFT_OVL_16k - 1 - i] ) ); + move32(); } } } - if ( st->element_mode != IVAS_CPE_DFT ) + IF( NE_16( st->element_mode, IVAS_CPE_DFT ) ) { /* Reset CLDFB synthesis buffer */ - set_f( st->cldfbSynTd->cldfb_state, 0.0f, st->cldfbSynTd->p_filter_length ); + set32_fx( st->cldfbSynTd->cldfb_state_fx, 0, st->cldfbSynTd->p_filter_length ); } - else + ELSE { - hCPE->hStereoDft->flip_sign = -hCPE->hStereoDft->flip_sign; /* Make sure sign is updated even if DFT SHB target is not generated */ + hCPE->hStereoDft->flip_sign = negate( hCPE->hStereoDft->flip_sign ); /* Make sure sign is updated even if DFT SHB target is not generated */ + move16(); } } /* Memory reset to compensate for 0.9375 ms offset when transitioning from IO to SWB */ /* When switching from n >1 to n = 1, we keep the enc/dec delay as 8.75/3.25 and below code not needed; only when n = 1 start, it will be 9.6875/2.3125 in that case this reset is needed for IO->BWE.*/ - if ( st->last_extl == -1 && st->element_mode == EVS_MONO ) + test(); + IF( EQ_16( st->last_extl, -1 ) && ( st->element_mode == EVS_MONO ) ) { - delay = NS2SA( input_Fs, DELAY_FIR_RESAMPL_NS ); - for ( i = 0; i < delay; i++ ) + delay = NS2SA_FX2( input_Fs, DELAY_FIR_RESAMPL_NS ); + move16(); + FOR( i = 0; i < delay; i++ ) { - shb_speech[i] = (float) i * ( 0.03f * shb_speech[2 * delay - 1 - i] ); + shb_speech[i] = mult_r( mult_r( i, 983 /*0.03f Q15*/ ), shb_speech[2 * delay - 1 - i] ); + move16(); } } diff --git a/lib_enc/swb_tbe_enc.c b/lib_enc/swb_tbe_enc.c index 4414d3762..61eec9e75 100644 --- a/lib_enc/swb_tbe_enc.c +++ b/lib_enc/swb_tbe_enc.c @@ -77,12 +77,7 @@ static void gainFrSmooth_En( TD_BWE_ENC_HANDLE hBWE_TD, const int16_t last_extl, static void Quant_BWE_LSF( BSTR_ENC_HANDLE hBstr, TD_BWE_ENC_HANDLE hBWE_TD, const int16_t codec_mode, const float lsp_shb[], float Q_lsfs[], const int32_t extl_brate ); static void Quant_shb_ener_sf( Encoder_State *st, float *shb_ener_sf ); static void Quant_shb_res_gshape( Encoder_State *st, float *shb_res_gshape ); -#ifdef IVAS_FLOAT_FIXED -static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, const Word16 lsf_shb_fx[], Word16 Q_lsfs_fx[], int16_t nbits ); -#else static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, const float lsf_shb[], float Q_lsfs[], int16_t nbits ); -#endif - /*-------------------------------------------------------------------* * InitSWBencBuffer() @@ -158,6 +153,10 @@ void InitSWBencBuffer( set_f( hBWE_TD->dec_2_over_3_mem, 0.0f, L_FILT_2OVER3 ); set_f( hBWE_TD->dec_2_over_3_mem_lp, 0.0f, L_FILT_2OVER3_LP ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( hBWE_TD->dec_2_over_3_mem_fx, 0, L_FILT_2OVER3 ); + set16_fx( hBWE_TD->dec_2_over_3_mem_lp_fx, 0, L_FILT_2OVER3_LP ); +#endif return; } @@ -181,6 +180,8 @@ void InitSWBencBufferStates( set_f( hBWE_TD->old_speech_shb, 0.0f, L_LOOK_16k + L_SUBFR16k ); set_f( hBWE_TD->mem_shb_res, 0.0f, MAX_LEN_MA_FILTER ); + set16_fx( hBWE_TD->mem_shb_res_fx, 0, MAX_LEN_MA_FILTER ); + set32_fx( hBWE_TD->mem_shb_res_32_fx, 0, MAX_LEN_MA_FILTER ); set_f( hBWE_TD->old_EnvSHBres, 0.0f, L_FRAME4k ); hBWE_TD->old_mean_EnvSHBres = 0.0f; hBWE_TD->prev_enr_EnvSHBres = 1.0f; @@ -1453,7 +1454,6 @@ void swb_tbe_enc( return; } - /*-------------------------------------------------------------------* * EstimateSHBFrameGain() * @@ -2014,386 +2014,13 @@ static void gainFrSmooth_En( return; } + /*-------------------------------------------------------------------* * Quant_BWE_LSF() * * Quantize super highband spectral envolope *-------------------------------------------------------------------*/ -#ifdef IVAS_FLOAT_FIXED -#define MAXINT32 MAX_32 -static void first_VQstages_fx( - const Word16 *const *cb, - Word16 u[], /* i : vector to be encoded (prediction and mean removed) */ - Word16 *levels, /* i : number of levels in each stage */ - Word16 stagesVQ, /* i : number of stages */ - Word16 w[], /* i : weights */ - Word16 N, /* i : vector dimension */ - Word16 max_inner, /* i : maximum number of swaps in inner loop */ - Word16 indices_VQstage[] ) -{ - Word16 resid_buf[2 * LSFMBEST * M], *resid[2]; - Word32 dist_buf[2 * LSFMBEST], *dist[2], en; - Word32 f_tmp, L_tmp, L_tmp1, *pTmp32; - Word16 Tmp[M], *pTmp, cs; - Word16 *pTmp_short, idx_buf[2 * LSFMBEST * MAX_VQ_STAGES], parents[LSFMBEST], counter = 0, j, - m, s, c, c2, p_max, *indices[2]; - move16(); - Word16 maxC = LSFMBEST; - move16(); -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move16(); -#endif - - /*float dd[16];*/ - const Word16 *cb_stage, *cbp; - - /* Set pointers to previous (parent) and current node (parent node is indexed [0], current node is indexed [1]) */ - indices[0] = idx_buf; - move16(); - indices[1] = idx_buf + maxC * stagesVQ; - move16(); - resid[0] = resid_buf; - move16(); - resid[1] = resid_buf + maxC * N; - move16(); - dist[0] = dist_buf; - move16(); - dist[1] = dist_buf + maxC; - move16(); - - set16_fx( idx_buf, 0, ( const Word16 )( 2 * stagesVQ * maxC ) ); - set16_fx( parents, 0, maxC ); - - /* Set up inital distance vector */ - L_tmp = L_deposit_l( 0 ); - FOR( j = 0; j < N; j++ ) - { -#ifdef BASOP_NOGLOB - L_tmp1 = L_shl_o( L_mult0( u[j], w[j] ), 7, &Overflow ); /*x2.56 + Q8 + Q7 */ -#else /* BASOP_NOGLOB */ - L_tmp1 = L_shl( L_mult0( u[j], w[j] ), 7 ); /*x2.56 + Q8 + Q7 */ -#endif /* BASOP_NOGLOB */ - L_tmp1 = Mult_32_16( L_tmp1, u[j] ); /*x2.56 + Q15 + x2.56 -Q15 */ - L_tmp = L_add( L_tmp, L_tmp1 ); /*Q0 + x2.56 +x2.56 */ - } - set32_fx( dist[1], L_tmp, maxC ); - - /* Set up initial error (residual) vectors */ - pTmp = resid[1]; - move16(); - FOR( c = 0; c < maxC; c++ ) - { - Copy( u, pTmp, N ); - pTmp += N; - } - - /*----------------------------------------------------------------* - * LSF quantization - *----------------------------------------------------------------*/ - - /* Loop over all stages */ - m = 1; - move16(); - FOR( s = 0; s < stagesVQ; s++ ) - { - /* set codebook pointer to point to first stage */ - cbp = cb[s]; - - /* save pointer to the beginning of the current stage */ - cb_stage = cbp; - - /* swap pointers to parent and current nodes */ - pTmp_short = indices[0]; - indices[0] = indices[1]; - move16(); - indices[1] = pTmp_short; - move16(); - - pTmp = resid[0]; - resid[0] = resid[1]; - move16(); - resid[1] = pTmp; - move16(); - - pTmp32 = dist[0]; - dist[0] = dist[1]; - move32(); - dist[1] = pTmp32; - move32(); - - /* p_max points to maximum distortion node (worst of best) */ - p_max = 0; - move16(); - - /* set distortions to a large value */ - set32_fx( dist[1], MAXINT32, maxC ); - - FOR( j = 0; j < levels[s]; j++ ) - { - /* compute weighted codebook element and its energy */ - FOR( c2 = 0; c2 < N; c2++ ) - { - Tmp[c2] = shl( mult( w[c2], cbp[c2] ), 2 ); /* Q8 + x2.56 -Q15 +Q2 */ - move16(); - } - - en = L_mult( cbp[0], Tmp[0] ); - - FOR( c2 = 1; c2 < N; c2++ ) - { - en = L_mac( en, cbp[c2], Tmp[c2] ); /*x2.56 + x2.56 + Q-5 +Q1 */ - } - cbp += N; - move16(); - - /* iterate over all parent nodes */ - FOR( c = 0; c < m; c++ ) - { - pTmp = &resid[0][c * N]; - move16(); - L_tmp = L_mult( pTmp[0], Tmp[0] ); - FOR( c2 = 1; c2 < N; c2++ ) - { - L_tmp = L_mac( L_tmp, pTmp[c2], Tmp[c2] ); /* */ - } - - L_tmp = L_add( dist[0][c], L_sub( en, L_shl( L_tmp, 1 ) ) ); - - IF( LE_32( L_tmp, dist[1][p_max] ) ) - { - /* replace worst */ - dist[1][p_max] = L_tmp; - move32(); - indices[1][p_max * stagesVQ + s] = j; - move16(); - parents[p_max] = c; - move16(); - - /* limit number of times inner loop is entered */ - IF( LT_16( counter, max_inner ) ) - { - counter = add( counter, 1 ); - IF( LT_16( counter, max_inner ) ) - { - /* find new worst */ - p_max = maximum_32_fx( dist[1], maxC, &f_tmp ); - } - ELSE - { - /* find minimum distortion */ - p_max = minimum_32_fx( dist[1], maxC, &f_tmp ); - } - } - } - } - } - - /*------------------------------------------------------------* - * Compute error vectors for each node - *------------------------------------------------------------*/ - cs = 0; - move16(); - FOR( c = 0; c < maxC; c++ ) - { - /* subtract codebook entry from the residual vector of the parent node */ - pTmp = resid[1] + c * N; - move16(); - Copy( resid[0] + parents[c] * N, pTmp, N ); - Vr_subt( pTmp, cb_stage + ( indices[1][cs + s] ) * N, pTmp, N ); - - /* get indices that were used for parent node */ - Copy( indices[0] + parents[c] * stagesVQ, indices[1] + cs, s ); - cs = add( cs, stagesVQ ); - } - - m = maxC; - move16(); - } - - Copy( indices[1], indices_VQstage, maxC * stagesVQ ); - - return; -} -static Word16 dotp_loc( - const Word16 x[], /* i : vector x[] */ - const Word32 y[], /* i : vector y[] */ - const int16_t n /* i : vector length */ -) -{ - Word16 i; - Word32 suma; - Word16 guarded_bits = find_guarded_bits_fx( n ); - suma = L_shr( Mpy_32_16_1( y[0], x[0] ), guarded_bits ); - - FOR( i = 1; i < n; i++ ) - { - suma = L_add( suma, L_shr( Mpy_32_16_1( y[i], x[i] ), guarded_bits ) ); - } - suma = L_shl_sat( suma, guarded_bits ); - - return extract_h( suma ); -} -static void LVQQuant_BWE_LSF( - BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle*/ - const Word16 lsf_shb_fx[], /* i : unquanitzed LSFs */ - Word16 Q_lsfs_fx[], /* o : quanitzed LSFs */ - Word16 nbits ) -{ - - Word16 lsf_fx[LPC_SHB_ORDER]; - Word16 lsf_q_fx[LPC_SHB_ORDER]; - Word16 i, c2, dim1 = 6; - move16(); - Word16 levels[1], numbits_VQ; - Word16 c2_fx_temp; - - Word16 w_fx[8] = { 5120, 5120, 2048, 2048, 2048, 1024, 1024, 1024 }; // Q0 - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - move16(); - Word16 cand_fx[LPC_SHB_ORDER], quant_fx[LPC_SHB_ORDER], e_fx[2], ftmp_fx; - const Word16 *cb_stage_fx; - Word16 indices_firstVQ[LSFMBEST]; - - Word16 Idx, idx_lead, idx_scale; - UWord32 LVQ_index; - Word16 dd_fx[LATTICE_DIM], cv_out_fx[LATTICE_DIM]; - Word16 bits_lvq, predictor_bits, empty_bits; - - empty_bits = 0; /* This is the difference to 21 bits, if we want lower number of bits */ - move16(); - nbits = sub( nbits, empty_bits ); /* THIS IS TO SIMULATE DIFFERENT NUMBER OF input BITS - should be removed */ - move16(); - c2 = sub( NUM_BITS_SHB_MSLVQ, nbits ); - move16(); - numbits_VQ = config_LSF_BWE[c2 * 3]; - move16(); - levels[0] = config_LSF_BWE[c2 * 3 + 1]; - move16(); - predictor_bits = config_LSF_BWE[c2 * 3 + 2]; - move16(); - IF( LT_16( nbits, 19 ) ) - { - cb_stage_fx = cb_LSF_BWE_fx[1]; - } - ELSE - { - cb_stage_fx = cb_LSF_BWE_fx[0]; - } - - FOR( i = 0; i < LPC_SHB_ORDER; i++ ) - { - lsf_fx[i] = sub( 16384, lsf_shb_fx[LPC_SHB_ORDER - 1 - i] ); - } - - /* remove mean */ - v_sub_16( lsf_fx, SHB_LSF_mean_fx, Q_lsfs_fx, LPC_SHB_ORDER ); - - /* 6D multi-stage 6bit coding */ - first_VQstages_fx( &cb_stage_fx, Q_lsfs_fx, levels, 1, w_fx, dim1, 3000, indices_firstVQ ); - - - /* 8D MSLVQ coding */ - bits_lvq = sub( sub( nbits, numbits_VQ ), predictor_bits ); - Copy( SHB_LSF_mean_fx, cand_fx, LPC_SHB_ORDER ); - - Idx = indices_firstVQ[0]; - - v_add_16( cand_fx, cb_stage_fx + Idx * dim1, cand_fx, dim1 ); - - /* LVQ quantization */ - Copy( cand_fx, quant_fx, LPC_SHB_ORDER ); - - v_sub_16( lsf_fx, cand_fx, dd_fx, LATTICE_DIM ); - - mslvq_ivas_16( dd_fx, quant_fx, cv_out_fx, &idx_lead, &idx_scale, w_fx, 0, ( nbits < 19 ), bits_lvq ); - - IF( EQ_16( idx_scale, -1 ) ) - { - set16_fx( cv_out_fx, 0, LATTICE_DIM ); - } - v_add_16( cand_fx, quant_fx, cand_fx, LATTICE_DIM ); - - /* arrange the LSF candidate vector prior to selection to an ascending order*/ - v_sort( cand_fx, 0, LPC_SHB_ORDER - 1 ); - - set16_fx( Q_lsfs_fx, 0, LPC_SHB_ORDER ); - /* mvr2r( mean_lsf, Q_lsfs, LPC_SHB_ORDER ); */ - - v_add_16( Q_lsfs_fx, cb_stage_fx + Idx * dim1, Q_lsfs_fx, dim1 ); - - /* write VQ indexes */ - push_indice( hBstr, IND_SHB_LSF, Idx, numbits_VQ ); - - /* write MSLVQ index */ - LVQ_index = index_lvq_SHB_fx( idx_lead, idx_scale, bits_lvq, cv_out_fx, ( nbits < 19 ) ); - - IF( GT_16( bits_lvq, 15 ) ) - { - push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) & ( 0xffff >> 1 ) ), 15 ); - push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) >> 15 ) & ( 0xffff >> 1 ), bits_lvq - 15 ); - } - ELSE - { - push_indice( hBstr, IND_SHB_LSF, (Word16) LVQ_index, bits_lvq ); - } - - v_add_16( Q_lsfs_fx, quant_fx, lsf_q_fx, LATTICE_DIM ); /* quantized mean removed data for first 8 dim*/ - - /* predict last 2 components */ - IF( predictor_bits == 0 ) - { - lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, LastCoefPred_0bit_fx, LATTICE_DIM ); - lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_0bit_fx[LATTICE_DIM + 1], LATTICE_DIM ); - } - ELSE - { - v_sub_16( &lsf_fx[LATTICE_DIM], &SHB_LSF_mean_fx[LATTICE_DIM], &lsf_q_fx[LATTICE_DIM], 2 ); - - FOR( i = 0; i < 2; i++ ) - { - ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM]; - - e_fx[i] = mult( ftmp_fx, ftmp_fx ); - - ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i + LATTICE_DIM + 1], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM + 1]; - - e_fx[i] = add_sat( e_fx[i], mult( ftmp_fx, ftmp_fx ) ); - } - - c2_fx_temp = minimum_fx( e_fx, 2, &ftmp_fx ); - - lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp], LATTICE_DIM ); - - lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp + LATTICE_DIM + 1], LATTICE_DIM ); - - push_indice( hBstr, IND_SHB_LSF, c2, 1 ); - } - - if ( empty_bits > 0 ) - { - push_indice( hBstr, IND_SHB_LSF, 0, empty_bits ); - } - - v_add_16( SHB_LSF_mean_fx, lsf_q_fx, lsf_q_fx, LPC_SHB_ORDER ); - - v_sort( lsf_q_fx, 0, LPC_SHB_ORDER - 1 ); - - FOR( i = 0; i < LPC_SHB_ORDER; i++ ) - { - Q_lsfs_fx[i] = sub_sat( 16384, lsf_q_fx[LPC_SHB_ORDER - 1 - i] ); - } - - return; -} -#else static void LVQQuant_BWE_LSF( BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle*/ const float lsf_shb[], /* i : unquanitzed LSFs */ @@ -2530,7 +2157,6 @@ static void LVQQuant_BWE_LSF( return; } -#endif /*-------------------------------------------------------------------* * Quant_BWE_LSF() * @@ -2556,25 +2182,7 @@ static void Quant_BWE_LSF( if ( extl_brate == SWB_TBE_1k75 ) { - -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 lsf_shb_fx[LPC_SHB_ORDER]; - for ( i = 0; i < LPC_SHB_ORDER; i++ ) - { - lsf_shb_fx[i] = (Word16) ( lsf_shb[i] * 32767 ); - } -#endif - LVQQuant_BWE_LSF( hBstr, lsf_shb_fx, lsf_shb_fx, NUM_BITS_SHB_MSLVQ ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - for ( i = 0; i < LPC_SHB_ORDER; i++ ) - { - Q_lsfs[i] = (float) ( (float) lsf_shb_fx[i] / 32767.0 ); - } -#endif -#else LVQQuant_BWE_LSF( hBstr, lsf_shb, Q_lsfs, NUM_BITS_SHB_MSLVQ ); -#endif } else { @@ -2775,6 +2383,7 @@ static void Quant_shb_ener_sf( return; } + /*-------------------------------------------------------------------* * Quant_shb_res_gshape() * diff --git a/lib_enc/swb_tbe_enc_fx.c b/lib_enc/swb_tbe_enc_fx.c index 90940ccfa..c52458790 100644 --- a/lib_enc/swb_tbe_enc_fx.c +++ b/lib_enc/swb_tbe_enc_fx.c @@ -12,8 +12,18 @@ #include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ +#include "ivas_prot.h" /* Function prototypes */ #include "stl.h" + +/*-----------------------------------------------------------------* + * Local constants + *-----------------------------------------------------------------*/ + +#define ENVSHBRES_ACORR_MIN 40 /* minimum lag for calculating autocorrelation function on SHB residual TD envelope */ +#define ENVSHBRES_ACORR_MAX 80 /* maximum lag for calculating autocorrelation function on SHB residual TD envelope */ + + /*-----------------------------------------------------------------* * Local functions *-----------------------------------------------------------------*/ @@ -78,10 +88,19 @@ static void Quant_lower_LSF_fx( const Word16 lsf[], static Word16 Quant_mirror_point_fx( const Word16 lsf[], const Word16 lsf_q[], Word16 *m ); static Word16 Find_LSF_grid_fx( const Word16 lsf[], Word16 lsf_q[], const Word16 m ); + static void Quant_BWE_LSF_fx( Encoder_State *st_fx, const Word16 lsp_shb[], Word16 Q_lsfs[] ); + +static void Quant_BWE_LSF_ivas_fx( BSTR_ENC_HANDLE hBstr, TD_BWE_ENC_HANDLE hBWE_TD, const Word16 codec_mode, const Word16 lsf_shb_fx[], Word16 Q_lsfs_fx[], const Word32 extl_brate ); + static void Quant_shb_ener_sf_fx( Encoder_State *st_fx, Word32 *shb_ener_sf_fx_32, Word16 Q_shb ); + +static void Quant_shb_ener_sf_ivas_fx( Encoder_State *st_fx, Word32 *shb_ener_sf_Q31, Word16 Q_ener ); + static void Quant_shb_res_gshape_fx( Encoder_State *st_fx, Word16 *shb_res_gshape_fx ); +static void Quant_shb_res_gshape_ivas_fx( Encoder_State *st, Word16 shb_res_gshape_fx[] ); + static void gainFrSmooth_En_fx( Encoder_State *st_fx, Word16 *shb_frame_fx, const Word16 *lpc_shb_fx, @@ -1765,6 +1784,8 @@ void fb_tbe_reset_enc_fx( return; } + + /*======================================================================================*/ /* FUNCTION : void swb_tbe_enc_fx () */ /*--------------------------------------------------------------------------------------*/ @@ -2656,114 +2677,1704 @@ void swb_tbe_enc_fx( } -/*==========================================================================*/ -/* FUNCTION : static void EstimateSHBFrameGain_fx() */ -/*--------------------------------------------------------------------------*/ -/* PURPOSE : Estimate the overall gain factor needed to scale */ -/* synthesized highband to original highband signal level. */ -/*--------------------------------------------------------------------------*/ +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_enc_ivas_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ +/*--------------------------------------------------------------------------------------*/ /* INPUT ARGUMENTS : */ -/* _(Word16) length : SHB overlap length Q0 */ -/* _(Word16*) oriSHB : target original SHB frame Q_oriSHB */ -/* _(Word16*) synSHB : shaped SHB excitation Q_synSHB */ -/* _(Word16*) win_shb : SHB window Q15 */ -/* _(Word16*) subwin_shb_local : SHB subframe window Q15 */ -/* _(Word16) Q_oriSHB : Q format of oriSHB */ -/* _(Word16) Q_synSHB : Q format of synSHB */ -/*--------------------------------------------------------------------------*/ +/* _(Word16) coder_type : coding type */ +/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/*--------------------------------------------------------------------------------------*/ /* OUTPUT ARGUMENTS : */ -/* _(Word32*)GainFrame :estimat of gain frame Q18 */ -/*--------------------------------------------------------------------------*/ +/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ +/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ /* INPUT/OUTPUT ARGUMENTS : */ -/* _None */ -/*--------------------------------------------------------------------------*/ +/* _ Encoder_State *st_fx: : Encoder state structure */ +/*--------------------------------------------------------------------------------------*/ /* RETURN ARGUMENTS : */ /* _ None */ -/*--------------------------------------------------------------------------*/ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*======================================================================================*/ -static void EstimateSHBFrameGain_fx( - const Word16 length, /* i : SHB overlap length */ - const Word16 *oriSHB, /* i : target original SHB frame Q(Q_oriSHB) */ - const Word16 Q_oriSHB, /* i : Q of arget original SHB frame */ - const Word16 *synSHB, /* i : shaped SHB excitation Q(Q_synSHB) */ - const Word16 Q_synSHB, /* i : Q of shaped SHB excitation */ - Word16 *subgain, /* i : estimate of gain shape Q15 */ - Word32 *GainFrame, /* o : estimat of gain frame Q18 */ - const Word16 *win_shb, /* i : SHB window Q15 */ - const Word16 *subwin_shb_local, /* i : SHB subframe window Q15 */ - const Word16 n_subfr_saturation /* i : Number of subframes which saturated in GainShape oriNrg calculation */ +void swb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + STEREO_ICBWE_ENC_HANDLE hStereoICBWE, /* i/o: IC-BWE state structure */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb */ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2 * Q_new */ + const Word16 voice_factors_fx[], /* i : voicing factors Q15 */ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc */ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6 */ ) { - const Word16 *skip; - Word16 i, j, k, l_shb_lahead, l_frame; - Word16 join_length, num_join, sig; - Word32 mod_syn[L_FRAME16k + L_SHB_LAHEAD]; - Word32 oriNrg, synNrg; - Word16 sum_gain; - Word32 frame_gain; - Word32 L_tmp; - Word16 exp_out; - Word16 tmp; - Word16 scaling = 0; + Word16 i, j, k, delay; + + Word16 shb_old_speech_fx[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + Word16 bwe_exc_extended_16[L_FRAME32k + NL_BUFF_OFFSET]; + + Word16 shaped_shb_excitation_fx[L_FRAME16k + L_SHB_LAHEAD]; + Word32 GainFrame_fx; /* Q18 */ + Word16 GainShape_fx[NUM_SHB_SUBFR]; /* Q15 */ + Word16 lpc_shb_fx[LPC_SHB_ORDER + 1], lsp_shb_fx[LPC_SHB_ORDER], lsf_shb_fx[LPC_SHB_ORDER]; + Word16 weights_lsp[LPC_SHB_ORDER]; + Word16 Q_out; + Word16 *shb_frame_fx, *shb_new_speech_fx; + Word16 R_h[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER + 1]; + + Word16 ana_align_delay; + Word32 prev_pow_fx, curr_pow_fx, Lscale; + Word32 p2m_in_fx, p2m_out_fx; + + Word16 exp_out, exp, exp1, frac; + Word16 cnt, n_mem, n_mem2; + Word32 L_tmp, L_tmp1; + Word16 Q_bwe_exc; + + Word16 frGainAttenuate, frGainSmoothEn; + Word16 MA_lsp_shb_spacing; + Word16 temp_swb_fac, feedback; + Word32 L_feedback; + Word16 tmp, tmp1, tmp2; + Word32 Lmax; + Word16 sc; + Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; + Word16 sd_uq_q_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 pitBufAvg_fx; + Word16 voicingBufAvg_fx; + Word16 sum1, sum2; + Word16 recip, Q_recip; + const Word16 *ptr_lsp_interp_coef_fx; + + Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; + Word16 lpc_shb_sf_fx[4 * ( LPC_SHB_ORDER + 1 )]; + + /*Word32 shb_ener_sf_fx_32[4];*/ + Word32 shb_ener_sf_Q31; + Word16 shb_res_fx[L_FRAME16k]; + Word16 shb_res_gshape_fx[NB_SUBFR16k]; + Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; + Word16 vf_ind_fx; + + Word16 formant_fac_fx; + // int16_t stab_check = 1; + Word16 MSFlag; + Word16 *nlExc16k_fx, *mixExc16k_fx; + + Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; + + Word16 acorr_v2a_fx; /* Q15 */ + + Word16 acorr_EnvSHBres[ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN], *p_acorr, shb_env_tilt_fx; + Word16 buf_EnvSHBres_fx[2 * L_FRAME4k], *p_buf, EnvSHBres_fx[L_FRAME16k], EnvSHBres_4k_fx[L_FRAME4k], EnvSHBres_4k_norm_fx[L_FRAME4k], env_mean_normf_fx[L_FRAME4k]; + Word16 GainShape_Interp_fx[NUM_SHB_SUBGAINS], GainShape_tilt_fx; /* Q15 */ + Word16 seg_mean[4], den_seg_mean[4], *p_env, step; + Word16 temp, scale_fx, scale_e, pow_e, tmp_e, tmp1_e; + Word16 seg_len, seg_len_2; + Word16 den_seg_len, den_seg_len_2, fact_atten_fx; /* Q15 */ + Word32 sum_gain_fx, normFact_fx; + Word32 pow0_fx, alpha_fx; + Word16 Env_error_part_fx[NUM_SHB_SUBGAINS], Env_error_fx; /* Q0 */ + + Word16 mean_vf; + Word16 lsf_diff_fx[LPC_SHB_ORDER], w_fx[LPC_SHB_ORDER]; + Word16 refl_fx[M]; + Word16 tilt_para_fx; + Word16 Q_bwe_exc_fb; + Word16 n_subfr_saturation; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; move32(); #endif - move16(); - /* initilaization */ - l_frame = L_FRAME16k; + Env_error_fx = 0; move16(); - l_shb_lahead = L_SHB_LAHEAD; + pitBufAvg_fx = 0; + move16(); + voicingBufAvg_fx = 0; + move16(); + set16_fx( Env_error_part_fx, 0, NUM_SHB_SUBGAINS ); + shb_env_tilt_fx = 0; + move16(); + sum1 = 0; + move16(); + sum2 = 0; move16(); - skip = skip_bands_SWB_TBE; - IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + /* init and buffers set up */ + exp1 = 0; /* to avoid compilation warnings */ + move16(); + + IF( st_fx->element_mode >= IVAS_CPE_DFT && hStereoICBWE != NULL ) { - skip = skip_bands_WB_TBE; - l_frame = L_FRAME16k / 4; + nlExc16k_fx = hStereoICBWE->nlExc16k_fx; + mixExc16k_fx = hStereoICBWE->mixExc16k_fx; + MSFlag = hStereoICBWE->MSFlag; move16(); - l_shb_lahead = L_SHB_LAHEAD / 4; + } + ELSE + { + nlExc16k_fx = NULL; + mixExc16k_fx = NULL; + MSFlag = 0; move16(); } - /* apply gain for each subframe, and store noise output signal using overlap-add*/ - set32_fx( mod_syn, 0, l_frame + l_shb_lahead ); + set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); - IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) + test(); + test(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) && ( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) ) { - sum_gain = 0; + ana_align_delay = -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ) + 20; /* 20 corresponds to the 1.25 ms CLDFB delay */ move16(); - j = skip[0]; + } + ELSE + { + ana_align_delay = -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ); move16(); - FOR( k = 0; k < length / 2; k++ ) + } + + /* compensate for the delay in target generation and subframe LA */ + shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay; + + set16_fx( shb_old_speech_fx, 0, L_LOOK_16k + L_SUBFR16k + L_FRAME16k ); + + /* set up the speech buffers for TBE processing*/ + delay = L_LOOK_16k + L_SUBFR16k; + move16(); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + shb_new_speech_fx = shb_old_speech_fx + delay - L_MEM_RECALC_TBE_16K; + } + ELSE + { + shb_new_speech_fx = shb_old_speech_fx + delay; + } + + Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, delay ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, delay ); + + /* autocorrelation of SHB speech for 10-th order LP analysis */ + autocorr_fx( shb_old_speech_fx, + LPC_SHB_ORDER + 1, + R_h, /* autocorr (msb) Q15 */ + R_l, /* autocorr (lsb) */ + &Q_R, + NS2SA( INT_FS_16k, ACELP_LOOK_NS ) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb_fx, + 0, + 1 ); + + + /* Spectral smoothing of autocorrelation coefficients */ + test(); + test(); + IF( st_fx->rf_mode || EQ_32( st_fx->extl_brate, SWB_TBE_0k95 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) { - sum_gain = mult_r( subwin_shb_local[2 * k + 2], subgain[0] ); /* Q15 */ - mod_syn[j + k] = L_mult( synSHB[j + k], sum_gain ); - move32(); /* Q(16+Q_synSHB) */ - mod_syn[j + k + length / 2] = L_mult( synSHB[j + k + length / 2], subgain[0] ); - move32(); /* Q(16+Q_synSHB) */ + L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); } + } - FOR( i = 1; i < NUM_SHB_SUBFR / 2; i++ ) + /* Set the autocorr[0] element to a non-negative value */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL ); /* LPC in Q14 */ + { + Word16 enerG, lpc_shb1[M + 1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set16_fx( lpc_shb1, 0, M + 1 ); + Copy( lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1 ); + + /* estimate the LP gain */ + enerG = Enr_1_Az_fx( lpc_shb1, 2 * L_SUBFR ); /* Q3 */ + + /* if the LP gain is greater than a threshold, avoid saturation */ + IF( GT_16( enerG, 256 /*32 Q3*/ ) ) { - j = skip[i]; - move16(); - FOR( k = 0; k < length; k++ ) - { - L_tmp = L_mult0( subwin_shb_local[k + 1], subgain[i] ); /* Q30 */ - sum_gain = round_fx( L_mac0( L_tmp, subwin_shb_local[length - k - 1], subgain[i - 1] ) ); /* Q14 */ - mod_syn[j + k] = L_shl( L_mult( sum_gain, synSHB[j + k] ), 1 ); - move32(); /* Q(16+Q_synSHB) */ - } + set16_fx( lpc_shb_fx, 0, LPC_SHB_ORDER + 1 ); + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, 2, NULL ); /* LPC in Q14 */ } - FOR( k = 0; k < length / 2; k++ ) + } + + /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + test(); + test(); + IF( st_fx->rf_mode || EQ_32( st_fx->extl_brate, SWB_TBE_0k95 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) { - j = skip[i]; + lpc_shb_fx[i] = mult_r( lpc_shb_fx[i], lpc_weights_fx[i] ); move16(); - sum_gain = mult_r( subwin_shb_fx[length - 2 * k - 2], subgain[i - 1] ); /* Q15 */ - mod_syn[j + k] = L_mult( synSHB[j + k], sum_gain ); - move32(); /* Q(16+Q_synSHB) */ + } + } + + /* stab_check = a2lsp( lsf_shb, lpc_shb, LPC_SHB_ORDER ); - stab_check missing */ + /* LPC to LSP conversion */ + /* LPC: Q12, LSP: Q15 */ + E_LPC_a_lsp_conversion( lpc_shb_fx, lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + + /* LSP to LSF conversion */ + /* LSP: Q15, LSF: Q15 */ + E_LPC_lsp_lsf_conversion( lsp_shb_fx, lsf_shb_fx, LPC_SHB_ORDER ); + + test(); + test(); + IF( ( NE_16( st_fx->last_extl, SWB_TBE ) && NE_16( st_fx->last_extl, FB_TBE ) ) || st_fx->ini_frame == 0 ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + // hBWE_TD->prev_lsp_shb_fx[i] = i / 20.0f; + hBWE_TD->prev_lsp_shb_fx[i] = lsp_shb_prev_tbl_fx[i]; + move16(); + } + } + + // if ( stab_check == 0 ) + //{ + // mvr2r( hBWE_TD->prev_lsp_shb, lsf_shb, LPC_SHB_ORDER ); + // } + + Copy( lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + Copy( lsf_shb_fx, lsf_shb_orig_fx, LPC_SHB_ORDER ); + + /* Input signal filtering in case of tonal sounds in the high band + gain Frame smoothing and attenuation control */ + gainFrSmooth_En_fx( st_fx, shb_frame_fx, lpc_shb_fx, lsf_shb_fx, &MA_lsp_shb_spacing, &frGainAttenuate, &frGainSmoothEn ); + + test(); + test(); + IF( st_fx->rf_mode || EQ_32( st_fx->extl_brate, SWB_TBE_0k95 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) ) + { + lsp_weights_fx( lsf_shb_fx, weights_lsp, LPC_SHB_ORDER, &Q_out ); + + /* to compensate for the 1.1* weighting done inside the function lsp_weights */ + /*weights_lsp[3]*=0.909091f; weights_lsp[4]*=0.909091f; */ + weights_lsp[3] = mult_r( weights_lsp[3], 29789 /*0.909091f Q15*/ ); + move16(); + weights_lsp[4] = mult_r( weights_lsp[4], 29789 /*0.909091f Q15*/ ); + move16(); + + /* 8-bit VQ, 10 dimension */ + i = closest_centroid_fx( lsf_shb_fx, weights_lsp, swb_tbe_lsfvq_cbook_8b, 256, LPC_SHB_ORDER ); + Copy( swb_tbe_lsfvq_cbook_8b + i * LPC_SHB_ORDER, lsf_shb_fx, LPC_SHB_ORDER ); + + set16_fx( hBWE_TD->lsf_idx, 0, NUM_Q_LSF ); + + IF( EQ_16( st_fx->codec_mode, MODE1 ) ) + { + push_indice( hBstr, IND_SHB_LSF, i, 8 ); + } + ELSE + { + hBWE_TD->lsf_idx[0] = i; + move16(); + } + } + ELSE + { + /* LSF quantization (21 bits) */ + Quant_BWE_LSF_ivas_fx( hBstr, st_fx->hBWE_TD, st_fx->codec_mode, lsf_shb_fx, lsf_shb_fx, st_fx->extl_brate ); + } + + /* space the lsfs to assert a minimum distance */ + space_lsfs_fx( lsf_shb_fx, LPC_SHB_ORDER ); + + /* voice factor adjustment and gainframe attenuation factor */ + tmp = sub( lsf_shb_fx[0], lsf_shb_orig_fx[0] ); + L_tmp = L_mult( tmp, tmp ); + FOR( i = 1; i < LPC_SHB_ORDER; i++ ) + { + /* Estimate the QD in lsfs between UQ and Q */ + tmp = sub( lsf_shb_fx[i], lsf_shb_orig_fx[i] ); + L_tmp = L_mac( L_tmp, tmp, tmp ); + } + sd_uq_q_fx = round_fx( L_tmp ); /* sd_uq_q_fx in Q15 */ + /* voice factor modification to limit any spurious jumps in the middle of voiced subframes*/ + /* mean(voice_factors_fx[i], 4); */ + + L_tmp = L_mult( voice_factors_fx[0], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[1], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[2], 8192 ); + mean_vf = mac_r( L_tmp, voice_factors_fx[3], 8192 ); + + Copy( voice_factors_fx, vf_modified_fx, NB_SUBFR16k ); + + test(); + IF( EQ_16( st_fx->coder_type, VOICED ) || GT_16( mean_vf, 13107 /*0.4f Q15*/ ) ) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mult( voice_factors_fx[i], 26214 ); + vf_modified_fx[i] = mac_r( L_tmp, voice_factors_fx[i - 1], 6554 ); + move16(); + } + IF( NE_16( st_fx->L_frame, L_FRAME ) ) + { + L_tmp = L_mult( voice_factors_fx[4], 26214 ); + vf_modified_fx[4] = mac_r( L_tmp, voice_factors_fx[3], 6554 ); + move16(); + } + } + + /* convert quantized LSFs to LSPs for interpolation */ + E_LPC_lsf_lsp_conversion( lsf_shb_fx, lsp_shb_2_fx, LPC_SHB_ORDER ); + + test(); + IF( EQ_16( st_fx->last_extl, SWB_TBE ) || EQ_16( st_fx->last_extl, FB_TBE ) ) + { + /* SHB LSP values from prev. frame for interpolation */ + Copy( hBWE_TD->swb_lsp_prev_interp_fx, lsp_shb_1_fx, LPC_SHB_ORDER ); + } + ELSE + { + /* Use current frame's LSPs; in effect no interpolation */ + Copy( lsp_shb_2_fx, lsp_shb_1_fx, LPC_SHB_ORDER ); + } + + lsf_diff_fx[0] = lsf_diff_fx[sub( LPC_SHB_ORDER, 1 )] = 16384; /*Q15*/ + move16(); + FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) + { + lsf_diff_fx[i] = sub( lsf_shb_fx[i], lsf_shb_fx[sub( i, 1 )] ); + move16(); + } + a2rc_fx( hBWE_TD->cur_sub_Aq_fx + 1, refl_fx, M ); + + /* LSP interpolation for 13.2 kbps and 16.4 kbps */ + /* tilt_para_fx = 6.6956f * (1.0f + refl_fx[0]) * (1.0f + refl_fx[0]) + - 3.8714f * (1.0f + refl_fx[0]) + + 1.3041f; */ + tmp = add( 16384, shr( refl_fx[0], 1 ) ); /*Q14*/ + tmp1 = mult( 27425 /*Q12*/, tmp ); /*Q11*/ + tmp1 = mult( tmp1, tmp ); + tmp2 = shr( mult( 31715, tmp ), 2 ); /* Q11 */ + tilt_para_fx = add( sub( tmp1, tmp2 ), 1335 ); /*Q10*/ + + IF( NE_16( st_fx->last_extl, SWB_TBE ) ) + { + FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) + { + hBWE_TD->prev_lsf_diff_fx[i - 1] = mult( lsf_diff_fx[i], 16384 ); /*Q15*/ + move16(); + } + } + + IF( LE_32( st_fx->extl_brate, FB_TBE_1k8 ) ) + { + test(); + test(); + test(); + test(); + test(); + IF( !( GT_16( hBWE_TD->prev_tilt_para_fx, 5120 /* 5.0f in Q10 */ ) && ( EQ_16( st_fx->coder_type, TRANSITION ) || LT_16( tilt_para_fx, 1024 /* 1.0f in Q10 */ ) ) ) && + !( ( ( LT_16( hBWE_TD->prev_tilt_para_fx, 3072 /* 3.0f in Q10 */ ) && GE_16( hBWE_TD->prev_coder_type, VOICED ) ) ) && GT_16( tilt_para_fx, 5120 /* 5.0f in Q10 */ ) ) ) + { + FOR( i = 1; i < LPC_SHB_ORDER - 1; i++ ) + { + IF( LT_16( lsf_diff_fx[i], hBWE_TD->prev_lsf_diff_fx[i - 1] ) ) + { + tmp = mult( 26214, lsf_diff_fx[i] ); + tmp = div_s( tmp, hBWE_TD->prev_lsf_diff_fx[i - 1] ); + tmp = s_max( tmp, 16384 ); + w_fx[i] = s_min( tmp, 32767 ); + move16(); + } + ELSE + { + tmp = mult( 26214, hBWE_TD->prev_lsf_diff_fx[i - 1] ); + tmp = div_s( tmp, lsf_diff_fx[i] ); + tmp = s_max( tmp, 16384 ); + w_fx[i] = s_min( tmp, 32767 ); + move16(); + } + } + w_fx[0] = w_fx[1]; + move16(); + w_fx[sub( LPC_SHB_ORDER, 1 )] = w_fx[sub( LPC_SHB_ORDER, 2 )]; + move16(); + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + tmp1 = mult( lsp_shb_1_fx[i], sub( 32767, w_fx[i] ) ); + tmp2 = mult( lsp_shb_2_fx[i], w_fx[i] ); + lsp_temp_fx[i] = add( tmp1, tmp2 ); + move16(); + } + } + ELSE + { + Copy( lsp_shb_2_fx, lsp_temp_fx, LPC_SHB_ORDER ); + } + } + + Copy( lsf_diff_fx + 1, hBWE_TD->prev_lsf_diff_fx, LPC_SHB_ORDER - 2 ); + hBWE_TD->prev_tilt_para_fx = tilt_para_fx; + move16(); + + shb_ener_sf_Q31 = 0; + move16(); + test(); + IF( GE_32( st_fx->extl_brate, SWB_TBE_2k8 ) ) + { + /* ---------- SHB LSP interpolation ---------- */ + ptr_lsp_interp_coef_fx = interpol_frac_shb; /* Q15 */ + FOR( j = 0; j < 4; j++ ) + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + /*lsp_temp_fx[i] = lsp_shb_1_fx[i]*(*ptr_lsp_interp_coef_fx) */ + /* + lsp_shb_2_fx[i]*(*(ptr_lsp_interp_coef_fx+1)); */ + L_tmp = L_mult( lsp_shb_1_fx[i], ( *ptr_lsp_interp_coef_fx ) ); + lsp_temp_fx[i] = mac_r( L_tmp, lsp_shb_2_fx[i], ( *( ptr_lsp_interp_coef_fx + 1 ) ) ); + move16(); + } + ptr_lsp_interp_coef_fx += 2; + + tmp = i_mult2( j, ( LPC_SHB_ORDER + 1 ) ); + /* convert LSPs to LPC coefficients for SHB synthesis*/ + E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER ); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf_fx + tmp, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_sf_fx[tmp] ), 2 ) ); + } + + /* -------- Calculate the SHB Energy -------- */ + /*shb_ener_sf[0] = 0.003125f * sum2_f( shb_frame + L_SHB_LAHEAD, 320 );*/ + FOR( i = L_SHB_LAHEAD; i < L_FRAME16k + L_SHB_LAHEAD; i++ ) + { + /* shbEner = shbEner + in[i] * in[i] */ +#ifdef BASOP_NOGLOB + shb_ener_sf_Q31 = L_mac0_sat( shb_ener_sf_Q31, shb_frame_fx[i], shb_frame_fx[i] ); +#else + shb_ener_sf_Q31 = L_mac0( shb_ener_sf_Q31, shb_frame_fx[i], shb_frame_fx[i] ); +#endif + /* o: shb_ener_sf_Q31 in (2*Q_shb) */ + } + shb_ener_sf_Q31 = Mult_32_16( shb_ener_sf_Q31, 102 /*0.003125f Q15*/ ); + shb_ener_sf_Q31 = L_add( 1l /*1 Q0*/, shb_ener_sf_Q31 ); + Quant_shb_ener_sf_ivas_fx( st_fx, &shb_ener_sf_Q31, shl( Q_shb, 1 ) ); + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + set16_fx( shb_res_fx, 0, L_FRAME16k ); + Residu3_10_fx( lpc_shb_sf_fx, shb_frame_fx + L_SHB_LAHEAD, shb_res_fx, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 80, shb_res_fx + 80, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 2 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 160, shb_res_fx + 160, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 3 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 240, shb_res_fx + 240, 80, 0 ); + /* i: shb_frame_fx in Q_shb */ + /* o: shb_res_fx in Q_shb */ + + set32_fx( shb_res_gshape_fx_32, 0, NB_SUBFR16k ); + FOR( i = 0; i < NB_SUBFR16k; i++ ) + { + shb_res_gshape_fx_32[i] = sum2_fx( shb_res_fx + i_mult( i, 64 ), 64 ); + move32(); + } + /* o: shb_res_gshape_fx_32 in (2*Q_shb+1) */ + + maximum_32_fx( shb_res_gshape_fx_32, NB_SUBFR16k, &L_tmp ); + + /* root_a_over_b_fx(shb_res_gshape_fx_32[i], (2*Q_shb+1), L_tmp, (2*Q_shb+1), &exp);*/ + /* First, find 1/L_tmp, L_tmp in QA = (2*Q_shb+1) */ + + /* case when den = 0 */ + recip = 0; /*instead of 32767 to be compatible with previous root_a_over_b_fx() output */ + move16(); + Q_recip = 0; + move16(); + + IF( L_tmp ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + recip = div_s( 16384, tmp ); + Q_recip = sub( 31, sub( exp, 14 ) ); /* = 31-(exp+2*Q_shb+1-14), but adjusted by (2*Q_shb+1) for use at Mult_32_16 below */ + } + + FOR( i = 0; i < NB_SUBFR16k; i++ ) + { + L_tmp1 = Mult_32_16( shb_res_gshape_fx_32[i], recip ); /*Q = Q_recip+1-16*/ + L_tmp = root_a_fx( L_tmp1, sub( Q_recip, 15 ), &exp ); + shb_res_gshape_fx[i] = round_fx( L_shl( L_tmp, sub( exp, 1 ) ) ); /* Q14 */ + move16(); + } + + Quant_shb_res_gshape_ivas_fx( st_fx, shb_res_gshape_fx ); + } + ELSE IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + FOR( j = 0; j < 4; j++ ) + { + tmp = i_mult2( j, ( LPC_SHB_ORDER + 1 ) ); + /* convert LSPs to LPC coefficients for SHB synthesis*/ + E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER ); + /* Bring the LPCs to Q12 */ + Copy_Scale_sig( lpc_shb_sf_fx + tmp, lpc_shb_sf_fx + tmp, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_sf_fx[tmp] ), 2 ) ); + } + + /* -------- calculate the residuals using the FOUR subframe LPCs -------- */ + set16_fx( shb_res_fx, 0, L_FRAME16k ); + Residu3_10_fx( lpc_shb_sf_fx, shb_frame_fx + L_SHB_LAHEAD, shb_res_fx, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 80, shb_res_fx + 80, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 2 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 160, shb_res_fx + 160, 80, 0 ); + Residu3_10_fx( lpc_shb_sf_fx + 3 * ( LPC_SHB_ORDER + 1 ), shb_frame_fx + L_SHB_LAHEAD + 240, shb_res_fx + 240, 80, 0 ); + } + + Copy( lsp_shb_2_fx, hBWE_TD->swb_lsp_prev_interp_fx, LPC_SHB_ORDER ); /* lsp_shb_2_fx in Q15 */ + /* for 13.2 and 16.4kbps */ + E_LPC_f_lsp_a_conversion( lsp_temp_fx, lpc_shb_fx, LPC_SHB_ORDER ); + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); /* Q12 */ + + /* Determine formant PF strength */ + formant_fac_fx = swb_formant_fac_fx( lpc_shb_fx[1], &hBWE_TD->tilt_mem_fx ); + /* i:lpc_shb_fx Q12, o:formant_fac_fx Q15 */ + + /* calculate SHB auto-correlation function and convert to SHB voicing factor */ + // acorr_v2a = 0.0f; + L_tmp = 0; + move32(); + acorr_v2a_fx = 0; + move16(); + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* calculate the TD envelope of the SHB residual signal */ + find_td_envelope_fx( shb_res_fx, L_FRAME16k, 20, hBWE_TD->mem_shb_res_fx, EnvSHBres_fx ); /* Q_shb */ + + /* downsample the TD envelope by 4 */ + FOR( k = 0; k < L_FRAME4k; k++ ) + { + EnvSHBres_4k_fx[k] = EnvSHBres_fx[4 * k]; /* Q_shb */ + } + + /* calculate long-term mean envelope over four consecutive segments using linear interpolation */ + seg_len = L_FRAME4k / 4; + move16(); + den_seg_len = 1638; /* Q15 */ + move16(); + seg_len_2 = L_FRAME4k / 8; + move16(); + den_seg_len_2 = 3641; /* Q15 */ + move16(); + FOR( k = 0; k < 4; k++ ) + { + // seg_mean[k] = max(1.0f, mean(&EnvSHBres_4k[k * seg_len], seg_len)); + seg_mean[k] = s_max( 1, mean_no_sat_fx( &EnvSHBres_4k_fx[k * seg_len], seg_len ) ); /* Q_shb */ + move16(); + // den_seg_mean[k] = 1.0f / seg_mean[k]; + tmp = BASOP_Util_Divide1616_Scale( MAX16B, seg_mean[k], &tmp_e ); + tmp_e = sub( tmp_e, sub( 15, Q_shb ) ); + den_seg_mean[k] = shl_sat( tmp, tmp_e ); /* Q15 */ + move16(); + } + + /* first half of the first segment */ + IF( hBWE_TD->old_mean_EnvSHBres_fx == 0 ) + { + set16_fx( env_mean_normf_fx, den_seg_mean[0], seg_len_2 ); + } + ELSE + { + env_mean_normf_fx[0] = hBWE_TD->old_mean_EnvSHBres_fx; /* Q15 */ + move16(); + // step = (den_seg_mean[0] - hBWE_TD->old_mean_EnvSHBres) * den_seg_len_2; + step = mult( sub( den_seg_mean[0], hBWE_TD->old_mean_EnvSHBres_fx ), den_seg_len_2 ); /* Q15 */ + FOR( i = 1; i < seg_len_2; i++ ) + { + env_mean_normf_fx[i] = add_sat( env_mean_normf_fx[i - 1], step ); /* Q15 */ + move16(); + } + } + + /* segments 1-4 */ + p_env = &env_mean_normf_fx[seg_len_2]; + FOR( k = 1; k < 4; k++ ) + { + // step = ( den_seg_mean[k] - den_seg_mean[k - 1] ) * den_seg_len; + step = mult( den_seg_mean[k] - den_seg_mean[k - 1], den_seg_len ); + FOR( i = 0; i < seg_len; i++ ) + { + *p_env = add_sat( *( p_env - 1 ), step ); + move16(); + p_env++; + } + } + + /* last half of the last segment */ + // set_f( p_env, den_seg_mean[3], seg_len_2 ); + set16_fx( p_env, den_seg_mean[3], seg_len_2 ); + hBWE_TD->old_mean_EnvSHBres_fx = den_seg_mean[3]; + move16(); + + /* normalize residual SHB envelope with its long-term mean envelope */ + FOR( k = 0; k < L_FRAME4k; k++ ) + { + EnvSHBres_4k_norm_fx[k] = mult( EnvSHBres_4k_fx[k], env_mean_normf_fx[k] ); + move16(); + } + + /* calculate tilt of the long-term mean envelope */ + lls_interp_n_fx( seg_mean, 4, &shb_env_tilt_fx, &temp, 0 ); + + /* copy previous residual envelope to the buffer */ + Copy( hBWE_TD->old_EnvSHBres_fx, buf_EnvSHBres_fx, L_FRAME4k ); // Qs to be handled + + /* subtract mean value from the normalized SHB residual envelope */ + p_buf = &buf_EnvSHBres_fx[L_FRAME4k]; + temp = mean_no_sat_fx( EnvSHBres_4k_norm_fx, L_FRAME4k ); + FOR( k = 0; k < L_FRAME4k; k++ ) + { + *p_buf++ = sub( EnvSHBres_4k_norm_fx[k], temp ); + move16(); + } + + /* update memory */ + Copy( &buf_EnvSHBres_fx[L_FRAME4k], hBWE_TD->old_EnvSHBres_fx, L_FRAME4k ); // Qs to be handled + + /* calculate energy normalization factor for the auto-correlation function */ + // pow0 = sum2_f( &buf_EnvSHBres[L_FRAME4k], L_FRAME4k ) + 1.0f; + pow_e = sub( 15, Q_shb ); + pow0_fx = sum2_16_exp_fx( &buf_EnvSHBres_fx[L_FRAME4k], L_FRAME4k, &pow_e, 0 /* Give guard bits */ ) + 1; + // if (hBWE_TD->prev_enr_EnvSHBres == 1.0f) + IF( BASOP_Util_Cmp_Mant32Exp( hBWE_TD->prev_enr_EnvSHBres_fx, hBWE_TD->prev_enr_EnvSHBres_e, 1, 31 ) == 0 ) + { + // scale = 1.0f / pow0; + scale_fx = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, pow0_fx, &tmp_e ); + scale_e = sub( tmp_e, pow_e ); + } + ELSE + { + // scale = 1.0f / max( pow0, hBWE_TD->prev_enr_EnvSHBres ); + L_tmp1 = pow0_fx; + move32(); + IF( BASOP_Util_Cmp_Mant32Exp( L_tmp1, pow_e, hBWE_TD->prev_enr_EnvSHBres_fx, hBWE_TD->prev_enr_EnvSHBres_e ) < 0 ) + { + L_tmp1 = hBWE_TD->prev_enr_EnvSHBres_fx; + move32(); + pow_e = hBWE_TD->prev_enr_EnvSHBres_e; + move16(); + } + scale_fx = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, L_tmp1, &tmp_e ); // Qs to be handled + scale_e = sub( tmp_e, pow_e ); + } + hBWE_TD->prev_enr_EnvSHBres_fx = pow0_fx; + move32(); + hBWE_TD->prev_enr_EnvSHBres_e = pow_e; + move16(); + + /* calculate normalized auto-correlation function on the residual normalized SHB envelope */ + p_acorr = acorr_EnvSHBres; + p_buf = &buf_EnvSHBres_fx[L_FRAME4k - ENVSHBRES_ACORR_MIN]; + + FOR( k = 0; k < ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN; k++ ) + { + //*p_acorr++ = scale * dotp(&buf_EnvSHBres[L_FRAME4k], p_buf--, L_FRAME4k); + Word64 W_tmp = 0; + move64(); + + // tmp = *p_buf; + FOR( i = 0; i < L_FRAME4k; ++i ) + { + L_tmp = L_mult( buf_EnvSHBres_fx[L_FRAME4k + i], p_buf[i] ); // 2 * Q_shb + 1 + W_tmp = W_add( W_tmp, W_deposit32_l( L_tmp ) ); + } + p_buf--; + tmp_e = W_norm( W_tmp ); + L_tmp1 = W_extract_h( W_shl( W_tmp, tmp_e ) ); // 2 * Q_shb + tmp_e - 31 + L_tmp = Mpy_32_16_1( L_tmp1, scale_fx ); /* 2 * Q_shb + tmp_e - 31 - scale_e */ + //*p_acorr++ = extract_h( L_shl( L_tmp, add( 16, Q_shb ) - ( 2 * Q_shb + tmp_e - 31 - scale_e ) ) ); + *p_acorr++ = extract_h( L_shl( L_tmp, sub( add( 16, Q_shb ), sub( sub( add( shl( Q_shb, 1 ), tmp_e ), 31 ), scale_e ) ) ) ); + move16(); + } + + /* calculate variance of the SHB autocorrelation function */ + // acorr_v2a = sum2_f( acorr_EnvSHBres, ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN ) / ( ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN ); + tmp_e = sub( 15, Q_shb ); + L_tmp = Mpy_32_32( sum2_16_exp_fx( acorr_EnvSHBres, ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN, &tmp_e, 0 ), 53687091 /* 1 / ( ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN ) in Q31 */ ); + + /* multiply with the maximum of the SHB autocorrelation function */ + maximum_fx( acorr_EnvSHBres, ENVSHBRES_ACORR_MAX - ENVSHBRES_ACORR_MIN, &temp ); + // acorr_v2a *= temp; + L_tmp = Mpy_32_16_1( L_tmp, temp ); /* 31 - tmp_e + Q_shb - 15 */ + + // alpha = 25.0f; + alpha_fx = -1677721600; // Q26 + move32(); + + // acorr_v2a = 2.0f / ( 1.0f + (float) expf( -alpha * acorr_v2a ) ) - 1.0f; + Word32 exp_tmp = 1459366444; + Word16 exp_e = 2; + Word16 res_e = 0; + move32(); + move16(); + move16(); + + L_tmp = Mpy_32_32( alpha_fx, L_tmp ); // 31 - tmp_e + Q_shb - 15 - 5 + + tmp_e = sub( 31, sub( sub( add( sub( 31, tmp_e ), Q_shb ), 15 ), 5 ) ); + + // L_tmp = BASOP_Util_fPow(exp_tmp, exp_e, 2, 31, &res_e); + + L_tmp = BASOP_Util_fPow( exp_tmp, exp_e, L_tmp, tmp_e, &res_e ); + L_tmp = BASOP_Util_Add_Mant32Exp( ONE_IN_Q31, 0, L_tmp, res_e, &tmp_e ); + acorr_v2a_fx = BASOP_Util_Divide3232_Scale( 2, L_tmp, &res_e ); + + res_e = sub( add( res_e, 31 ), tmp_e ); + + acorr_v2a_fx = sub( acorr_v2a_fx, shl( 1, sub( 15, res_e ) ) ); + + /* limit in the range 0.0 - 1.0 */ + // acorr_v2a = min( 1.0f, max( 0.0f, acorr_v2a ) ); + acorr_v2a_fx = shl_sat( acorr_v2a_fx, res_e ); + + if ( acorr_v2a_fx < 0 ) + { + acorr_v2a_fx = 0; + move16(); + } + + hBWE_TD->prev_shb_env_tilt_fx = shb_env_tilt_fx; + move16(); + hBWE_TD->prev_shb_env_tilt_q = Q_shb; + move16(); + } + + /* Calculate the 6 to 14 kHz (or 7.5 - 15.5 kHz) SHB excitation signal from the ACELP core excitation */ + vf_ind_fx = 20; + move16(); + + /* Save the SWB LSP values from current frame for interpolation */ + + /* -------- start of memory rescaling -------- */ + /* ----- calculate optimum Q_bwe_exc and rescale memories accordingly ----- */ + Lmax = L_deposit_l( 0 ); + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[cnt] ) ); + } + Q_bwe_exc = norm_l( Lmax ); + if ( Lmax == 0 ) + { + Q_bwe_exc = 31; + move16(); + } + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + /* Account for any outliers in the memories from previous frame for rescaling to avoid saturation */ + find_max_mem_enc( st_fx, &n_mem, &n_mem2 ); + + tmp2 = add( st_fx->prev_Q_bwe_exc, n_mem ); + if ( GT_16( Q_bwe_exc, tmp2 ) ) + { + Q_bwe_exc = tmp2; + move16(); + } + + /* rescale the memories if Q_bwe_exc is different from previous frame */ + sc = sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ); + IF( sc != 0 ) + { + rescale_genSHB_mem_enc( st_fx, sc ); + } + + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + /* rescale the bwe_exc_extended and bring it to 16-bit single precision with dynamic norm */ + FOR( cnt = 0; cnt < L_FRAME32k; cnt++ ) + { +#ifdef BASOP_NOGLOB + bwe_exc_extended_16[cnt] = round_fx_sat( L_shl_sat( bwe_exc_extended[cnt], sc ) ); +#else + bwe_exc_extended_16[cnt] = round_fx( L_shl( bwe_exc_extended[cnt], sc ) ); +#endif + move16(); + } + + /* state_syn_shbexc_fx is kept at (st_fx->prev_Q_bwe_syn) for 24.4/32kbps or is kept at Q_bwe_exc for 13.2/16.4kbps */ + Copy( hBWE_TD->state_syn_shbexc_fx, shaped_shb_excitation_fx, L_SHB_LAHEAD ); + + /* save the previous Q factor of the buffer */ + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + Q_bwe_exc = sub( Q_bwe_exc, 16 ); /* Q_bwe_exc reflecting the single precision dynamic norm-ed buffers from here */ + + /* -------- end of rescaling memories -------- */ + Q_bwe_exc_fb = hBWE_TD->prev_Q_bwe_exc_fb; + move16(); + + // Replace with IVAS equivalent + GenShapedSHBExcitation_ivas_fx( shaped_shb_excitation_fx + L_SHB_LAHEAD, lpc_shb_fx, White_exc16k_fx, + hBWE_TD->mem_csfilt_fx, hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->state_lpc_syn_fx, + st_fx->coder_type, bwe_exc_extended_16, hBWE_TD->bwe_seed, vf_modified_fx, st_fx->extl, + &( hBWE_TD->tbe_demph_fx ), &( hBWE_TD->tbe_premph_fx ), lpc_shb_sf_fx, shb_ener_sf_Q31, + shb_res_gshape_fx, shb_res_fx, &vf_ind_fx, formant_fac_fx, hBWE_TD->fb_state_lpc_syn_fx, + &( hBWE_TD->fb_tbe_demph_fx ), &Q_bwe_exc, &Q_bwe_exc_fb, Q_shb, n_mem2, st_fx->prev_Q_bwe_syn, st_fx->total_brate, 0, st_fx->element_mode, st_fx->flag_ACELP16k, nlExc16k_fx, mixExc16k_fx, st_fx->extl_brate, MSFlag, + EnvSHBres_4k_norm_fx, &( hBWE_TD->prev_pow_exc16kWhtnd_fx32 ), &( hBWE_TD->prev_mix_factor_fx ), &Env_error_fx, Env_error_part_fx ); + + *Q_white_exc = Q_bwe_exc_fb; + move16(); + IF( EQ_16( st_fx->extl, FB_TBE ) ) + { + hBWE_TD->prev_Q_bwe_exc_fb = Q_bwe_exc_fb; + move16(); + } + ELSE + { + /*Indirectly a memory reset of FB memories for next frame such that rescaling of memories would lead to 0 due to such high prev. Q value. + 51 because of 31 + 20(shift of Q_bwe_exc_fb before de-emphasis)*/ + hBWE_TD->prev_Q_bwe_exc_fb = 51; + move16(); + } + + /* fill-in missing SHB excitation */ + test(); + test(); + IF( ( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) || EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) && LE_32( st_fx->last_core_brate, SID_2k40 ) ) + { + Copy( shaped_shb_excitation_fx + L_SHB_LAHEAD, shaped_shb_excitation_fx, L_SHB_LAHEAD ); + } + + test(); + IF( GE_16( st_fx->element_mode, IVAS_CPE_DFT ) && hStereoICBWE != NULL ) + { + Copy( shaped_shb_excitation_fx + L_SHB_LAHEAD, hStereoICBWE->shbSynthRef_fx, L_FRAME16k ); + } + + test(); + test(); + IF( GE_32( st_fx->extl_brate, SWB_TBE_2k8 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->idx_mixFac = vf_ind_fx; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_VF, vf_ind_fx, NUM_BITS_SHB_VF ); + } + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + hBWE_TD->mem_stp_swb_fx[i] = shl( hBWE_TD->mem_stp_swb_fx[i], sub( Q_bwe_exc, st_fx->prev_Q_bwe_syn ) ); + move16(); + } + + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + + FOR( i = 0; i < L_FRAME16k; i += L_SUBFR16k ) + { + PostShortTerm_fx( &shaped_shb_excitation_fx[L_SHB_LAHEAD + i], lpc_shb_fx, &shaped_shb_excitationTemp_fx[i], hBWE_TD->mem_stp_swb_fx, + hBWE_TD->ptr_mem_stp_swb_fx, &( hBWE_TD->gain_prec_swb_fx ), hBWE_TD->mem_zero_swb_fx, formant_fac_fx ); + /* i: shaped_shb_excitation_fx in Q_bwe_exc */ + /* i: lpc_shb_fx in Q12 */ + } + Copy( shaped_shb_excitationTemp_fx, &shaped_shb_excitation_fx[L_SHB_LAHEAD], L_FRAME16k ); + + + tmp = sub( shl( Q_bwe_exc, 1 ), 31 ); + prev_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ + curr_pow_fx = L_shl( 21475l /*0.00001f Q31*/, tmp ); /* 2*(Q_bwe_exc) */ + FOR( i = 0; i < L_SHB_LAHEAD + 10; i++ ) + { +#ifdef BASOP_NOGLOB + prev_pow_fx = L_mac0_o( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i], &Overflow ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0_o( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], &Overflow ); /* 2*Q_bwe_exc */ +#else + prev_pow_fx = L_mac0( prev_pow_fx, shaped_shb_excitation_fx[i], shaped_shb_excitation_fx[i] ); /* 2*Q_bwe_exc */ + curr_pow_fx = L_mac0( curr_pow_fx, shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10], shaped_shb_excitation_fx[i + L_SHB_LAHEAD + 10] ); /* 2*Q_bwe_exc */ +#endif + } + + if ( GT_16( voice_factors_fx[0], 24576 /*0.75f Q15*/ ) ) + { + /*curr_pow_fx = Mult_32_16( curr_pow_fx, 8192);*/ /* Q(2*Q_bwe_exc) */ + curr_pow_fx = L_shr( curr_pow_fx, 2 ); /* scale by 0.25 */ + } + + Lscale = root_a_over_b_fx( curr_pow_fx, + shl( Q_bwe_exc, 1 ), + prev_pow_fx, + shl( Q_bwe_exc, 1 ), + &exp ); + FOR( i = 0; i < L_SHB_LAHEAD; i++ ) + { + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q(16-exp+Q_bwe_exc) */ + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ + move16(); + } + IF( exp < 0 ) + { + Lscale = L_shl( Lscale, exp ); + exp = 0; + move16(); + } + FOR( ; i < L_SHB_LAHEAD + 10; i++ ) + { +#ifdef BASOP_NOGLOB + tmp = i_mult_o( sub( i, 19 ), 3277 /*0.1f Q15*/, &Overflow ); /* Q15 */ + L_tmp1 = Mult_32_16( L_shl_o( 1, sub( 31, exp ), &Overflow ), tmp ); /* Q31-exp */ +#else + tmp = i_mult( sub( i, 19 ), 3277 /*0.1f Q15*/ ); /* Q15 */ + L_tmp1 = Mult_32_16( L_shl( 1, sub( 31, exp ) ), tmp ); /* Q31-exp */ +#endif + tmp = sub( 32767 /*1.0f Q15*/, tmp ); + Lscale = L_add( Mult_32_16( Lscale, tmp ), L_tmp1 ); + L_tmp = Mult_32_16( Lscale, shaped_shb_excitation_fx[i] ); /* Q_bwe_exc + (31-exp) - 15 */ +#ifdef BASOP_NOGLOB + shaped_shb_excitation_fx[i] = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /* Q_bwe_exc */ +#else + shaped_shb_excitation_fx[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc */ +#endif + move16(); + } + } + ELSE + { + /* reset the PF memories if the PF is not running */ + set16_fx( hBWE_TD->mem_stp_swb_fx, 0, LPC_SHB_ORDER ); + hBWE_TD->gain_prec_swb_fx = ONE_IN_Q14; + move16(); + set16_fx( hBWE_TD->mem_zero_swb_fx, 0, LPC_SHB_ORDER ); + } + + /* Update SHB excitation */ + Copy( shaped_shb_excitation_fx + L_FRAME16k, hBWE_TD->state_syn_shbexc_fx, L_SHB_LAHEAD ); /* Q_bwe_exc */ + + /* Estimate the gain-shape parameter */ + n_subfr_saturation = 0; + move16(); + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, + Q_bwe_exc, GainShape_fx, subwin_shb_fx, &n_subfr_saturation ); + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* Gain shape attenuation in case of big error in envelope modelling */ + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + IF( GT_16( Env_error_part_fx[i], 100 ) ) + { + /* set gain shape to the average of the remaining gains */ + // GainShape[i] = ( sum_f( GainShape, NUM_SHB_SUBGAINS ) - GainShape[i] ) / ( NUM_SHB_SUBGAINS - 1 ); + L_tmp = L_sub( sum16_32_fx( GainShape_fx, NUM_SHB_SUBGAINS ), GainShape_fx[i] ); + tmp = BASOP_Util_Divide3232_Scale( L_tmp, NUM_SHB_SUBGAINS - 1, &exp ); + GainShape_fx[i] = shl( tmp, sub( exp, 15 ) ); /* Q15 */ + move16(); + } + } + } + + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* Gain shape BWS/high band low energy fix */ + IF( LT_16( hBWE_TD->cldfbHBLT, 8192 /*1.0f Q13*/ ) ) /* cldfbHBLT in Q13 */ + { + /* There is not much HB past 10kHz; the temporal resolution is quite coarse, so reduce the dynamic range */ + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /* 0.35f +/- delta variation; delta = 0.1*(GS-0.35)*/ + /* GainShape[i] = 0.315f + 0.1f * GainShape[i]; */ + GainShape_fx[i] = mac_r( 676457349l /*0.315 Q31*/, 3277 /*0.1 Q15*/, GainShape_fx[i] ); + move16(); + } + } + } + + /* high-band gain control in case of BWS */ + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + IF( st_fx->bwidth_sw_cnt > 0 ) + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + // GainShape[i] *= ( (float) ( st->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD ); + tmp = i_mult( st_fx->bwidth_sw_cnt, ONE_BY_BWS_TRAN_PERIOD_Q15 ); + GainShape_fx[i] = mult( GainShape_fx[i], tmp ); + move16(); + } + } + } + + /* Gain frame adjustment factor */ + /* log( (GainShape[0]) / (st->prev_wb_GainShape) )*/ + test(); + IF( GainShape_fx[0] && hBWE_TD->prev_swb_GainShape_fx ) + { + exp = norm_s( hBWE_TD->prev_swb_GainShape_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), hBWE_TD->prev_swb_GainShape_fx ); + L_tmp = L_mult( GainShape_fx[0], tmp ); /*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); /*move16(); */ + exp1 = sub( exp, exp1 ); /*move16(); */ + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + L_feedback = L_mult0( temp_swb_fac, temp_swb_fac ); + + + FOR( i = 1; i < NUM_SHB_SUBGAINS; i++ ) + { + test(); + IF( GainShape_fx[i] && GainShape_fx[i - 1] ) + { + exp = norm_s( GainShape_fx[i - 1] ); + tmp = div_s( shl( 1, sub( 14, exp ) ), GainShape_fx[i - 1] ); + L_tmp = L_mult( GainShape_fx[i], tmp ); /* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_swb_fac = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_swb_fac = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_swb_fac, temp_swb_fac ); + } + + /* feedback = 0.4f / (1 + 0.5f * feedback) */ + L_tmp = L_add( L_shr( L_feedback, 1 ), L_shl( 1, 21 ) ); /* Q21 */ + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /*Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /*Q31 */ + feedback = round_fx( L_tmp ); /*Q15 */ + } + ELSE + { + feedback = 8738; + move16(); /*Q15 */ + } + + /* calculate tilt in all sub-frame gains */ + Copy( GainShape_fx, GainShape_Interp_fx, NUM_SHB_SUBGAINS ); + lls_interp_n_fx( GainShape_Interp_fx, NUM_SHB_SUBGAINS, &GainShape_tilt_fx, &temp, 1 ); + + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // if (acorr_v2a < 0.4f && vf_ind >= 5 && fabs(GainShape_tilt) < 0.2f && shb_env_tilt < 500.0f && hBWE_TD->prev_shb_env_tilt < 500.0f) + test(); + test(); + test(); + test(); + IF( LT_16( acorr_v2a_fx, 13107 ) /* 0.4f in Q15 */ && GE_16( vf_ind_fx, 5 ) && LT_16( abs_s( GainShape_tilt_fx ), 6554 /* 0.2f in Q15 */ ) && LT_32( L_deposit_l( shb_env_tilt_fx ), L_shl( 500, Q_shb ) ) && LT_32( L_deposit_l( hBWE_TD->prev_shb_env_tilt_fx ), L_shl( 500, hBWE_TD->prev_shb_env_tilt_q ) ) ) + { + /* stronger smoothing in case of unvoiced SHB residual signal with gaussian excitation */ + // feedback = lin_interp(acorr_v2a, 0.4f, 0.0f, 0.0f, 0.95f, 0); + feedback = lin_interp_ivas_fx( acorr_v2a_fx, 13107 /* 0.4f in Q15 */, 0, 0, 31130 /* 0.95f in Q15 */, 0 ); + // feedback = min( max( feedback, 0.0f ), 1.0f ); + feedback = s_min( s_max( feedback, 0 ), MAX16B ); + + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + // GainShape[i] = ( 1 - feedback ) * GainShape[i] + feedback * GainShape_Interp[i]; + GainShape_fx[i] = extract_h( L_add( L_mult( sub( MAX16B, feedback ), GainShape_fx[i] ), L_mult( feedback, GainShape_Interp_fx[i] ) ) ); + move16(); + } + } + } + ELSE + { + /* voicing in Q15 */ + L_tmp = L_mult( voicing[0], 8192 ); + L_tmp = L_mac( L_tmp, voicing[1], 8192 ); + L_tmp = L_mac( L_tmp, voicing[2], 8192 ); + tmp = sum1 = round_fx( L_tmp ); /* sum1 used again below - Q13 */ + tmp = add( tmp, 1 ); /* To ensure change is BE */ + + /* voice_factors_fx in Q15 */ + L_tmp = L_mult( voice_factors_fx[0], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[1], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[2], 8192 ); + L_tmp = L_mac( L_tmp, voice_factors_fx[3], 8192 ); + tmp1 = sum2 = round_fx( L_tmp ); /* sum2 used again below - Q13 */ + + + test(); + test(); + IF( EQ_16( frGainAttenuate, 1 ) || ( GT_16( tmp, 19661 /* 2.4f in Q13 */ ) && GT_16( tmp1, 6554 /* 0.8f in Q13 */ ) ) ) + + { + temp_swb_fac = hBWE_TD->prev_swb_GainShape_fx; + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + /*GainShape_fx[i] = (1 - feedback) * GainShape[i] + feedback * temp_swb_fac; */ + GainShape_fx[i] = round_fx( L_mac( L_mult( sub( 32767, feedback ), GainShape_fx[i] ), feedback, temp_swb_fac ) ); + temp_swb_fac = GainShape_fx[i]; + move16(); + } + } + } + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* Re-normalize gain shape before quantization */ + // sum_gain = sum2_f(GainShape, NUM_SHB_SUBGAINS); + sum_gain_fx = sum16_32_fx( GainShape_fx, NUM_SHB_SUBGAINS ); + IF( sum_gain_fx == 0 ) + { + normFact_fx = 0; + move16(); + } + ELSE + { + // normFact = (float) sqrt( 1.0f / sum_gain ); + tmp = Q16; + move16(); + normFact_fx = ISqrt32( sum_gain_fx, &tmp ); + } + + // v_multc( GainShape, normFact, GainShape, NUM_SHB_SUBGAINS ); + FOR( i = 0; i < NUM_SHB_SUBGAINS; ++i ) + { + GainShape_fx[i] = extract_h( L_shl( Mpy_32_16_1( normFact_fx, GainShape_fx[i] ), tmp ) ); /* Q15 */ + move16(); + } + } + + + hBWE_TD->prev_swb_GainShape_fx = GainShape_fx[3]; + move16(); + + /* Compute the power of gains away from the peak gain prior to quantization */ + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_in_fx = pow_off_pk_corrected_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + } + ELSE + { + p2m_in_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBGAINS, 1 ); + } + + /* Quantization of the gain shape parameter */ + QuantizeSHBsubgains_ivas_fx( st_fx, GainShape_fx, st_fx->extl ); + /* o: GainShape_fx in Q15 */ + + /* Compute the power of gains away from the peak gain after quantization */ + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_out_fx = pow_off_pk_corrected_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + } + ELSE + { + p2m_out_fx = pow_off_pk_fx( GainShape_fx, NUM_SHB_SUBFR, 4 ); + } + + /* Gain shape smoothing after quantization */ + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + GainShape_Interp_fx[i] = GainShape_fx[i * NUM_SHB_SUBGAINS]; + move16(); + } + + lls_interp_n_fx( GainShape_Interp_fx, NUM_SHB_SUBGAINS, &GainShape_tilt_fx, &temp, 1 ); + + // if ( vf_ind >= 6 && fabs( GainShape_tilt ) < 0.12f ) + test(); + IF( GE_16( vf_ind_fx, 6 ) && LT_16( abs_s( GainShape_tilt_fx ), 3932 /* 0.12f in Q15 */ ) ) + { + // feedback = 0.3f; + feedback = 9830; /* 0.3f in Q15 */ + move16(); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + // GainShape[i] = ( 1 - feedback ) * GainShape[i * NUM_SHB_SUBGAINS] + feedback * GainShape_Interp[i]; + GainShape_fx[i] = extract_h( L_add( L_mult( sub( MAX16B, feedback ), GainShape_fx[i * NUM_SHB_SUBGAINS] ), L_mult( feedback, GainShape_Interp_fx[i] ) ) ); // Q15 + move16(); + } + + FOR( i = NUM_SHB_SUBFR - 1; i > 0; i-- ) + { + GainShape_fx[i] = GainShape_fx[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; + move16(); + } + } + } + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN, shb_frame_fx, Q_shb, shaped_shb_excitation_fx, Q_bwe_exc, + GainShape_fx, &GainFrame_fx, window_shb_fx, subwin_shb_fx, n_subfr_saturation ); + + IF( EQ_16( st_fx->tec_tfa, 1 ) ) + { + tfaCalcEnv_fx( shb_frame_fx, st_fx->tfa_enr ); + } + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + IF( GT_32( p2m_out_fx, L_shl( p2m_in_fx, 1 ) ) ) + { + L_tmp = root_a_over_b_fx( p2m_in_fx, 28, p2m_out_fx, 29, &exp_out ); + GainFrame_fx = L_shl( Mult_32_32( GainFrame_fx, L_tmp ), exp_out ); /* Q18 */ + } + + // if ( st_fx->element_mode > EVS_MONO && st_fx->L_frame != st_fx->last_L_frame && hBWE_TD->prev_gainFr_SHB != 0 && ( st_fx->last_extl == SWB_TBE || st_fx->last_extl == FB_TBE ) && st_fx->coder_type == TRANSITION && st_fx->coder_type_raw != VOICED && st_fx->clas == VOICED_CLAS && st_fx->last_clas == VOICED_CLAS && ( 3.0f * voice_factors[0] < voice_factors[( st_fx->L_frame >> 6 ) - 1] ) ) + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( st_fx->element_mode > EVS_MONO && NE_16( st_fx->L_frame, st_fx->last_L_frame ) && hBWE_TD->prev_gainFr_SHB != 0 && ( EQ_16( st_fx->last_extl, SWB_TBE ) || EQ_16( st_fx->last_extl, FB_TBE ) ) && EQ_16( st_fx->coder_type, TRANSITION ) && NE_16( st_fx->coder_type_raw, VOICED ) && EQ_16( st_fx->clas, VOICED_CLAS ) && EQ_16( st_fx->last_clas, VOICED_CLAS ) && LT_16( mult( 24576 /* 3.0f in Q13 */, voice_factors_fx[0] ), shr( voice_factors_fx[( st_fx->L_frame >> 6 ) - 1], 2 ) ) ) + { + // float fac = GainFrame / hBWE_TD->prev_gainFr_SHB; + Word16 fac = BASOP_Util_Divide3232_Scale( GainFrame_fx, hBWE_TD->prev_gainFr_SHB_fx, &tmp_e ); + + // if ( fac > 4.0f ) + IF( BASOP_Util_Cmp_Mant32Exp( L_deposit_h( fac ), tmp_e, 1073741824, 3 ) > 0 ) + { + // GainFrame = 4.0f * GainFrame / fac; + GainFrame_fx = BASOP_Util_Divide3216_Scale( GainFrame_fx, fac, &tmp1_e ); + GainFrame_fx = L_shl( GainFrame_fx, add( tmp1_e, 2 ) ); /* Q18 */ + } + } + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // if ( acorr_v2a > 0.1f && Env_error > 5.0f ) + test(); + test(); + IF( GT_16( acorr_v2a_fx, 3277 /* 0.1f in Q15 */ ) && GT_16( Env_error_fx, 5 ) ) + { + /* attenuate frame gain in case of voiced SHB residual signal with gaussian excitation */ + // fact_atten = lin_interp( Env_error, 5.0f, 1.0f, 25.0f, 0.2f, 1 ); + fact_atten_fx = lin_interp_ivas_fx( Env_error_fx, 5, MAX16B, 25, 6554 /* 0.2f in Q15 */, 1 ); + // GainFrame *= fact_atten; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, fact_atten_fx ); + } + /* Frame gain attenuation in case of big error in envelope modelling */ + // else if ( Env_error > 100.0f || hBWE_TD->prev_Env_error > 100.0f ) + ELSE IF( GT_16( Env_error_fx, 100 ) || GT_16( hBWE_TD->prev_Env_error_fx, 100 ) ) + { + // if ( Env_error > 100.0f ) + IF( GT_16( Env_error_fx, 100 ) ) + { + // fact_atten = lin_interp( Env_error, 100.0f, 1.0f, 300.0f, 0.1f, 1 ); + fact_atten_fx = lin_interp_ivas_fx( Env_error_fx, 100, MAX16B, 300, 3277 /* 0.1f in Q15 */, 1 ); + } + ELSE + { + // fact_atten = lin_interp( hBWE_TD->prev_Env_error, 100.0f, 1.0f, 300.0f, 0.5f, 1 ); + fact_atten_fx = lin_interp_ivas_fx( hBWE_TD->prev_Env_error_fx, 100, MAX16B, 300, ONE_IN_Q14 /* 0.5f in Q15 */, 1 ); + } + // GainFrame *= fact_atten; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, fact_atten_fx ); + } + } + ELSE + { + test(); + IF( EQ_16( frGainSmoothEn, 1 ) && LT_32( hBWE_TD->prev_gainFr_SHB_fx, GainFrame_fx ) ) + { + GainFrame_fx = L_add( L_shr( hBWE_TD->prev_gainFr_SHB_fx, 1 ), L_shr( GainFrame_fx, 1 ) ); /* Q18 */ + } + } + + test(); + test(); + IF( EQ_16( frGainAttenuate, 1 ) && LE_16( MA_lsp_shb_spacing, 79 /*0.0024f Q15*/ ) ) + { + exp1 = norm_l( GainFrame_fx ); + frac = Log2_norm_lc( L_shl( GainFrame_fx, exp1 ) ); + exp = sub( 30, add( exp1, 21 ) ); + L_tmp = Mpy_32_16( exp, frac, 26214 ); /* Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + GainFrame_fx = Pow2( 30, frac ); + exp = sub( exp, 30 ); + GainFrame_fx = L_shl( GainFrame_fx, exp + 18 ); /* Q18 */ + } + ELSE IF( EQ_16( hBWE_TD->prev_frGainAtten, 1 ) && GT_32( Mult_32_16( GainFrame_fx, 10923 ), hBWE_TD->prev_gainFr_SHB_fx ) ) + { + /*GainFrame *= (0.8f + 0.5f*feedback); */ + tmp = add( 26214, mult_r( feedback, 16384 ) ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 */ + } + + hBWE_TD->prev_frGainAtten = frGainAttenuate; + move16(); + + hBWE_TD->prev_gainFr_SHB_fx = GainFrame_fx; + move16(); /* Q18 */ + + // if ( GainFrame > 153.0f && st_fx->element_mode >= IVAS_CPE_DFT && hStereoICBWE != NULL ) + test(); + test(); + if ( GT_32( GainFrame_fx, 40108032 /* 153.0f in Q18 */ ) && GE_16( st_fx->element_mode, IVAS_CPE_DFT ) && hStereoICBWE != NULL ) + { + hStereoICBWE->MSFlag = 1; + move16(); + } + + /* Gain attenuation when the SWB LSF quantization error is larger than a threshold */ + tmp = mult_r( 25600 /*400 Q6*/, sd_uq_q_fx ); /* Q6 * Q15 => Q6 */ + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // sd_uq_q = 1 - 0.7f * ( sd_uq_q * sd_uq_q ); + tmp1 = mult_r( 22938 /*0.7f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } + ELSE + { + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + tmp1 = mult_r( 6554 /*0.2f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } + ELSE + { + tmp1 = mult_r( 3277 /*0.1f Q15*/, tmp ); /* Q15, Q6 => Q6 */ + L_tmp = L_msu( 8192l /*1.0f Q13*/, tmp1, tmp ); /* Q13 */ + } + } + /* sd_uq_q = max(min(sd_uq_q, 1.0f), 0.5f); */ + L_tmp = L_min( L_tmp, 8192l /*1.0f Q13*/ ); + L_tmp = L_max( L_tmp, 4096l /*0.5f Q13*/ ); /* Q13 */ + /* keep the L_tmp; dont overwrite */ + + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* pitBufAvg = 0.0025f * sum_f(pitch_buf, 4); */ + /* pitch_buf: Q6 */ + pitBufAvg_fx = mult_r( pitch_buf[0], 1311 ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[1], 1311 ) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[2], 1311 ) ); + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[3], 1311 ) ); /* Q10 */ + + /* voicingBufAvg = (sum_f(voice_factors, 4)=sum2 > 0.6f) ? 0.333f : 0.1667f; */ + tmp2 = 5462 /*0.1667f Q15*/; + move16(); + if ( GT_16( sum2, 4915 /*0.6f Q13*/ ) ) + { + tmp2 = 10912 /*0.333f Q15*/; /* Q15 */ + move16(); + } + voicingBufAvg_fx = shl( mult( tmp2, sum1 ), 2 ); /* Q15 */ + + // if ( voicingBufAvg <= 0.0f && sd_uq_q * pitBufAvg != 0 ) + test(); + IF( voicingBufAvg_fx <= 0 && Mpy_32_16_1( L_tmp, pitBufAvg_fx ) != 0 ) + { + // voicingBufAvg = sd_uq_q * pitBufAvg / 1.001f; + tmp = BASOP_Util_Divide1616_Scale( pitBufAvg_fx, 16400, &tmp_e ); + tmp_e = sub( add( tmp_e, 5 ), 1 ); + L_tmp1 = Mpy_32_16_1( L_tmp, tmp ); + voicingBufAvg_fx = extract_h( L_tmp1 ); + } + // else if ( voicingBufAvg <= 0.0f ) + ELSE IF( voicingBufAvg_fx <= 0 ) + { + // voicingBufAvg = 1.0f; + voicingBufAvg_fx = MAX16B; + move16(); + } + } + + /* high-band gain control in case of BWS */ + test(); + IF( NE_32( st_fx->extl_brate, SWB_TBE_1k10 ) && NE_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + IF( st_fx->bwidth_sw_cnt > 0 ) + { + // GainFrame *= ( (float) ( st_fx->bwidth_sw_cnt ) / (float) BWS_TRAN_PERIOD ); + tmp = i_mult( st_fx->bwidth_sw_cnt, ONE_BY_BWS_TRAN_PERIOD_Q15 ); + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, tmp ); + } + } + + /* Controlled gain evolution in SWB for stronger voiced segments */ + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + // GainFrame *= sd_uq_q; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, extract_l( L_shl( L_tmp, 2 ) ) ); + } + ELSE + { + /* max(min((float)(sd_uq_q*pitBufAvg/voicingBufAvg), 1.0f), 0.6f) */ + /* sd_uq_q: Q13, pitBufAvg_fx: Q6, voicingBufAvg_fx: Q15 */ + /* 1/voicingBufAvg_fx */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), voicingBufAvg_fx ); /* (14-exp) */ + + /* sd_uq_q*pitBufAvg */ + L_tmp = Mult_32_16( L_tmp, pitBufAvg_fx ); /* Q13 * Q10 + 1 -16 => Q8 */ + L_tmp = Mult_32_16( L_tmp, tmp ); /* Q8 + (14 - exp) - 15 => Q7 - exp */ +#ifdef BASOP_NOGLOB + tmp = round_fx_o( L_shl_o( L_tmp, 31 - ( 7 - exp ), &Overflow ), &Overflow ); /* Q15 */ +#else + tmp = round_fx( L_shl( L_tmp, 31 - ( 7 - exp ) ) ); /* Q15 */ +#endif + } + tmp = s_min( tmp, 32767 /*1.0f Q15*/ ); + tmp = s_max( tmp, 19661 /*0.6f Q15*/ ); + GainFrame_fx = Mult_32_16( GainFrame_fx, tmp ); /* Q18 + Q15 + 1 - 16 : Q18 */ + } + + test(); + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + if ( EQ_16( st_fx->rf_mode, 1 ) ) + { + /* Compensate for energy increase mismatch due to memory-less synthesis */ + // GainFrame *= 0.85f; + GainFrame_fx = Mpy_32_16_1( GainFrame_fx, 27853 ); + } + } + ELSE + { + test(); + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) || EQ_16( st_fx->rf_mode, 1 ) ) + { + /* Compensate for energy increase mismatch due to memory-less synthesis*/ + GainFrame_fx = Mult_32_16( GainFrame_fx, 27853 /*0.85f Q15*/ ); /* Q18 */ + } + } + + /* Quantization of the frame gain parameter */ + IF( st_fx->rf_mode ) + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame_fx, st_fx->extl, 0, &hRF->RF_bwe_gainFr_ind, 0 ); + } + ELSE + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame_fx, st_fx->extl, 0, NULL, ( EQ_32( st_fx->extl_brate, SWB_TBE_1k10 ) || EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) ? 1 : 0 ); + } + + IF( hStereoICBWE != NULL ) + { + push_indice( hBstr, IND_STEREO_ICBWE_MSFLAG, hStereoICBWE->MSFlag, STEREO_ICBWE_MSFLAG_BITS ); + } + + /* Backup for the IC BWE parameters */ + test(); + IF( GE_16( st_fx->element_mode, IVAS_CPE_DFT ) && hStereoICBWE != NULL ) + { + // Check Qs + Copy_Scale_sig_16_32( lpc_shb_fx, hStereoICBWE->lpSHBRef_fx, LPC_SHB_ORDER + 1, 0 ); + } + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation */ + IF( EQ_32( st_fx->extl, FB_TBE ) ) + { + tmp = norm_l( GainFrame_fx ); + if ( GainFrame_fx == 0 ) + { + tmp = 31; + move16(); + } + L_tmp = L_shl( GainFrame_fx, tmp ); /* 18 + tmp */ + + tmp1 = 0; + move16(); + FOR( i = 0; i < L_FRAME16k; i++ ) + { + L_tmp1 = Mult_32_16( L_tmp, GainShape_fx[NUM_SHB_SUBFR * i / L_FRAME16k] ); /* Q : 18 + tmp +15 -15*/ + /*White_exc16k_fx[i] = round_fx( L_shl(Mult_32_16( L_tmp1, White_exc16k_fx[i]),(23 - tmp -*Q_white_exc)) );*/ + /*18 + tmp +*Q_white_exc -15 + 23 - tmp -*Q_white_exc -16 = 10*/ + White_exc16k_fx[i] = round_fx( Mult_32_16( L_tmp1, White_exc16k_fx[i] ) ); /* 18 + tmp +*Q_white_exc -15 -16 */ + move16(); + /*Lmax = L_max(Lmax,White_exc16k_fx[i]);*/ + tmp1 = s_max( tmp1, abs_s( White_exc16k_fx[i] ) ); + /*White_exc16k_fx[i] =32767;*/ + /*White_exc16k_fx[i] = shr(White_exc16k_fx[i],5);*/ + } + *Q_white_exc = sub( add( *Q_white_exc, tmp ), 13 ); /* *Q_white_exc + 18 + tmp -15 -16 */ + move16(); + tmp = norm_s( tmp1 ); + if ( tmp1 == 0 ) + { + tmp = 15; + move16(); + } + + FOR( i = 0; i < L_FRAME16k; i++ ) + { + White_exc16k_fx[i] = shl( White_exc16k_fx[i], sub( tmp, 1 ) ); + move16(); + } + *Q_white_exc = sub( add( *Q_white_exc, tmp ), 1 ); + move16(); + } + + hBWE_TD->prev_Env_error = Env_error_fx; + move16(); + + /* *Q_white_exc = Q_bwe_exc_mod; move16(); output Qwhiteexc_FB from the GenShapedSHB function*/ + st_fx->prev_Q_bwe_syn = Q_bwe_exc; + move16(); + + return; +} + + +/*==========================================================================*/ +/* FUNCTION : static void EstimateSHBFrameGain_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Estimate the overall gain factor needed to scale */ +/* synthesized highband to original highband signal level. */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) length : SHB overlap length Q0 */ +/* _(Word16*) oriSHB : target original SHB frame Q_oriSHB */ +/* _(Word16*) synSHB : shaped SHB excitation Q_synSHB */ +/* _(Word16*) win_shb : SHB window Q15 */ +/* _(Word16*) subwin_shb_local : SHB subframe window Q15 */ +/* _(Word16) Q_oriSHB : Q format of oriSHB */ +/* _(Word16) Q_synSHB : Q format of synSHB */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word32*)GainFrame :estimat of gain frame Q18 */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ + +static void EstimateSHBFrameGain_fx( + const Word16 length, /* i : SHB overlap length */ + const Word16 *oriSHB, /* i : target original SHB frame Q(Q_oriSHB) */ + const Word16 Q_oriSHB, /* i : Q of arget original SHB frame */ + const Word16 *synSHB, /* i : shaped SHB excitation Q(Q_synSHB) */ + const Word16 Q_synSHB, /* i : Q of shaped SHB excitation */ + Word16 *subgain, /* i : estimate of gain shape Q15 */ + Word32 *GainFrame, /* o : estimat of gain frame Q18 */ + const Word16 *win_shb, /* i : SHB window Q15 */ + const Word16 *subwin_shb_local, /* i : SHB subframe window Q15 */ + const Word16 n_subfr_saturation /* i : Number of subframes which saturated in GainShape oriNrg calculation */ +) +{ + const Word16 *skip; + Word16 i, j, k, l_shb_lahead, l_frame; + Word16 join_length, num_join, sig; + Word32 mod_syn[L_FRAME16k + L_SHB_LAHEAD]; + Word32 oriNrg, synNrg; + Word16 sum_gain; + Word32 frame_gain; + Word32 L_tmp; + Word16 exp_out; + Word16 tmp; + Word16 scaling = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + move16(); + + /* initilaization */ + l_frame = L_FRAME16k; + move16(); + l_shb_lahead = L_SHB_LAHEAD; + move16(); + skip = skip_bands_SWB_TBE; + + IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) + { + skip = skip_bands_WB_TBE; + l_frame = L_FRAME16k / 4; + move16(); + l_shb_lahead = L_SHB_LAHEAD / 4; + move16(); + } + + /* apply gain for each subframe, and store noise output signal using overlap-add*/ + set32_fx( mod_syn, 0, l_frame + l_shb_lahead ); + + IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) + { + sum_gain = 0; + move16(); + j = skip[0]; + move16(); + FOR( k = 0; k < length / 2; k++ ) + { + sum_gain = mult_r( subwin_shb_local[2 * k + 2], subgain[0] ); /* Q15 */ + mod_syn[j + k] = L_mult( synSHB[j + k], sum_gain ); + move32(); /* Q(16+Q_synSHB) */ + mod_syn[j + k + length / 2] = L_mult( synSHB[j + k + length / 2], subgain[0] ); + move32(); /* Q(16+Q_synSHB) */ + } + + FOR( i = 1; i < NUM_SHB_SUBFR / 2; i++ ) + { + j = skip[i]; + move16(); + FOR( k = 0; k < length; k++ ) + { + L_tmp = L_mult0( subwin_shb_local[k + 1], subgain[i] ); /* Q30 */ + sum_gain = round_fx( L_mac0( L_tmp, subwin_shb_local[length - k - 1], subgain[i - 1] ) ); /* Q14 */ + mod_syn[j + k] = L_shl( L_mult( sum_gain, synSHB[j + k] ), 1 ); + move32(); /* Q(16+Q_synSHB) */ + } + } + FOR( k = 0; k < length / 2; k++ ) + { + j = skip[i]; + move16(); + sum_gain = mult_r( subwin_shb_fx[length - 2 * k - 2], subgain[i - 1] ); /* Q15 */ + mod_syn[j + k] = L_mult( synSHB[j + k], sum_gain ); + move32(); /* Q(16+Q_synSHB) */ } } ELSE @@ -2824,10 +4435,10 @@ static void EstimateSHBFrameGain_fx( sig = round_fx_o( Mult_32_16( mod_syn[i], win_shb[i] ), &Overflow ); /*Q_synSHB */ synNrg = L_mac0_o( synNrg, sig, sig, &Overflow ); /* 2*Q_synSHB */ #else - sig = mult_r( oriSHB[i], win_shb[i] ); /* Q_oriSHB */ - oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_orisHB*/ - sig = round_fx( Mult_32_16( mod_syn[i], win_shb[i] ) ); /*Q_synSHB */ - synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_synSHB */ + sig = mult_r( oriSHB[i], win_shb[i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_orisHB*/ + sig = round_fx( Mult_32_16( mod_syn[i], win_shb[i] ) ); /*Q_synSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_synSHB */ #endif } @@ -2838,9 +4449,9 @@ static void EstimateSHBFrameGain_fx( sig = round_fx_o( mod_syn[i], &Overflow ); /* Q_oriSHB */ synNrg = L_mac0_o( synNrg, sig, sig, &Overflow ); /* 2*Q_oriSHB */ #else - oriNrg = L_mac0( oriNrg, oriSHB[i], oriSHB[i] ); /* 2*Q_oriSHB */ - sig = round_fx( mod_syn[i] ); /* Q_oriSHB */ - synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ + oriNrg = L_mac0( oriNrg, oriSHB[i], oriSHB[i] ); /* 2*Q_oriSHB */ + sig = round_fx( mod_syn[i] ); /* Q_oriSHB */ + synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ #endif } @@ -2854,8 +4465,8 @@ static void EstimateSHBFrameGain_fx( sig = round_fx_o( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ), &Overflow ); /* Q_oriSHB */ synNrg = L_mac0_o( synNrg, sig, sig, &Overflow ); /* 2*Q_oriSHB */ #else - sig = mult_r( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i] ); /* Q_oriSHB */ - oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB */ + sig = mult_r( oriSHB[i], win_shb[l_frame + l_shb_lahead - 1 - i] ); /* Q_oriSHB */ + oriNrg = L_mac0( oriNrg, sig, sig ); /* 2*Q_oriSHB */ sig = round_fx( Mult_32_16( mod_syn[i], win_shb[l_frame + l_shb_lahead - 1 - i] ) ); /* Q_oriSHB */ synNrg = L_mac0( synNrg, sig, sig ); /* 2*Q_oriSHB */ @@ -3729,23 +5340,108 @@ static void Quant_shb_ener_sf_fx( { push_indice_fx( st_fx->hBstr, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF ); } - return; + return; +} + + +/*-------------------------------------------------------------------* + * Quant_shb_ener_sf_ivas_fx() + * + * Quantize SHB subframe energies + *-------------------------------------------------------------------*/ + +static void Quant_shb_ener_sf_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word32 *shb_ener_sf_Q31, /* i/o: super highband subframe energies Q_ener */ + Word16 Q_ener ) +{ + Word16 idxSubEner_fx; + Word16 temp_shb_ener_sf_fx; + Word16 exp /*, exp2*/, frac; + Word32 L_tmp1, L_tmp; + Word32 sum; + Word16 tmp; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + /* shb_ener_sf_fx[0] = log10(0.003125*shb_ener_sf[0:319]); */ + sum = *shb_ener_sf_Q31; /* L_tmp in Q_ener = (2*Q_shb+1) */ + move32(); + + exp = norm_l( sum ); + frac = Log2_norm_lc( L_shl( sum, exp ) ); + exp = sub( 30, add( exp, Q_ener ) ); /* 30-(exp+Q_ener ) */ + L_tmp1 = Mpy_32_16( exp, frac, 617 ); /* 2466=LOG10(2) in Q11, so answer Ltmp in Q12 */ + + tmp = round_fx( L_shl( L_tmp1, 30 - 14 ) ); /* tmp in Q12 */ + + temp_shb_ener_sf_fx = 0; + move16(); + idxSubEner_fx = usquant_fx( tmp, &temp_shb_ener_sf_fx, 0, 86, shl( 1, NUM_BITS_SHB_ENER_SF ) ); /* 86 = 0.042f in Q11 = Qin-1 */ + /* o: temp_shb_ener_sf_fx in Q12 */ + + /* shb_ener_sf_fx[0] = pow(10.0, temp_shb_ener_sf_fx ); */ + /* = pow(2, 3.321928*temp_shb_ener_sf_fx) */ + L_tmp = L_mult( temp_shb_ener_sf_fx, 27213 ); /* 3.321928 in Q13 -> L_tmp in Q12+Q13+1 = Q26 */ + L_tmp = L_shl( L_tmp, -10 ); /* bring L_tmp from Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); /* Extract exponent */ + L_tmp = Pow2( 14, frac ); + *shb_ener_sf_Q31 = L_shl( L_tmp, add( sub( exp, 14 ), Q_ener ) ); /* In Q_ener */ + move32(); + + hBWE_TD->idx_shb_fr_gain = idxSubEner_fx; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 ) ) + { + push_indice( st_fx->hBstr, IND_SHB_ENER_SF, idxSubEner_fx, NUM_BITS_SHB_ENER_SF ); + } + return; +} + + +/*-------------------------------------------------------------------* + * Quant_shb_res_gshape_fx() + * + * Quantize SHB gain shapes in residual domain + *-------------------------------------------------------------------*/ + +static void Quant_shb_res_gshape_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 shb_res_gshape_fx[] /* i/o: super highband gain shapes Q14 */ +) +{ + Word16 i, idxSubGain_fx[NB_SUBFR16k]; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + + FOR( i = 0; i < NB_SUBFR16k; i++ ) + { + idxSubGain_fx[i] = usquant_fx( shb_res_gshape_fx[i], + &shb_res_gshape_fx[i], + 2048 /*0.125f Q14*/, /*2048 = 0.125 in Q14 */ + 1024 /*0.125f Q13*/, /*1024 = 0.125 in Q13 */ + shl( 1, NUM_BITS_SHB_RES_GS ) ); + + hBWE_TD->idx_res_gs[i] = idxSubGain_fx[i]; + IF( NE_16( st_fx->codec_mode, MODE2 ) ) + { + push_indice_fx( st_fx->hBstr, IND_SHB_RES_GS1 + i, idxSubGain_fx[i], NUM_BITS_SHB_RES_GS ); + } + } } /*-------------------------------------------------------------------* - * Quant_shb_res_gshape_fx() + * Quant_shb_res_gshape_ivas_fx() * * Quantize SHB gain shapes in residual domain *-------------------------------------------------------------------*/ -static void Quant_shb_res_gshape_fx( - Encoder_State *st_fx, /* i/o: encoder state structure */ - Word16 shb_res_gshape_fx[] /* i/o: super highband gain shapes Q14 */ +static void Quant_shb_res_gshape_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + Word16 shb_res_gshape_fx[] /* i/o: super highband gain shapes Q14 */ ) { Word16 i, idxSubGain_fx[NB_SUBFR16k]; - TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; FOR( i = 0; i < NB_SUBFR16k; i++ ) { @@ -3754,11 +5450,16 @@ static void Quant_shb_res_gshape_fx( 2048 /*0.125f Q14*/, /*2048 = 0.125 in Q14 */ 1024 /*0.125f Q13*/, /*1024 = 0.125 in Q13 */ shl( 1, NUM_BITS_SHB_RES_GS ) ); + move16(); - hBWE_TD->idx_res_gs[i] = idxSubGain_fx[i]; - IF( NE_16( st_fx->codec_mode, MODE2 ) ) + IF( st->codec_mode == MODE2 ) { - push_indice_fx( st_fx->hBstr, IND_SHB_RES_GS1 + i, idxSubGain_fx[i], NUM_BITS_SHB_RES_GS ); + hBWE_TD->idx_res_gs[i] = idxSubGain_fx[i]; + move16(); + } + ELSE + { + push_indice( st->hBstr, IND_SHB_RES_GS1 + i, idxSubGain_fx[i], NUM_BITS_SHB_RES_GS ); } } } @@ -4399,18 +6100,20 @@ static void return_M_Least_fx_GainFrame( /*-------------------------------------------------------------------* * Quant_lower_LSF_fx() *-------------------------------------------------------------------*/ + static void Quant_lower_LSF_fx( - const Word16 lsf[], /* i : Input LSFs Q15 */ - Word16 lsf_q[], /* o : Quantized LSFs Q15 */ - Word16 lsf_idx[] /* o : Quantized LSFs indices */ + const Word16 lsf[], /* i : Input LSFs Q15 */ + Word16 lsf_q[], /* o : Quantized LSFs Q15 */ + Word16 lsf_idx[] /* o : Quantized LSFs indices */ ) { Word16 i; - lsf_idx[0] = (Word16) squant_fx( lsf[0], &lsf_q[0], lsf_q_cb_fx[0], lsf_q_cb_size[0] ); + lsf_idx[0] = squant_fx( lsf[0], &lsf_q[0], lsf_q_cb_fx[0], lsf_q_cb_size[0] ); + move16(); FOR( i = 1; i < NUM_Q_LSF; i++ ) { - lsf_idx[i] = (Word16) squant_fx( sub( lsf[i], lsf_q[i - 1] ), &lsf_q[i], lsf_q_cb_fx[i], lsf_q_cb_size[i] ); + lsf_idx[i] = squant_fx( sub( lsf[i], lsf_q[i - 1] ), &lsf_q[i], lsf_q_cb_fx[i], lsf_q_cb_size[i] ); move16(); lsf_q[i] = add( lsf_q[i - 1], lsf_q[i] ); move16(); @@ -4423,19 +6126,19 @@ static void Quant_lower_LSF_fx( /*-------------------------------------------------------------------* * Quant_mirror_point_fx() *-------------------------------------------------------------------*/ + static Word16 Quant_mirror_point_fx( - const Word16 lsf[], /* i : Input LSFs */ - const Word16 lsf_q[], - Word16 *m /* o : Mirror point */ + const Word16 lsf[], /* i : Input LSFs Q15 */ + const Word16 lsf_q[], /* i : Quantized LSFs Q15 */ + Word16 *m /* o : Mirror point Q15 */ ) { Word16 m_diff; Word16 m_idx; - m_diff = mult_r( sub( lsf[NUM_Q_LSF], lsf_q[NUM_Q_LSF - 1] ), 16384 ); + m_diff = mult_r( sub( lsf[NUM_Q_LSF], lsf_q[NUM_Q_LSF - 1] ), 16384 /* 0.5f in Q15 */ ); - m_idx = (Word16) squant_fx( m_diff, m, mirror_point_q_cb_fx, - MIRROR_POINT_Q_CB_SIZE ); /*move16(); */ + m_idx = squant_fx( m_diff, m, mirror_point_q_cb_fx, MIRROR_POINT_Q_CB_SIZE ); *m = add( lsf_q[NUM_Q_LSF - 1], *m ); move16(); @@ -4443,6 +6146,7 @@ static Word16 Quant_mirror_point_fx( return m_idx; } + /*-------------------------------------------------------------------* * Find_LSF_grid() * @@ -4450,9 +6154,9 @@ static Word16 Quant_mirror_point_fx( *-------------------------------------------------------------------*/ static Word16 Find_LSF_grid_fx( - const Word16 lsf[], /* i : Input LSFs */ - Word16 lsf_q[], /* o : Quantized LSFs */ - const Word16 m /* i : Mirror point */ + const Word16 lsf[], /* i : Input LSFs Q15 */ + Word16 lsf_q[], /* o : Quantized LSFs Q15 */ + const Word16 m /* i : Mirror point Q15 */ ) { Word16 lsf_map[NUM_MAP_LSF]; @@ -4465,6 +6169,7 @@ static Word16 Find_LSF_grid_fx( Word16 I_best = 0; Word16 i, j; Word16 scale; + move16(); Word16 tmp, exp, tmp1; Word32 L_tmp; @@ -4670,6 +6375,390 @@ static void gainFrSmooth_En_fx( Encoder_State *st_fx, } } +#define MAXINT32 MAX_32 +static void first_VQstages_fx( + const Word16 *const *cb, + Word16 u[], /* i : vector to be encoded (prediction and mean removed) */ + Word16 *levels, /* i : number of levels in each stage */ + Word16 stagesVQ, /* i : number of stages */ + Word16 w[], /* i : weights */ + Word16 N, /* i : vector dimension */ + Word16 max_inner, /* i : maximum number of swaps in inner loop */ + Word16 indices_VQstage[] ) +{ + Word16 resid_buf[2 * LSFMBEST * M], *resid[2]; + Word32 dist_buf[2 * LSFMBEST], *dist[2], en; + Word32 f_tmp, L_tmp, L_tmp1, *pTmp32; + Word16 Tmp[M], *pTmp, cs; + Word16 *pTmp_short, idx_buf[2 * LSFMBEST * MAX_VQ_STAGES], parents[LSFMBEST], counter = 0, j, + m, s, c, c2, p_max, *indices[2]; + move16(); + Word16 maxC = LSFMBEST; + move16(); +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move16(); +#endif + + /*float dd[16];*/ + const Word16 *cb_stage, *cbp; + + /* Set pointers to previous (parent) and current node (parent node is indexed [0], current node is indexed [1]) */ + indices[0] = idx_buf; + move16(); + indices[1] = idx_buf + maxC * stagesVQ; + move16(); + resid[0] = resid_buf; + move16(); + resid[1] = resid_buf + maxC * N; + move16(); + dist[0] = dist_buf; + move16(); + dist[1] = dist_buf + maxC; + move16(); + + set16_fx( idx_buf, 0, ( const Word16 )( 2 * stagesVQ * maxC ) ); + set16_fx( parents, 0, maxC ); + + /* Set up inital distance vector */ + L_tmp = L_deposit_l( 0 ); + FOR( j = 0; j < N; j++ ) + { +#ifdef BASOP_NOGLOB + L_tmp1 = L_shl_o( L_mult0( u[j], w[j] ), 7, &Overflow ); /*x2.56 + Q8 + Q7 */ +#else /* BASOP_NOGLOB */ + L_tmp1 = L_shl( L_mult0( u[j], w[j] ), 7 ); /*x2.56 + Q8 + Q7 */ +#endif /* BASOP_NOGLOB */ + L_tmp1 = Mult_32_16( L_tmp1, u[j] ); /*x2.56 + Q15 + x2.56 -Q15 */ + L_tmp = L_add( L_tmp, L_tmp1 ); /*Q0 + x2.56 +x2.56 */ + } + set32_fx( dist[1], L_tmp, maxC ); + + /* Set up initial error (residual) vectors */ + pTmp = resid[1]; + move16(); + FOR( c = 0; c < maxC; c++ ) + { + Copy( u, pTmp, N ); + pTmp += N; + } + + /*----------------------------------------------------------------* + * LSF quantization + *----------------------------------------------------------------*/ + + /* Loop over all stages */ + m = 1; + move16(); + FOR( s = 0; s < stagesVQ; s++ ) + { + /* set codebook pointer to point to first stage */ + cbp = cb[s]; + + /* save pointer to the beginning of the current stage */ + cb_stage = cbp; + + /* swap pointers to parent and current nodes */ + pTmp_short = indices[0]; + indices[0] = indices[1]; + move16(); + indices[1] = pTmp_short; + move16(); + + pTmp = resid[0]; + resid[0] = resid[1]; + move16(); + resid[1] = pTmp; + move16(); + + pTmp32 = dist[0]; + dist[0] = dist[1]; + move32(); + dist[1] = pTmp32; + move32(); + + /* p_max points to maximum distortion node (worst of best) */ + p_max = 0; + move16(); + + /* set distortions to a large value */ + set32_fx( dist[1], MAXINT32, maxC ); + + FOR( j = 0; j < levels[s]; j++ ) + { + /* compute weighted codebook element and its energy */ + FOR( c2 = 0; c2 < N; c2++ ) + { + Tmp[c2] = shl( mult( w[c2], cbp[c2] ), 2 ); /* Q8 + x2.56 -Q15 +Q2 */ + move16(); + } + + en = L_mult( cbp[0], Tmp[0] ); + + FOR( c2 = 1; c2 < N; c2++ ) + { + en = L_mac( en, cbp[c2], Tmp[c2] ); /*x2.56 + x2.56 + Q-5 +Q1 */ + } + cbp += N; + move16(); + + /* iterate over all parent nodes */ + FOR( c = 0; c < m; c++ ) + { + pTmp = &resid[0][c * N]; + move16(); + L_tmp = L_mult( pTmp[0], Tmp[0] ); + FOR( c2 = 1; c2 < N; c2++ ) + { + L_tmp = L_mac( L_tmp, pTmp[c2], Tmp[c2] ); /* */ + } + + L_tmp = L_add( dist[0][c], L_sub( en, L_shl( L_tmp, 1 ) ) ); + + IF( LE_32( L_tmp, dist[1][p_max] ) ) + { + /* replace worst */ + dist[1][p_max] = L_tmp; + move32(); + indices[1][p_max * stagesVQ + s] = j; + move16(); + parents[p_max] = c; + move16(); + + /* limit number of times inner loop is entered */ + IF( LT_16( counter, max_inner ) ) + { + counter = add( counter, 1 ); + IF( LT_16( counter, max_inner ) ) + { + /* find new worst */ + p_max = maximum_32_fx( dist[1], maxC, &f_tmp ); + } + ELSE + { + /* find minimum distortion */ + p_max = minimum_32_fx( dist[1], maxC, &f_tmp ); + } + } + } + } + } + + /*------------------------------------------------------------* + * Compute error vectors for each node + *------------------------------------------------------------*/ + cs = 0; + move16(); + FOR( c = 0; c < maxC; c++ ) + { + /* subtract codebook entry from the residual vector of the parent node */ + pTmp = resid[1] + c * N; + move16(); + Copy( resid[0] + parents[c] * N, pTmp, N ); + Vr_subt( pTmp, cb_stage + ( indices[1][cs + s] ) * N, pTmp, N ); + + /* get indices that were used for parent node */ + Copy( indices[0] + parents[c] * stagesVQ, indices[1] + cs, s ); + cs = add( cs, stagesVQ ); + } + + m = maxC; + move16(); + } + + Copy( indices[1], indices_VQstage, maxC * stagesVQ ); + + return; +} + +static Word16 dotp_loc( + const Word16 x[], /* i : vector x[] */ + const Word32 y[], /* i : vector y[] */ + const Word16 n /* i : vector length */ +) +{ + Word16 i; + Word32 suma; + Word16 guarded_bits = find_guarded_bits_fx( n ); + suma = L_shr( Mpy_32_16_1( y[0], x[0] ), guarded_bits ); + + FOR( i = 1; i < n; i++ ) + { + suma = L_add( suma, L_shr( Mpy_32_16_1( y[i], x[i] ), guarded_bits ) ); + } + suma = L_shl_sat( suma, guarded_bits ); + + return extract_h( suma ); +} + +static void LVQQuant_BWE_LSF_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + const Word16 lsf_shb_fx[], /* i : unquanitzed LSFs Q15 */ + Word16 Q_lsfs_fx[], /* o : quanitzed LSFs Q15 */ + Word16 nbits ) +{ + + Word16 lsf_fx[LPC_SHB_ORDER]; + Word16 lsf_q_fx[LPC_SHB_ORDER]; + Word16 i, c2, dim1 = 6; + move16(); + Word16 levels[1], numbits_VQ; + Word16 c2_fx_temp; + + Word16 w_fx[8] = { 5120, 5120, 2048, 2048, 2048, 1024, 1024, 1024 }; /* Q10 */ + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + move16(); + Word16 cand_fx[LPC_SHB_ORDER], quant_fx[LPC_SHB_ORDER], e_fx[2], ftmp_fx; + const Word16 *cb_stage_fx; + Word16 indices_firstVQ[LSFMBEST]; + + Word16 Idx, idx_lead, idx_scale; + UWord32 LVQ_index; + Word16 dd_fx[LATTICE_DIM], cv_out_fx[LATTICE_DIM]; + Word16 bits_lvq, predictor_bits, empty_bits; + + empty_bits = 0; /* This is the difference to 21 bits, if we want lower number of bits */ + move16(); + nbits = sub( nbits, empty_bits ); /* THIS IS TO SIMULATE DIFFERENT NUMBER OF input BITS - should be removed */ + move16(); + c2 = sub( NUM_BITS_SHB_MSLVQ, nbits ); + move16(); + numbits_VQ = config_LSF_BWE[c2 * 3]; + move16(); + levels[0] = config_LSF_BWE[c2 * 3 + 1]; + move16(); + predictor_bits = config_LSF_BWE[c2 * 3 + 2]; + move16(); + IF( LT_16( nbits, 19 ) ) + { + cb_stage_fx = cb_LSF_BWE_fx[1]; + } + ELSE + { + cb_stage_fx = cb_LSF_BWE_fx[0]; + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsf_fx[i] = sub( 16384 /* 0.5f in Q15 */, lsf_shb_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + /* remove mean */ + v_sub_16( lsf_fx, SHB_LSF_mean_fx, Q_lsfs_fx, LPC_SHB_ORDER ); + + /* 6D multi-stage 6bit coding */ + first_VQstages_fx( &cb_stage_fx, Q_lsfs_fx, levels, 1, w_fx, dim1, 3000, indices_firstVQ ); + + + /* 8D MSLVQ coding */ + bits_lvq = sub( sub( nbits, numbits_VQ ), predictor_bits ); + Copy( SHB_LSF_mean_fx, cand_fx, LPC_SHB_ORDER ); + + Idx = indices_firstVQ[0]; + move16(); + + v_add_16( cand_fx, cb_stage_fx + Idx * dim1, cand_fx, dim1 ); + + /* LVQ quantization */ + Copy( cand_fx, quant_fx, LPC_SHB_ORDER ); + + v_sub_16( lsf_fx, cand_fx, dd_fx, LATTICE_DIM ); + + mslvq_ivas_16( dd_fx, quant_fx, cv_out_fx, &idx_lead, &idx_scale, w_fx, 0, ( nbits < 19 ), bits_lvq ); + + IF( EQ_16( idx_scale, -1 ) ) + { + set16_fx( cv_out_fx, 0, LATTICE_DIM ); + } + v_add_16( cand_fx, quant_fx, cand_fx, LATTICE_DIM ); + + /* arrange the LSF candidate vector prior to selection to an ascending order*/ + v_sort( cand_fx, 0, LPC_SHB_ORDER - 1 ); + + set16_fx( Q_lsfs_fx, 0, LPC_SHB_ORDER ); + /* mvr2r( mean_lsf, Q_lsfs, LPC_SHB_ORDER ); */ + + v_add_16( Q_lsfs_fx, cb_stage_fx + Idx * dim1, Q_lsfs_fx, dim1 ); + + /* write VQ indexes */ + push_indice( hBstr, IND_SHB_LSF, Idx, numbits_VQ ); + + /* write MSLVQ index */ + LVQ_index = index_lvq_SHB_fx( idx_lead, idx_scale, bits_lvq, cv_out_fx, ( nbits < 19 ) ); + + IF( GT_16( bits_lvq, 15 ) ) + { + push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) & ( 0xffff >> 1 ) ), 15 ); + push_indice( hBstr, IND_SHB_LSF, (Word16) ( ( LVQ_index ) >> 15 ) & ( 0xffff >> 1 ), bits_lvq - 15 ); + } + ELSE + { + push_indice( hBstr, IND_SHB_LSF, (Word16) LVQ_index, bits_lvq ); + } + + v_add_16( Q_lsfs_fx, quant_fx, lsf_q_fx, LATTICE_DIM ); /* quantized mean removed data for first 8 dim*/ + + /* predict last 2 components */ + IF( predictor_bits == 0 ) + { + lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, LastCoefPred_0bit_fx, LATTICE_DIM ); + move16(); + lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_0bit_fx[LATTICE_DIM + 1], LATTICE_DIM ); + move16(); + } + ELSE + { + v_sub_16( &lsf_fx[LATTICE_DIM], &SHB_LSF_mean_fx[LATTICE_DIM], &lsf_q_fx[LATTICE_DIM], 2 ); + + FOR( i = 0; i < 2; i++ ) + { + ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM]; + + e_fx[i] = mult( ftmp_fx, ftmp_fx ); + move16(); + + ftmp_fx = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * i + LATTICE_DIM + 1], LATTICE_DIM ) - lsf_q_fx[LATTICE_DIM + 1]; + + e_fx[i] = add_sat( e_fx[i], mult( ftmp_fx, ftmp_fx ) ); + move16(); + } + + c2_fx_temp = minimum_fx( e_fx, 2, &ftmp_fx ); + + lsf_q_fx[LATTICE_DIM] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp], LATTICE_DIM ); + move16(); + + lsf_q_fx[LATTICE_DIM + 1] = dotp_loc( lsf_q_fx, &LastCoefPred_1bit_fx[2 * ( LATTICE_DIM + 1 ) * c2_fx_temp + LATTICE_DIM + 1], LATTICE_DIM ); + move16(); + + push_indice( hBstr, IND_SHB_LSF, c2, 1 ); + } + + if ( empty_bits > 0 ) + { + push_indice( hBstr, IND_SHB_LSF, 0, empty_bits ); + } + + v_add_16( SHB_LSF_mean_fx, lsf_q_fx, lsf_q_fx, LPC_SHB_ORDER ); + + v_sort( lsf_q_fx, 0, LPC_SHB_ORDER - 1 ); + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + Q_lsfs_fx[i] = sub_sat( 16384 /* 0.5f in Q15 */, lsf_q_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + + return; +} + /*-------------------------------------------------------------------* * Quant_BWE_LSF() * @@ -4740,6 +6829,84 @@ static void Quant_BWE_LSF_fx( return; } + +static void Quant_BWE_LSF_ivas_fx( + BSTR_ENC_HANDLE hBstr, /* i/o: encoder bitstream handle */ + TD_BWE_ENC_HANDLE hBWE_TD, /* i/o: TD BWE data handle */ + const Word16 codec_mode, /* i : codec mode */ + const Word16 lsf_shb_fx[], /* i : unquanitzed LSFs Q15 */ + Word16 Q_lsfs_fx[], /* o : quanitzed LSFs Q15 */ + const Word32 extl_brate /* i : extension layer bit rate */ +) +{ + Word16 lsf_fx[LPC_SHB_ORDER]; + Word16 lsf_q_fx[LPC_SHB_ORDER]; + Word16 lsf_idx[NUM_Q_LSF]; + Word16 i; + Word16 m_idx; + Word16 m_fx; + Word16 grid_idx; + + IF( EQ_32( extl_brate, SWB_TBE_1k75 ) ) + { + LVQQuant_BWE_LSF_fx( hBstr, lsf_shb_fx, Q_lsfs_fx, NUM_BITS_SHB_MSLVQ ); + } + ELSE + { + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + lsf_fx[i] = sub( 16384 /* 0.5f in Q15 */, lsf_shb_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + Quant_lower_LSF_fx( lsf_fx, lsf_q_fx, lsf_idx ); + + FOR( i = 0; i < NUM_Q_LSF; i++ ) + { + IF( EQ_16( codec_mode, MODE2 ) ) + { + hBWE_TD->lsf_idx[i] = lsf_idx[i]; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_LSF, lsf_idx[i], lsf_q_num_bits[i] ); + } + } + + m_idx = Quant_mirror_point_fx( lsf_fx, lsf_q_fx, &m_fx ); + + IF( EQ_16( codec_mode, MODE2 ) ) + { + hBWE_TD->m_idx = m_idx; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_MIRROR, m_idx, MIRROR_POINT_BITS ); + } + + grid_idx = Find_LSF_grid_fx( lsf_fx, lsf_q_fx, m_fx ); + + IF( EQ_16( codec_mode, MODE2 ) ) + { + hBWE_TD->grid_idx = grid_idx; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_GRID, grid_idx, NUM_LSF_GRID_BITS ); + } + + FOR( i = 0; i < LPC_SHB_ORDER; i++ ) + { + Q_lsfs_fx[i] = sub( 16384 /* 0.5f in Q15 */, lsf_q_fx[LPC_SHB_ORDER - 1 - i] ); + move16(); + } + } + + return; +} + /*-------------------------------------------------------------------* * fb_tbe_enc() * @@ -5013,7 +7180,8 @@ void InitSWBencBufferStates_fx( set16_fx( hBWE_TD->mem_shb_res_fx, 0, MAX_LEN_MA_FILTER ); set16_fx( hBWE_TD->old_EnvSHBres_fx, 0, L_FRAME4k ); hBWE_TD->old_mean_EnvSHBres_fx = 0; - hBWE_TD->prev_enr_EnvSHBres_fx = 32767; /*1.0f in Q15*/ + hBWE_TD->prev_enr_EnvSHBres_fx = 1; /*1.0f in Q0*/ + hBWE_TD->prev_enr_EnvSHBres_e = 31; hBWE_TD->prev_shb_env_tilt_fx = 0; hBWE_TD->prev_pow_exc16kWhtnd_fx = 32767; /*1.0f in Q15*/ hBWE_TD->prev_mix_factor_fx = 32767; /*1.0f in Q15*/ diff --git a/lib_enc/tcx_ltp_enc_fx.c b/lib_enc/tcx_ltp_enc_fx.c index 32e44d84a..6d9ae393b 100644 --- a/lib_enc/tcx_ltp_enc_fx.c +++ b/lib_enc/tcx_ltp_enc_fx.c @@ -274,6 +274,226 @@ static void tcx_ltp_pitch_search( } } +static void tcx_ltp_pitch_search_ivas_fx( + const Word16 pitch_ol, + Word16 *pitch_int, + Word16 *pitch_fr, + Word16 *index, + Word16 *norm_corr, + const Word16 len, + const Word16 *wsp, // Qx + const Word16 pitmin, + const Word16 pitfr1, + const Word16 pitfr2, + const Word16 pitmax, + const Word16 pitres, + const Word16 check_border_case, + Word16 *border_case ) +{ + Word16 i, t, t0, t1, step, fraction, t0_min, t0_max, t_min, t_max, delta, temp_m, temp_e, s, s_wsp; + Word32 cor_max, cor[256], *pt_cor, temp; + Word16 wsp2[L_FRAME_PLUS + PIT_MAX_MAX + L_INTERPOL1]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + delta = 16; + move16(); + if ( EQ_16( pitres, 6 ) ) + { + delta = 8; + move16(); + } + + t0_min = sub( pitch_ol, shr( delta, 1 ) ); + t0_max = sub( add( t0_min, delta ), 1 ); + + IF( LT_16( t0_min, pitmin ) ) + { + t0_min = pitmin; + move16(); + t0_max = sub( add( t0_min, delta ), 1 ); + } + + IF( GT_16( t0_max, pitmax ) ) + { + t0_max = pitmax; + move16(); + t0_min = add( sub( t0_max, delta ), 1 ); + } + + t_min = sub( t0_min, L_INTERPOL1 ); + t_max = add( t0_max, L_INTERPOL1 ); + + /* normalize wsp */ + s_wsp = getScaleFactor16( wsp - t_max, add( len, t_max ) ); + s_wsp = sub( s_wsp, 4 ); + FOR( t = negate( t_max ); t < len; t++ ) + { + wsp2[t + t_max] = shl( wsp[t], s_wsp ); // Q(x + s_wsp) + move16(); + } + wsp = wsp2 + t_max; + + pt_cor = cor; + + FOR( t = t_min; t <= t_max; t++ ) + { + *pt_cor = dot( wsp, wsp - t, len ); // 2*(x + s_wsp) + pt_cor++; + } + + pt_cor = cor + L_INTERPOL1; + cor_max = L_add( *pt_cor++, 0 ); + t1 = t0_min; + move16(); + + FOR( t = add( t0_min, 1 ); t <= t0_max; t++ ) + { + IF( GT_32( *pt_cor, cor_max ) ) + { + cor_max = *pt_cor; + move32(); + t1 = t; + move16(); + } + pt_cor++; + } + + temp = dot( wsp, wsp, len ); // 2*(x + s_wsp) + s = norm_l( temp ); + temp_e = negate( s ); + temp_m = extract_h( L_shl( temp, s ) ); // Q(2*(x + s_wsp) - temp_e - 16) + + temp = dot( wsp - t1, wsp - t1, len ); // 2*(x + s_wsp) + s = norm_l( temp ); + temp_m = mult( temp_m, extract_h( L_shl( temp, s ) ) ); // //Q = 4*(x + s_wsp) + s - temp_e - 47 + temp_e = sub( temp_e, s ); + + temp_m = Sqrt16( temp_m, &temp_e ); + + if ( temp_m == 0 ) + { + temp_m = 1; + move16(); + } + s = sub( norm_l( cor_max ), 1 ); + temp_m = divide1616( extract_h( L_shl( cor_max, s ) ), temp_m ); + temp_e = sub( negate( s ), temp_e ); + +#ifdef BASOP_NOGLOB + *norm_corr = shl_o( temp_m, temp_e, &Overflow ); +#else + BASOP_SATURATE_WARNING_OFF_EVS + *norm_corr = shl( temp_m, temp_e ); + BASOP_SATURATE_WARNING_ON_EVS +#endif + + test(); + IF( check_border_case && EQ_16( t1, t0_min ) ) + { + Word32 tmpCor; + FOR( t = t1 - L_INTERPOL1; t < t1; t++ ) + { + tmpCor = dot( wsp, wsp - t, len ); + IF( GT_32( tmpCor, cor_max ) ) + { + *border_case = 1; + move16(); + break; + } + } + } + + IF( GE_16( t1, pitfr1 ) ) + { + *pitch_int = t1; + move16(); + *pitch_fr = 0; + move16(); + + *index = add( sub( t1, pitfr1 ), extract_l( L_mac0( L_mult0( sub( pitfr2, pitmin ), pitres ), + sub( pitfr1, pitfr2 ), shr( pitres, 1 ) ) ) ); + + return; + } + + /*------------------------------------------------------------------* + * Search fractional pitch with 1/4 subsample resolution. + * search the fractions around t0 and choose the one which maximizes + * the interpolated normalized correlation. + *-----------------------------------------------------------------*/ + + pt_cor = cor + sub( L_INTERPOL1, t0_min ); + t0 = t1; + move16(); + + step = 1; + move16(); + if ( GE_16( t0, pitfr2 ) ) + { + step = 2; + move16(); + } + fraction = step; + move16(); + + IF( EQ_16( t0, t0_min ) ) /* Limit case */ + { + fraction = 0; + move16(); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + } + ELSE /* Process negative fractions */ + { + t0 = sub( t0, 1 ); + cor_max = interpolate_corr( &pt_cor[t0], fraction, pitres ); + + FOR( i = add( fraction, step ); i < pitres; i += step ) + { + temp = interpolate_corr( &pt_cor[t0], i, pitres ); + + IF( GT_32( temp, cor_max ) ) + { + cor_max = L_add( temp, 0 ); + fraction = i; + move16(); + } + } + } + + FOR( i = 0; i < pitres; i += step ) /* Process positive fractions */ + { + temp = interpolate_corr( &pt_cor[t1], i, pitres ); + + IF( GT_32( temp, cor_max ) ) + { + cor_max = L_add( temp, 0 ); + fraction = i; + move16(); + t0 = t1; + move16(); + } + } + + *pitch_int = t0; + move16(); + *pitch_fr = fraction; + move16(); + + IF( GE_16( t0, pitfr2 ) ) + { + *index = add( extract_l( L_mac0( L_mult0( sub( t0, pitfr2 ), shr( pitres, 1 ) ), + sub( pitfr2, pitmin ), pitres ) ), + shr( fraction, 1 ) ); + } + ELSE + { + *index = add( imult1616( sub( t0, pitmin ), pitres ), fraction ); + } +} + static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_frame, Word16 *gain, Word16 *gain_index ) { @@ -340,6 +560,71 @@ static void tcx_ltp_find_gain( Word16 *speech, Word16 *pred_speech, Word16 L_fra move16(); } +static void tcx_ltp_find_gain_ivas_fx( Word16 *speech /*Qx*/, Word16 *pred_speech /*Qx*/, Word16 L_frame, Word16 *gain, Word16 *gain_index ) +{ + Word32 corr, ener; + Word16 i, g, s1, s2, tmp; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + s1 = sub( getScaleFactor16( speech, L_frame ), 4 ); + s2 = sub( getScaleFactor16( pred_speech, L_frame ), 4 ); + + /* Find gain */ + corr = L_deposit_l( 0 ); + ener = L_deposit_l( 1 ); + + FOR( i = 0; i < L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + tmp = shl_sat( pred_speech[i], s2 ); // Qx + s2 + corr = L_mac0_sat( corr, shl( speech[i], s1 ), tmp ); // 2*Qx + s1 + s2 + ener = L_mac0_sat( ener, tmp, tmp ); // 2*(Qx+s2) +#else + tmp = shl( pred_speech[i], s2 ); + corr = L_mac0( corr, shl( speech[i], s1 ), tmp ); + ener = L_mac0( ener, tmp, tmp ); +#endif + } + + s1 = sub( 1, add( s1, s2 ) ); + s2 = sub( 1, shl( s2, 1 ) ); + + tmp = sub( norm_l( corr ), 1 ); + corr = L_shl( corr, tmp ); + s1 = sub( s1, tmp ); + + tmp = norm_l( ener ); + ener = L_shl( ener, tmp ); + s2 = sub( s2, tmp ); + +#ifdef BASOP_NOGLOB + g = divide1616( round_fx_o( corr, &Overflow ), round_fx_o( ener, &Overflow ) ); +#else + g = divide1616( round_fx( corr ), round_fx( ener ) ); +#endif + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + g = shl_o( g, sub( s1, s2 ), &Overflow ); /*Q15*/ +#else /* BASOP_NOGLOB */ + g = shl( g, sub( s1, s2 ) ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + /* Quantize gain */ + g = shr_sat( sub_sat( g /*Q15*/, 0x1000 ), 13 ); // Q0 + g = s_max( g, -1 ); + + *gain_index = g; + move16(); + + /* Dequantize gain */ + *gain = imult1616( add( g, 1 ), 0x1400 ); /*Q15*/ + move16(); +} + void tcx_ltp_encode_fx( Word16 tcxltp_on, Word8 tcxOnly, Word16 tcxMode, @@ -646,3 +931,421 @@ void tcx_ltp_encode_fx( Word16 tcxltp_on, *norm_corr_past = norm_corr; move16(); } + +void tcx_ltp_encode_ivas_fx( + Encoder_State *st, + const Word16 tcxMode, + const Word16 L_frame, + Word16 *speech_fx, + Word16 *speech_ltp_fx, + const Word16 *wsp_fx, + const Word16 Top[], + Word16 *ltp_param, + Word16 *ltp_bits, + Word16 *A_fx, + const Word16 disable_ltp, + const Word16 element_mode ) +{ + Word16 i, n; + Word16 ltp_on, tcxOnly, L_subfr, SideInfoOnly, delta; + Word16 si_gain_fx; // Q15 + Word16 alpha_fx, step_fx; // Q15 + Word16 norm_corr_fx; // Q15 + Word16 border_case; + Word16 tempFlatness_fx; // Q7 + Word16 maxEnergyChange_fx; // Q7 + Word16 pred_speech_fx[L_FRAME_PLUS]; // Qspeech + Word16 buf_zir_fx[M + L_FRAME_PLUS / 4], *zir_fx; // Qspeech + Word16 Aest_fx[M + 1]; + Word16 exponent; + Word16 sqr; + Flag Overflow = 0; + move32(); + + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + + tcxOnly = st->tcxonly; + move16(); + L_subfr = L_SUBFR; + move16(); + SideInfoOnly = extract_l( GT_32( st->sr_core, 25600 ) ); + move16(); + + /* Reset memory if past frame is acelp */ + IF( st->last_core == ACELP_CORE ) + { + hTcxEnc->tcxltp_pitch_int_past = L_frame; + move16(); + hTcxEnc->tcxltp_pitch_int_past = 0; + move16(); + hTcxEnc->tcxltp_pitch_int_past = 0; + move16(); + } + + /* By default, LTP is off */ + ltp_param[0] = 0; + move16(); + norm_corr_fx = 0; + move16(); + border_case = 0; + move16(); + + test(); + IF( hTcxEnc->tcxltp || SideInfoOnly ) + { + Word16 nPrevSubblocks; + Word8 isTCX10 = 0; + move16(); + + /* Find pitch lag */ + IF( EQ_16( st->pit_res_max, 6 ) ) + { + delta = 8; + move16(); + } + ELSE + { + delta = 16; + move16(); + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IF( LT_16( abs_s( sub( Top[0], Top[1] ) ), shr( delta, 1 ) ) ) + { + /* estimates are close enough and stable, take the artihmetic mean as estimate */ + tcx_ltp_pitch_search_ivas_fx( shr( add( Top[0], Top[1] ), 1 ), &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, <p_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case ); + } + ELSE + { + /* pitch jumps between half frames, calc ltp for both estimates, choose the better one */ + Word16 pitch_int_2[2]; + Word16 pitch_fr_2[2]; + Word16 norm_corr_2_fx[2]; + Word16 pit_param_2[2]; + + FOR( i = 0; i < 2; i++ ) + { + tcx_ltp_pitch_search_ivas_fx( Top[i], &pitch_int_2[i], &pitch_fr_2[i], &pit_param_2[i], &norm_corr_2_fx[i], L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, 1, &border_case ); + } + + IF( GT_16( norm_corr_2_fx[1], norm_corr_2_fx[0] ) ) + { + i = 1; + move16(); + } + ELSE + { + i = 0; + move16(); + } + + hTcxEnc->tcxltp_pitch_int = pitch_int_2[i]; + move16(); + hTcxEnc->tcxltp_pitch_fr = pitch_fr_2[i]; + move16(); + ltp_param[1] = pit_param_2[i]; + move16(); + norm_corr_fx = norm_corr_2_fx[i]; + } + } + ELSE + { + Word16 tmp; + IF( GT_16( element_mode, EVS_MONO ) ) + { + tmp = 1; + } + ELSE + { + tmp = 0; + } + move16(); + tcx_ltp_pitch_search_ivas_fx( Top[1], &hTcxEnc->tcxltp_pitch_int, &hTcxEnc->tcxltp_pitch_fr, <p_param[1], &norm_corr_fx, L_frame, wsp_fx, st->pit_min, st->pit_fr1, st->pit_fr2, st->pit_max, st->pit_res_max, tmp, &border_case ); + } + + if ( border_case ) + { + norm_corr_fx = 0; + move16(); + } + + // nPrevSubblocks = ( 1 + min( NSUBBLOCKS, (int16_t) ceil( 0.5f + NSUBBLOCKS * ( 1.0f * ( hTcxEnc->tcxltp_pitch_int ) / L_frame ) ) ) ); + nPrevSubblocks = extract_h( L_add( L_mac( 32768, NSUBBLOCKS, div_s( hTcxEnc->tcxltp_pitch_int, L_frame ) ), 65535 ) ); // 0.5f Q16 //65535( 1.Q16 - 1) added to get the ceil + nPrevSubblocks = add( s_min( nPrevSubblocks, NSUBBLOCKS ), 1 ); + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + tempFlatness_fx = GetTCXAvgTemporalFlatnessMeasure_ivas_fx( st->hTranDet, NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q7 + maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10, + NSUBBLOCKS - NSUBBLOCKS_SHIFT, add( nPrevSubblocks, NSUBBLOCKS_SHIFT ) ); // Q7 + } + ELSE + { + tempFlatness_fx = GetTCXAvgTemporalFlatnessMeasure_ivas_fx( st->hTranDet, NSUBBLOCKS, nPrevSubblocks ); + maxEnergyChange_fx = GetTCXMaxenergyChange_ivas_fx( st->hTranDet, (const Word8) isTCX10, + NSUBBLOCKS, nPrevSubblocks ); + } + + /* Switch LTP on */ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( + ( tcxOnly == 0 ) && + EQ_16( tcxMode, TCX_20 ) && + GT_16( mult( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x2000 ) && /*mult returns Q15*/ + LT_16( tempFlatness_fx, 448 /*3.5f Q7*/ ) ) || + ( EQ_16( tcxOnly, 1 ) && + EQ_16( tcxMode, TCX_10 ) && + GT_16( s_max( norm_corr_fx, hTcxEnc->tcxltp_norm_corr_past ), 0x4000 ) && + LT_16( maxEnergyChange_fx, 448 /*3.5f Q7*/ ) ) || + ( /* Use LTP for lower correlation when pitch lag is big, L_frame*(1.2f-norm_corr) < pitch_int <=> norm_corr > 1.2f-pitch_int/L_frame */ + EQ_16( tcxOnly, 1 ) && + GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) && + L_msu( L_mult( L_frame, sub( 19661 /*1.2f Q14*/, shr( norm_corr_fx, 1 ) ) ), hTcxEnc->tcxltp_pitch_int, 1 << 14 ) < 0 /* L_frame*(1.2f-norm_corr) < pitch_int */ + ) || + ( EQ_16( tcxOnly, 1 ) && + EQ_16( tcxMode, TCX_20 ) && + GT_16( norm_corr_fx, 14418 /*0.44f Q15*/ ) && + ( LT_16( tempFlatness_fx, 768 /*6.0f Q7*/ ) || + ( LT_16( tempFlatness_fx, 896 /*7.0f Q7*/ ) && + LT_16( maxEnergyChange_fx, 2816 /*22.0f Q7*/ ) ) ) ) ) + { + IF( disable_ltp == 0 ) + { + ltp_param[0] = 1; + move16(); + } + } + + /* hysteresis for stable ltp prediction */ + ltp_on = 0; + move16(); + + test(); + test(); + test(); + test(); + test(); + + exponent = 15; + move16(); + sqr = Sqrt16( hTcxEnc->tcxltp_on_mem, &exponent ); + move16(); + sqr = shl_sat( sqr, exponent ); + IF( ( EQ_16( tcxOnly, 1 ) && EQ_16( st->element_mode, IVAS_CPE_MDCT ) && ( GT_16( ( mult( sqr, mult( ( norm_corr_fx ), 29492 ) ) ), 14419 ) && ( LT_16( tempFlatness_fx, 768 ) || ( LT_16( tempFlatness_fx, 896 ) && LT_16( maxEnergyChange_fx, 2816 ) ) ) ) ) ) // 0.9f Q15, 6.0f Q7, 7.0f Q7, 22.0f Q7 + { + ltp_on = 1; + move16(); + } + + test(); + IF( EQ_16( tcxOnly, 1 ) && EQ_16( ltp_param[0], 1 ) ) + { + /* increase ltp counter */ + hTcxEnc->tcxltp_on_mem = s_min( 5, add( hTcxEnc->tcxltp_on_mem, 1 ) ); + move16(); + } + ELSE IF( EQ_16( ltp_on, 1 ) ) + { + /* hysteresis takes effect, decrease counter */ + hTcxEnc->tcxltp_on_mem = s_max( 0, sub( hTcxEnc->tcxltp_on_mem, 1 ) ); + move16(); + ltp_param[0] = ltp_on; + move16(); + } + ELSE + { + /* no ltp in this frame, reset counter */ + hTcxEnc->tcxltp_on_mem = 0; + move16(); + } + } + + /* Find predicted signal */ + predict_signal( speech_fx, pred_speech_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, L_frame ); + + /* Find gain */ + tcx_ltp_find_gain_ivas_fx( speech_fx, pred_speech_fx, L_frame, &hTcxEnc->tcxltp_gain, <p_param[2] ); + + IF( ltp_param[0] ) + { + /* Total number of bits for LTP */ + IF( add( ltp_param[2], 1 ) ) /* hTcxEnc->tcxltp_gain > 0 */ + { + *ltp_bits = 12; + move16(); + } + ELSE /* hTcxEnc->tcxltp_gain <= 0 -> turn off LTP */ + { + ltp_param[0] = 0; + move16(); + } + } + + IF( !ltp_param[0] ) + { + /* No LTP -> set everything to zero */ + hTcxEnc->tcxltp_pitch_int = L_frame; + move16(); + hTcxEnc->tcxltp_pitch_fr = 0; + move16(); + ltp_param[1] = 0; + move16(); + set16_fx( pred_speech_fx, 0, L_frame ); + hTcxEnc->tcxltp_gain = 0; + move16(); + ltp_param[2] = 0; + move16(); + + test(); + IF( hTcxEnc->tcxltp || SideInfoOnly ) + { + *ltp_bits = 1; + move16(); + } + ELSE + { + *ltp_bits = 0; + move16(); + } + } + + si_gain_fx = 0; + move16(); + + IF( SideInfoOnly ) + { + si_gain_fx = hTcxEnc->tcxltp_gain; + move16(); + hTcxEnc->tcxltp_gain = 0; + move16(); + } + + IF( speech_ltp_fx != NULL ) + { + test(); + IF( hTcxEnc->tcxltp_gain_past == 0 && hTcxEnc->tcxltp_gain == 0 ) + { + Copy( speech_fx, speech_ltp_fx, L_subfr ); + } + ELSE IF( hTcxEnc->tcxltp_gain_past == 0 ) + { + alpha_fx = 0; + move16(); + + step_fx = shl( 2, norm_s( L_subfr ) ); + IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 ) + { + step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ ); + } + + FOR( n = 0; n < L_subfr; n++ ) + { + speech_ltp_fx[n] = sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, mult_ro( alpha_fx, pred_speech_fx[n], &Overflow ), &Overflow ), &Overflow ); + move16(); + alpha_fx = add_sat( alpha_fx, step_fx ); + } + } + ELSE + { + IF( A_fx == NULL ) + { + tcx_ltp_get_lpc( speech_fx - L_frame, L_frame, Aest_fx, M ); + A_fx = Aest_fx; + } + + IF( hTcxEnc->tcxltp_gain > 0 ) + { + predict_signal( speech_fx - M, buf_zir_fx, hTcxEnc->tcxltp_pitch_int, hTcxEnc->tcxltp_pitch_fr, st->pit_res_max, M ); + } + ELSE + { + set16_fx( buf_zir_fx, 0, M ); + } + + FOR( n = 0; n < M; n++ ) + { + buf_zir_fx[n] = add_sat( sub_sat( speech_ltp_fx[n - M], speech_fx[n - M] ), mult_r( hTcxEnc->tcxltp_gain, buf_zir_fx[n] ) ); + move16(); + } + + zir_fx = buf_zir_fx + M; + set16_fx( zir_fx, 0, L_subfr ); + + Syn_filt_s( 0, A_fx, M, zir_fx, zir_fx, L_subfr, buf_zir_fx, 0 ); + + alpha_fx = 0x7FFF; // 1.f Q15 + move16(); + step_fx = shl( 4, norm_s( L_subfr ) ); + IF( s_and( L_subfr, sub( L_subfr, 1 ) ) != 0 ) + { + step_fx = mult_r( step_fx, 26214 /*64.f/80.f Q15*/ ); + } + + FOR( n = shr( L_subfr, 1 ); n < L_subfr; n++ ) + { + zir_fx[n] = mult_r( zir_fx[n], alpha_fx ); + move16(); + alpha_fx = sub( alpha_fx, step_fx ); + } + + FOR( n = 0; n < L_subfr; n++ ) + { + speech_ltp_fx[n] = add_o( sub_o( speech_fx[n], mult_ro( hTcxEnc->tcxltp_gain, pred_speech_fx[n], &Overflow ), &Overflow ), zir_fx[n], &Overflow ); + move16(); + } + } + + test(); + IF( SideInfoOnly || hTcxEnc->tcxltp_gain == 0 ) + { + FOR( n = L_subfr; n < L_frame; n++ ) + { + speech_ltp_fx[n] = speech_fx[n]; + move16(); + } + } + ELSE + { + FOR( n = L_subfr; n < L_frame; n++ ) + { + speech_ltp_fx[n] = sub_o( speech_fx[n], mult( hTcxEnc->tcxltp_gain, pred_speech_fx[n] ), &Overflow ); + move16(); + } + } + } + + /* Update */ + hTcxEnc->tcxltp_pitch_int_past = hTcxEnc->tcxltp_pitch_int; + move16(); + hTcxEnc->tcxltp_pitch_fr_past = hTcxEnc->tcxltp_pitch_fr; + move16(); + hTcxEnc->tcxltp_gain_past = hTcxEnc->tcxltp_gain; + move16(); + + IF( SideInfoOnly ) + { + hTcxEnc->tcxltp_gain = si_gain_fx; + move16(); + } + + hTcxEnc->tcxltp_norm_corr_past = norm_corr_fx; + move16(); + + return; +} diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index 7a6cb1ad9..15379f73a 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -1681,17 +1681,7 @@ void ProcessIGF_ivas_fx( IGFSaveSpectrumForITF_ivas_fx( hIGFEnc, igfGridIdx, pITFMDCTSpectrum ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - float pMDCTSpectrum_flt[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ - float pPowerSpectrum_flt[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ - fixedToFloat_arrL32( pMDCTSpectrum, pMDCTSpectrum_flt, *q_spectrum, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); - fixedToFloat_arrL32( pPowerSpectrum, pPowerSpectrum_flt, *q_powerSpec, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); -#endif - IGFEncApplyMono( st, igfGridIdx, pMDCTSpectrum_flt, pPowerSpectrum_flt, isTCX20, st->hTcxEnc->fUseTns[frameno], sp_aud_decision0, vad_hover_flag ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - floatToFixed_arrL32( pMDCTSpectrum_flt, pMDCTSpectrum, *q_spectrum, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); - floatToFixed_arrL32( pPowerSpectrum_flt, pPowerSpectrum, *q_powerSpec, hIGFEnc->igfData.igfInfo.grid[igfGridIdx].infoGranuleLen ); -#endif + IGFEncApplyMono_ivas_fx( st, igfGridIdx, pMDCTSpectrum, sub( Q31, *q_spectrum ), pPowerSpectrum, sub( Q31, *q_powerSpec ), isTCX20, st->hTcxEnc->fUseTns[frameno], sp_aud_decision0, vad_hover_flag ); curr_order = 0; move16(); diff --git a/lib_enc/transient_detection_fx.c b/lib_enc/transient_detection_fx.c index 3e6bafcd6..1a47751fa 100644 --- a/lib_enc/transient_detection_fx.c +++ b/lib_enc/transient_detection_fx.c @@ -12,8 +12,9 @@ #include #include #include -#include "prot_fx.h" /* Function prototypes */ -#include "prot_fx_enc.h" /* Function prototypes */ +#include "prot_fx.h" /* Function prototypes */ +#include "ivas_prot_fx.h" /* Function prototypes */ +#include "prot_fx_enc.h" /* Function prototypes */ /* Exponent of attack threshold. Picked according to current threshold values. */ #define ATTACKTHRESHOLD_E 4 @@ -26,6 +27,14 @@ #define MIN_BLOCK_ENERGY ( (Word32) 1 ) +#ifdef IVAS_FLOAT_FIXED +#define MIN_BLOCK_ENERGY_FX 107 +#define THR_HIGH_FX 17408 /* 8.5f in Q11 */ +#define THR_NORM_HIGH_FX 16384 /* 8 in Q11 */ +#define THR_NORM_LOW_FX 9216 /* 4.5f in Q11 */ +#define THR_LOW_FX 8704 /* 4.25f in Q11 */ +#define THR_LOW_STEP_FX ONE_IN_Q11 /* 1 in Q11 */ +#endif /************************************************/ /* */ @@ -303,6 +312,43 @@ Word16 GetTCXAvgTemporalFlatnessMeasure_fx( struct TransientDetection const *pTr return i; } +Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( TRAN_DET_HANDLE pTransientDetection, Word16 nCurrentSubblocks, Word16 nPrevSubblocks ) +{ + Word16 i; + TransientDetector const *pTransientDetector; + SubblockEnergies const *pSubblockEnergies; + Word16 nDelay; + Word16 nRelativeDelay; + Word16 const *pSubblockNrgChange; + Word32 sumTempFlatness; + Word16 nTotBlocks; + + /* Initialization */ + pTransientDetector = &pTransientDetection->transientDetector; + pSubblockEnergies = pTransientDetector->pSubblockEnergies; + nDelay = pTransientDetector->nDelay; + nRelativeDelay = sub( pSubblockEnergies->nDelay, nDelay ); + pSubblockNrgChange = NULL; + nTotBlocks = add( nCurrentSubblocks, nPrevSubblocks ); + + assert( nTotBlocks > 0 ); + + sumTempFlatness = L_deposit_l( 0 ); + + assert( ( nPrevSubblocks <= nRelativeDelay ) && ( nCurrentSubblocks <= NSUBBLOCKS + nDelay ) ); + + pSubblockNrgChange = &pSubblockEnergies->subblockNrgChange[sub( nRelativeDelay, nPrevSubblocks )]; // subblockNrgChange Q7 + FOR( i = 0; i < nTotBlocks; i++ ) + { + sumTempFlatness = L_add( sumTempFlatness, L_deposit_l( pSubblockNrgChange[i] ) ); + } + + /* exponent = AVG_FLAT_E */ + i = div_l( L_shl( sumTempFlatness, 16 - 15 + SUBBLOCK_NRG_CHANGE_E - AVG_FLAT_E ), nTotBlocks ); // Q7 + + return i; +} + Word16 GetTCXMaxenergyChange_fx( struct TransientDetection const *pTransientDetection, const Word8 isTCX10, const Word16 nCurrentSubblocks, @@ -1221,7 +1267,7 @@ void set_transient_stereo( return; } - +#endif /*-------------------------------------------------------------------* * transient_analysis() * @@ -1229,93 +1275,145 @@ void set_transient_stereo( *-------------------------------------------------------------------*/ /*! r: preliminary flag to force ACELP */ -int16_t transient_analysis( - TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ - const float cor_map_LT[], /* i : LT correlation map */ - const float multi_harm_limit /* i : multi harminic threshold */ -) +Word16 transient_analysis_ivas_fx( + TRAN_DET_HANDLE hTranDet, /* i : handle transient detection */ + const Word16 cor_map_LT[], /* i : LT correlation map Q_cor_map */ + Word16 Q_cor_map, + const Word16 multi_harm_limit, /* i : multi harmonic threshold Q_multi_harm_limit */ + Word16 Q_multi_harm_limit ) { - const float *pSubblockNrg; - float accSubblockNrgRev[NSUBBLOCKS]; /* store acc Nrg in reversed signal */ - float *pTmp; /* point to acc Nrg */ - int16_t offset; - int16_t i; - float thr_fwd; - float thr_rev; - const int16_t nRelativeDelay = hTranDet->subblockEnergies.nDelay - hTranDet->transientDetector.nDelay; - int16_t prel_force_td; - float cor_map_LT_sum; - - pTmp = &accSubblockNrgRev[NSUBBLOCKS - 1]; - offset = nRelativeDelay - 4; + const Word32 *pSubblockNrg; + Word32 accSubblockNrgRev_fx[NSUBBLOCKS]; + Word32 *pTmp_fx; + Word16 offset; + Word16 i; + Word16 thr_fwd_fx; + Word16 thr_rev_fx; + const Word16 nRelativeDelay = sub( hTranDet->subblockEnergies.nDelay, hTranDet->transientDetector.nDelay ); + Word16 prel_force_td; + Word32 cor_map_LT_sum = 0; + move16(); + + /* Set pointer to the reverse accumulator buffer */ + pTmp_fx = &accSubblockNrgRev_fx[NSUBBLOCKS - 1]; + offset = sub( nRelativeDelay, 4 ); prel_force_td = FALSE; + move16(); + + cor_map_LT_sum = sum16_32_fx( cor_map_LT, L_FFT / 2 ); + + thr_fwd_fx = THR_NORM_HIGH_FX; // THR_NORM_HIGH_FX is in Q11 Format + move16(); + Word16 shift = 0; + move16(); + /* Q_cor_map: cor_map_LT is in Q_cor_map format */ + /* Q_multi_harm_limit: multi_harm_limit is in Q_multi_harm_limit format */ + IF( GT_16( Q_cor_map, Q_multi_harm_limit ) ) + { + shift = sub( Q_cor_map, Q_multi_harm_limit ); + + if ( GT_32( L_shr( cor_map_LT_sum, shift ), L_deposit_l( mult( multi_harm_limit, 26214 ) ) ) ) // 26214 is 0.8 in Q15 format + { + thr_fwd_fx = THR_HIGH_FX; // THR_HIGH_FX is in Q11 Format + move16(); + } + } + ELSE + { + shift = sub( Q_multi_harm_limit, Q_cor_map ); - /* summation of the LT correlation map */ - cor_map_LT_sum = sum_f( cor_map_LT, L_FFT / 2 ); /* Note maybe BE optimized by computing inside noise_est */ + if ( GT_32( cor_map_LT_sum, L_deposit_l( shr( mult( multi_harm_limit, 26214 ), shift ) ) ) ) // 26214 is 0.8 in Q15 format + { + thr_fwd_fx = THR_HIGH_FX; // THR_HIGH_FX is in Q11 Format + move16(); + } + } - thr_fwd = THR_NORM_HIGH; - if ( cor_map_LT_sum > multi_harm_limit * 0.8f ) + thr_rev_fx = THR_LOW_FX; // THR_LOW_FX is in Q11 Format + move16(); + IF( GT_16( Q_cor_map, Q_multi_harm_limit ) ) { - thr_fwd = THR_HIGH; + shift = sub( Q_cor_map, Q_multi_harm_limit ); + + if ( GT_32( L_shr( cor_map_LT_sum, shift ), L_deposit_l( mult( multi_harm_limit, 19661 ) ) ) ) // 19661 is 0.6 in Q15 format + { + thr_rev_fx = THR_NORM_LOW_FX; // THR_NORM_LOW_FX is in Q11 Format + move16(); + } } - thr_rev = THR_LOW; - if ( cor_map_LT_sum > multi_harm_limit * 0.6f ) + ELSE { - thr_rev = THR_NORM_LOW; + shift = sub( Q_multi_harm_limit, Q_cor_map ); + + if ( GT_32( cor_map_LT_sum, L_deposit_l( shr( mult( multi_harm_limit, 19661 ), shift ) ) ) ) // 19661 is 0.6 in Q15 format + { + thr_rev_fx = THR_NORM_LOW_FX; // THR_NORM_LOW_FX is in Q11 Format + move16(); + } } - /* forward attack analysis */ - for ( i = -2; i < 7; i++ ) + /* Forward attack analysis */ + FOR( i = -2; i < 7; i++ ) { - if ( hTranDet->subblockEnergies.subblockNrg[nRelativeDelay + i] > hTranDet->subblockEnergies.accSubblockNrg[nRelativeDelay + i] * thr_fwd ) + IF( BASOP_Util_Cmp_Mant32Exp( hTranDet->subblockEnergies.subblockNrg[nRelativeDelay + i], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( hTranDet->subblockEnergies.accSubblockNrg[nRelativeDelay + i], thr_fwd_fx ), add( hTranDet->subblockEnergies.accSubblockNrg_e, 4 ) ) > 0 ) { - prel_force_td |= 0x0001; + prel_force_td = s_or( prel_force_td, 0x0001 ); } } - if ( prel_force_td == 0 && hTranDet->transientDetector.prev_bIsAttackPresent == 1 ) + + test(); + IF( prel_force_td == 0 && EQ_16( hTranDet->transientDetector.prev_bIsAttackPresent, 1 ) ) { - /* release analysis */ + /* Release analysis */ pSubblockNrg = hTranDet->transientDetector.pSubblockEnergies->subblockNrg; - set_zero( accSubblockNrgRev, NSUBBLOCKS ); - for ( i = NSUBBLOCKS - 1; i > -1; i-- ) + set32_fx( accSubblockNrgRev_fx, 0, NSUBBLOCKS ); + + FOR( i = NSUBBLOCKS - 1; i > -1; i-- ) { - if ( i == NSUBBLOCKS - 1 ) + + IF( EQ_16( i, NSUBBLOCKS - 1 ) ) { - accSubblockNrgRev[i] = pSubblockNrg[i + offset]; + accSubblockNrgRev_fx[i] = pSubblockNrg[i + offset]; + move32(); } - else + ELSE { - accSubblockNrgRev[i] = *pTmp; - *pTmp *= hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg; - if ( pSubblockNrg[i + offset] > *pTmp ) + accSubblockNrgRev_fx[i] = *pTmp_fx; + *pTmp_fx = Mpy_32_16_1( *pTmp_fx, hTranDet->transientDetector.pSubblockEnergies->facAccSubblockNrg ); + move32(); + if ( GT_32( pSubblockNrg[i + offset], *pTmp_fx ) ) { - *pTmp = pSubblockNrg[i + offset]; + *pTmp_fx = pSubblockNrg[i + offset]; + move32(); } } } /* -3 check */ - if ( pSubblockNrg[1 + offset] > accSubblockNrgRev[1] * thr_rev ) + test(); + IF( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg[1 + offset], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( accSubblockNrgRev_fx[1], thr_rev_fx ), add( hTranDet->subblockEnergies.subblockNrg_e, 4 ) ) > 0 ) { - prel_force_td |= 0x0002; + prel_force_td = s_or( prel_force_td, 0x0002 ); + move16(); } /* -4 check */ - if ( prel_force_td == 0 && pSubblockNrg[offset] > accSubblockNrgRev[0] * thr_rev ) + test(); + IF( prel_force_td == 0 && BASOP_Util_Cmp_Mant32Exp( pSubblockNrg[offset], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( accSubblockNrgRev_fx[0], thr_rev_fx ), add( hTranDet->subblockEnergies.subblockNrg_e, 4 ) ) > 0 ) { - if ( pSubblockNrg[offset] > accSubblockNrgRev[0] * ( thr_rev + THR_LOW_STEP ) ) + + IF( BASOP_Util_Cmp_Mant32Exp( pSubblockNrg[offset], hTranDet->subblockEnergies.subblockNrg_e, Mpy_32_16_1( accSubblockNrgRev_fx[0], add( thr_rev_fx, THR_LOW_STEP_FX ) ), add( hTranDet->subblockEnergies.subblockNrg_e, 4 ) ) > 0 ) { - prel_force_td |= 0x0004; + prel_force_td = s_or( prel_force_td, 0x0004 ); } - else if ( ( hTranDet->subblockEnergies.ramp_up_flag & 0x0002 ) != 0 ) + ELSE IF( ( s_and( hTranDet->subblockEnergies.ramp_up_flag, 0x0002 ) ) != 0 ) { - prel_force_td |= 0x0008; + prel_force_td = s_or( prel_force_td, 0x0008 ); } } } + return prel_force_td != 0; } - -#endif diff --git a/lib_enc/updt_enc.c b/lib_enc/updt_enc.c index 6ea9eb417..edb92622e 100644 --- a/lib_enc/updt_enc.c +++ b/lib_enc/updt_enc.c @@ -42,6 +42,7 @@ #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" #include "prot_fx_enc.h" +#include "ivas_prot_fx.h" #endif #include "wmc_auto.h" @@ -453,7 +454,6 @@ void updt_enc_common( /*---------------------------------------------------------------------* * Updates - main main codec parameters *---------------------------------------------------------------------*/ - st->last_sr_core = st->sr_core; st->last_codec_mode = st->codec_mode; st->last_L_frame = st->L_frame; @@ -615,3 +615,226 @@ void updt_enc_common( return; } + + +#ifdef IVAS_FLOAT_FIXED +void updt_enc_common_ivas_fx( + Encoder_State *st /* i/o: encoder state structure */ +) +{ + /*---------------------------------------------------------------------* + * Updates - main main codec parameters + *---------------------------------------------------------------------*/ + st->last_sr_core = st->sr_core; + move32(); + st->last_codec_mode = st->codec_mode; + move16(); + st->last_L_frame = st->L_frame; + move16(); + st->last_core = st->core; + move16(); + + st->last_total_brate = st->total_brate; + move32(); + st->last_bits_frame_nominal = st->bits_frame_nominal; + move16(); + st->last_core_brate = st->core_brate; + move32(); + st->last_extl = st->extl; + move16(); + st->last_input_bwidth = st->input_bwidth; + move16(); + st->last_bwidth = st->bwidth; + move16(); + st->last_coder_type_raw = st->coder_type_raw; + move16(); + + test(); + IF( GT_32( st->core_brate, SID_2k40 ) && st->hDtxEnc != NULL ) + { + st->hDtxEnc->last_active_brate = st->total_brate; + move32(); + } + + IF( st->hBWE_TD != NULL ) + { + IF( EQ_16( st->core, HQ_CORE ) ) + { + /* in the HQ core, coder_type is not used so it could have been set to anything */ + st->hBWE_TD->prev_coder_type = GENERIC; + move16(); + } + ELSE + { + st->hBWE_TD->prev_coder_type = st->coder_type; + move16(); + } + } + + test(); + IF( st->Opt_DTX_ON && st->hTdCngEnc != NULL ) + { + IF( GT_32( st->core_brate, SID_2k40 ) ) + { + IF( EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( GE_16( st->hTdCngEnc->act_cnt, BUF_DEC_RATE ) ) + { + st->hTdCngEnc->act_cnt = 0; + move16(); + } + st->hTdCngEnc->act_cnt = add( st->hTdCngEnc->act_cnt, 1 ); + move16(); + + test(); + IF( EQ_16( st->hTdCngEnc->act_cnt, BUF_DEC_RATE ) && st->hTdCngEnc->ho_hist_size > 0 ) + { + st->hTdCngEnc->ho_hist_size = sub( st->hTdCngEnc->ho_hist_size, 1 ); + move16(); + } + } + + test(); + test(); + test(); + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) || EQ_16( st->hDtxEnc->first_CNG, 1 ) ) + { + IF( GE_16( ++( st->hTdCngEnc->act_cnt2 ), MIN_ACT_CNG_UPD ) ) + { + st->hTdCngEnc->act_cnt2 = MIN_ACT_CNG_UPD; + move16(); + } + + test(); + test(); + test(); + test(); + IF( ( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GE_16( st->hTdCngEnc->act_cnt2, MIN_ACT_CNG_UPD ) ) + { + Word32 cng_att_fx32 = 0; + + apply_scale( &cng_att_fx32, st->hFdCngEnc->hFdCngCom->CngBandwidth, st->hFdCngEnc->hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO ); + + st->hTdCngEnc->CNG_att_fx = extract_l( L_shr( cng_att_fx32, Q16 ) ); // Q23 + } + } + } + + test(); + test(); + test(); + IF( ( EQ_32( st->core_brate, SID_2k40 ) || EQ_32( st->core_brate, FRAME_NO_DATA ) ) && st->hDtxEnc->first_CNG == 0 && EQ_16( st->cng_type, LP_CNG ) ) + { + st->hDtxEnc->first_CNG = 1; + move16(); + } + } + + /*-----------------------------------------------------------------* + * Increase the counter of initialization frames + * Limit the max number of init. frames + *-----------------------------------------------------------------*/ + + IF( LT_16( st->ini_frame, MAX_FRAME_COUNTER ) ) + { + st->ini_frame = add( st->ini_frame, 1 ); + } + + /* synchronisation of CNG seeds */ + test(); + test(); + IF( st->hTdCngEnc != NULL && NE_32( st->core_brate, FRAME_NO_DATA ) && NE_32( st->core_brate, SID_2k40 ) && NE_16( st->core, AMR_WB_CORE ) ) + { + Random( &( st->hTdCngEnc->cng_seed ) ); + Random( &( st->hTdCngEnc->cng_ener_seed ) ); + } + + /*---------------------------------------------------------------------* + * Updates - MODE2 + *---------------------------------------------------------------------*/ + + test(); + IF( EQ_16( st->element_mode, EVS_MONO ) && EQ_16( st->mdct_sw, MODE2 ) ) + { + st->codec_mode = MODE2; + move16(); + + st->sr_core = getCoreSamplerateMode2( EVS_MONO, st->total_brate, st->bwidth, st->flag_ACELP16k, st->rf_mode, 0 ); + move16(); + + Word16 exp; + st->L_frame = BASOP_Util_Divide3232_Scale( st->sr_core, FRAMES_PER_SEC, &exp ); + st->L_frame = shr( st->L_frame, sub( 15, exp ) ); + move16(); + + IF( EQ_32( st->sr_core, INT_FS_12k8 ) ) + { + st->preemph_fac = PREEMPH_FAC; + st->gamma = GAMMA1; + } + ELSE + { + + st->preemph_fac = PREEMPH_FAC_16k; + st->gamma = GAMMA16k; + } + + st->igf = getIgfPresent_fx( EVS_MONO, st->total_brate, st->bwidth, st->rf_mode ); + } + + /* update FER clas */ + IF( NE_16( st->core, AMR_WB_CORE ) ) + { + st->last_clas = st->clas; + move16(); + } + + /* Update Core */ + core_encode_update_ivas_fx( st ); + + /*---------------------------------------------------------------------* + * RF mode updates + *---------------------------------------------------------------------*/ + + IF( st->rf_mode ) + { + IF( st->hSC_VBR != NULL ) + { + IF( st->hRF->rf_frame_type == RF_NELP ) + { + st->hSC_VBR->last_nelp_mode = 1; + move16(); + } + ELSE + { + st->hSC_VBR->last_nelp_mode = 0; + move16(); + } + } + } + + st->rf_mode_last = st->rf_mode; + move16(); + + IF( st->Opt_RF_ON ) + { + st->L_frame = L_FRAME; + st->rf_mode = 1; + move16(); + move16(); + } + + /*---------------------------------------------------------------------* + * Other updates + *---------------------------------------------------------------------*/ + + test(); + IF( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + st->hTcxEnc->tcxltp_norm_corr_mem = st->hTcxEnc->tcxltp_norm_corr_past; + } + + return; +} + +#endif diff --git a/lib_enc/vad_fx.c b/lib_enc/vad_fx.c index 46cf0e1aa..427dfa2e7 100644 --- a/lib_enc/vad_fx.c +++ b/lib_enc/vad_fx.c @@ -1967,6 +1967,20 @@ Word16 wb_vad_ivas_fx( #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; #endif + Word16 L_msnr_e = 0, L_mssnr_e = 0, L_mssnr_hov_e = 0, L_msnr18_e = 0, L_msnr19_e = 0; + move16(); /*L_msnr_e*/ + move16(); /*L_mssnr_e*/ + move16(); /*L_mssnr_hov_e*/ + move16(); /*L_msnr18_e*/ + move16(); /*L_msnr19_e*/ + move16(); /*Overflow*/ + move32(); /*L_mssnr*/ + move16(); /*thr1*/ + move16(); /*thr2*/ + move16(); /*nk*/ + move16(); /*nc*/ + move16(); /*th_clean*/ + move16(); /*flag*/ if ( hNoiseEst == NULL ) { @@ -2366,31 +2380,43 @@ Word16 wb_vad_ivas_fx( tmp = s_min( tmp, 16384 ); /* Q13, ftmp = min(ftmp, 2.0f); */ tmp1 = s_min( tmp1, 16384 ); /* Q13, ftmp1 = min(ftmp1, 2.0f); */ - L_msnr = L_deposit_l( tmp ); /*msnr = 1*tmp;*/ + Word16 norm_tmp = norm_l( tmp ); + Word32 scaled_tmp = L_shl( tmp, norm_tmp ); /*13+norm_tmp*/ + L_msnr = scaled_tmp; + move32(); + L_msnr_e = sub( 18, norm_tmp ); FOR( j = 1; j < stmp; j++ ) { /* Q13*Q13 +1 -16 +2 = Q13 */ - L_msnr = L_shl( Mult_32_16( L_msnr, tmp ), 2 ); /*Q13 , msnr *= ftmp;*/ + L_msnr = Mult_32_32( L_msnr, scaled_tmp ); /*L_msnr_e , msnr *= ftmp;*/ } - L_mssnr = L_add( L_mssnr, L_msnr ); /*Q13 mssnr += msnr;*/ + L_msnr_e = imult1616( L_msnr_e, stmp ); + L_mssnr = BASOP_Util_Add_Mant32Exp( L_mssnr, L_mssnr_e, L_msnr, L_msnr_e, &L_mssnr_e ); /*L_mssnr_e mssnr += msnr;*/ - if ( EQ_16( i, 18 ) ) + IF( EQ_16( i, 18 ) ) { - L_msnr18 = L_add( L_msnr, 0 ); /*Q13 msnr18 = msnr; */ + L_msnr18 = L_add( L_msnr, 0 ); /*L_msnr_e msnr18 = msnr; */ + L_msnr18_e = L_msnr_e; + move16(); } - if ( EQ_16( i, 19 ) ) + IF( EQ_16( i, 19 ) ) { - L_msnr19 = L_add( L_msnr, 0 ); /* Q13 , msnr19 = msnr; */ + L_msnr19 = L_add( L_msnr, 0 ); /* L_msnr_e , msnr19 = msnr; */ + L_msnr19_e = L_msnr_e; + move16(); } - L_msnr = L_deposit_l( tmp1 ); /* Q13, msnr = 1*tmp1 ;*/ - + norm_tmp = norm_l( tmp1 ); + scaled_tmp = L_shl( tmp1, norm_tmp ); /*13+norm_tmp*/ + L_msnr = scaled_tmp; + L_msnr_e = sub( 18, norm_tmp ); FOR( j = 1; j < stmp; j++ ) { - L_msnr = L_shl( Mult_32_16( L_msnr, tmp1 ), 2 ); /*Q13 msnr *= ftmp1;*/ + L_msnr = Mult_32_32( L_msnr, scaled_tmp ); /*L_msnr_e msnr *= ftmp1;*/ } - L_mssnr_hov = L_add( L_mssnr_hov, L_msnr ); /*Q13 mssnr_hov += msnr; */ + L_msnr_e = imult1616( L_msnr_e, stmp ); + L_mssnr_hov = BASOP_Util_Add_Mant32Exp( L_mssnr_hov, L_mssnr_hov_e, L_msnr, L_msnr_e, &L_mssnr_hov_e ); /*L_mssnr_hov_e mssnr_hov += msnr; */ /* recompute after he1 modifications */ /* snr[i] = fr_enr / st->bckr[i] = L_tmp1/st->bckr[i];*/ @@ -2479,12 +2505,16 @@ Word16 wb_vad_ivas_fx( { /* mssnr = (mssnr + 3*(msnr18 + msnr19)) * 0.77f; */ /* mssnr = (mssnr*.77f + 2.31f*(msnr18 + msnr19)); */ - L_tmp1 = Mult_32_16( L_mssnr, 25231 ); /* Q13+Q15+1-16 --> Q13 */ - L_tmp = Mult_32_16( L_shl( L_add( L_msnr18, L_msnr19 ), 2 ), 18924 ); /* Q(13+2)+Q(15-2)+1-16 --> Q13 */ - L_tmp = L_add( L_tmp1, L_tmp ); - if ( GT_32( L_tmp, L_mssnr ) ) + Word16 L_tmp_e; + L_tmp1 = Mult_32_16( L_mssnr, 25231 ); /* Q13+Q15+1-16 --> L_mssnr_e */ + L_tmp = Mult_32_16( BASOP_Util_Add_Mant32Exp( L_msnr18, L_msnr18_e, L_msnr19, L_msnr19_e, &L_tmp_e ), 18924 ); /* Q(31-L_tmp1_e)+Q(15-2)+1-16 -->exp= L_msnr_e +2*/ + L_tmp = BASOP_Util_Add_Mant32Exp( L_tmp1, L_mssnr_e, L_tmp, add( L_tmp_e, 2 ), &L_tmp_e ); + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_tmp, L_tmp_e, L_mssnr, L_mssnr_e ), 1 ) ) { L_mssnr = L_tmp; + L_mssnr_e = L_tmp_e; + move32(); + move16(); } } ELSE IF( ( snr_idx != 0 ) && GT_16( nb_sig_snr, 13 ) ) @@ -2492,9 +2522,9 @@ Word16 wb_vad_ivas_fx( L_tmp = -126976; move32(); /* -15.5 Q13 */ L_tmp = L_mac0( L_tmp, 80, lp_snr ); /* 2.5f(Q5)*lp_snr(Q8) - 15.5f */ - if ( L_tmp > 0 ) /* 2.5f*lp_snr - 15.5f > 0 */ + IF( L_tmp > 0 ) /* 2.5f*lp_snr - 15.5f > 0 */ { - L_mssnr = L_add( L_mssnr, L_tmp ); /* mssnr += 2.5f*lp_snr - 15.5f; */ + L_mssnr = BASOP_Util_Add_Mant32Exp( L_mssnr, L_mssnr_e, L_tmp, 18, &L_mssnr_e ); /* mssnr += 2.5f*lp_snr - 15.5f; */ } } @@ -2683,7 +2713,7 @@ Word16 wb_vad_ivas_fx( flag_he1 = 0; move16(); - IF( GT_32( L_mssnr, L_vad_thr ) ) + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_mssnr, L_mssnr_e, L_vad_thr, 18 ), 1 ) ) { flag_he1 = 1; move16(); /* he1 primary decision */ @@ -2745,7 +2775,7 @@ Word16 wb_vad_ivas_fx( test(); IF( flag_he1 == 0 && hVAD->soft_hangover > 0 ) { - IF( GT_32( L_mssnr_hov, L_vad_thr ) ) + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( L_mssnr_hov, L_mssnr_hov_e, L_vad_thr, 18 ), 1 ) ) { flag_he1 = 1; move16(); @@ -2877,9 +2907,10 @@ Word16 wb_vad_ivas_fx( hVAD->nb_active_frames = 0; move16(); - if ( LT_16( hVAD->hangover_cnt, HANGOVER_LONG_FX ) ) /* inside HO period */ + IF( LT_16( hVAD->hangover_cnt, HANGOVER_LONG_FX ) ) /* inside HO period */ { hVAD->hangover_cnt = add( hVAD->hangover_cnt, 1 ); + move16(); } -- GitLab From b9e7c3a6185422d4c9adb263e01a94e33e0ddd80 Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sat, 28 Sep 2024 12:29:13 +0530 Subject: [PATCH 2/2] Fixes for crashes in +10dB and -10dB scaled inputs --- lib_com/prot_fx.h | 2 ++ lib_enc/ivas_core_enc.c | 21 +++++++++++++++------ lib_enc/swb_pre_proc.c | 14 +++++++++++++- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 18d1b9266..3ae3a0436 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -10535,6 +10535,8 @@ void swb_pre_proc_ivas_fx( Word16 *new_swb_speech, /* o : original input signal at 32kHz - Q0 */ Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz - Q - q_reImBuffer */ Word16 *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz- Q0 */ + Word32 *shb_speech_32, /* o : SHB target signal (6-14kHz) at 16kHz- Q - q_reImBuffer */ + Word16 *use_shb32, /* o : flags valid data in 32-bit shb buffer for better precision. */ Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer Q - q_reImbuffer */ Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer Q - q_reImbuffer */ Word16 q_reImBuffer, /* i : scale data of real and imag CLDFB buffers */ diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index a77a88a33..5e0c00753 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -90,8 +90,8 @@ ivas_error ivas_core_enc( STEREO_ICBWE_ENC_HANDLE hStereoICBWE; STEREO_TD_ENC_DATA_HANDLE hStereoTD; float *inp[CPE_CHANNELS]; - float new_inp_resamp16k[CPE_CHANNELS][L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ - float old_syn_12k8_16k[CPE_CHANNELS][L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + float new_inp_resamp16k[CPE_CHANNELS][L_FRAME16k]; /* new input signal @16kHz, non pre-emphasised, used by the WB TBE/BWE */ + float old_syn_12k8_16k[CPE_CHANNELS][L_FRAME16k] = { { 0 } }; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ float shb_speech[L_FRAME16k]; float hb_speech[L_FRAME16k / 4]; float *new_swb_speech; @@ -105,7 +105,8 @@ ivas_error ivas_core_enc( #endif #ifdef IVAS_FLOAT_FIXED Word32 *new_swb_speech_fx; - Word16 shb_speech_fx[L_FRAME16k]; // Q_shb_spch + Word16 shb_speech_fx[L_FRAME16k]; // Q_shb_spch + Word32 shb_speech_fx_32[L_FRAME16k]; // Q_shb_spch Word16 Q_shb_spch; Word32 new_swb_speech_buffer_fx[L_FRAME48k + STEREO_DFT_OVL_MAX]; Word16 new_inp_resamp16k_fx[CPE_CHANNELS][L_FRAME16k]; @@ -847,6 +848,7 @@ ivas_error ivas_core_enc( Word32 realBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word32 imagBuffer_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; Word16 new_swb_speech_16_fx[L_FRAME48k] = { 0 }; + Word16 use_shb32 = 0; Word16 q_realImagBuffer = Q_factor_arrL( (float *) &realBuffer[n][0][0], CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); q_realImagBuffer = s_min( q_realImagBuffer, Q_factor_arrL( (float *) &imagBuffer[n][0][0], CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ) ); floatToFixed_arrL32( (float *) &realBuffer[n][0][0], (Word32 *) &realBuffer_fx[0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); @@ -858,7 +860,7 @@ ivas_error ivas_core_enc( #else for ( Word32 idx = 0; idx < ( L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); idx++ ) { - st->hSignalBuf->input_buff[idx] = (Word16) st->hSignalBuf->input_buff_flt[0]; + st->hSignalBuf->input_buff[idx] = (Word16) st->hSignalBuf->input_buff_flt[idx]; } #endif if ( st->element_mode == IVAS_CPE_DFT ) @@ -895,7 +897,7 @@ ivas_error ivas_core_enc( } #endif #endif - swb_pre_proc_ivas_fx( st, new_swb_speech_16_fx, new_swb_speech_fx, shb_speech_fx, realBuffer_fx, imagBuffer_fx, q_realImagBuffer, hCPE ); + swb_pre_proc_ivas_fx( st, new_swb_speech_16_fx, new_swb_speech_fx, shb_speech_fx, shb_speech_fx_32, &use_shb32, realBuffer_fx, imagBuffer_fx, q_realImagBuffer, hCPE ); #ifdef IVAS_FLOAT_FIXED_CONVERSIONS fixedToFloat_arr( (Word16 *) &st->hBWE_TD->old_speech_shb_fx[0], (float *) &st->hBWE_TD->old_speech_shb[0], 0, L_LOOK_16k + L_SUBFR16k ); fixedToFloat_arr( (Word16 *) &st->hBWE_FD->old_fdbwe_speech_fx[0], (float *) &st->hBWE_FD->old_fdbwe_speech[0], 0, L_FRAME48k ); @@ -906,7 +908,14 @@ ivas_error ivas_core_enc( } fixedToFloat_arrL32( (Word32 *) &st->cldfbSynTd->cldfb_state_fx[0], (float *) &st->cldfbSynTd->cldfb_state[0], q_realImagBuffer, st->cldfbSynTd->p_filter_length ); fixedToFloat_arr( new_swb_speech_16_fx, new_swb_speech, 0, L_FRAME48k ); - fixedToFloat_arr( shb_speech_fx, shb_speech, 0, L_FRAME16k ); + if ( use_shb32 == 0 ) + { + fixedToFloat_arr( shb_speech_fx, shb_speech, 0, L_FRAME16k ); + } + else + { + fixedToFloat_arrL( shb_speech_fx_32, shb_speech, q_realImagBuffer - 1, L_FRAME16k ); + } fixedToFloat_arrL32( (Word32 *) &realBuffer_fx[0][0], (float *) &realBuffer[n][0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); fixedToFloat_arrL32( (Word32 *) &imagBuffer_fx[0][0], (float *) &imagBuffer[n][0][0], q_realImagBuffer, CLDFB_NO_COL_MAX * CLDFB_NO_CHANNELS_MAX ); st->hBWE_TD->cldfbHBLT_flt = fix16_to_float( st->hBWE_TD->cldfbHBLT, Q13 ); diff --git a/lib_enc/swb_pre_proc.c b/lib_enc/swb_pre_proc.c index 4e0997aa4..d0031ba47 100644 --- a/lib_enc/swb_pre_proc.c +++ b/lib_enc/swb_pre_proc.c @@ -282,6 +282,8 @@ void swb_pre_proc_ivas_fx( Word16 *new_swb_speech, /* o : original input signal at 32kHz - Q0 */ Word32 *new_swb_speech_fx, /* o : original input signal at 32kHz - Q - q_reImBuffer */ Word16 *shb_speech, /* o : SHB target signal (6-14kHz) at 16kHz- Q0 */ + Word32 *shb_speech_32, /* o : SHB target signal (6-14kHz) at 16kHz- Q - q_reImBuffer */ + Word16 *use_shb32, /* o : flags valid data in 32-bit shb buffer for better precision. */ Word32 realBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : real buffer Q - q_reImbuffer */ Word32 imagBuffer[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX], /* i : imag buffer Q - q_reImbuffer */ Word16 q_reImBuffer, /* i : scale data of real and imag CLDFB buffers */ @@ -308,9 +310,11 @@ void swb_pre_proc_ivas_fx( Word32 lbEner; Word16 exp_lbEner = 0; Word16 Sample_Delay_SWB_BWE32k, lMemRecalc32k, dft_ovl32k; - Word32 shb_speech_32[L_FRAME16k]; Word32 one_by_50_Q31 = 42949673; + *use_shb32 = 0; + move16(); + lMemRecalc32k = NS2SA_FX2( 32000, L_MEM_RECALC_NS ); move16(); // exp_lbEner move16(); // lMemRecalc32k @@ -783,6 +787,8 @@ void swb_pre_proc_ivas_fx( // Copy_Scale_sig_16_32((const Word16 *)&shb_speech[0], (Word32 *)&shb_speech_32[0], L_FRAME16k,Q16); cldfbSynthesis_ivas_fx( realBufferFlipped, imagBufferFlipped, shb_speech_32, -1, st->cldfbSynTd ); + *use_shb32 = 1; + move16(); Copy_Scale_sig_32_16( (const Word32 *) &shb_speech_32[0], (Word16 *) &shb_speech[0], L_FRAME16k, negate( sub( q_reImBuffer, 1 ) ) ); } @@ -888,6 +894,8 @@ void swb_pre_proc_ivas_fx( IF( ( EQ_16( st->bwidth, FB ) || st->core == ACELP_CORE ) && ( st->element_mode == EVS_MONO ) ) { InitSWBencBufferStates_fx( st->hBWE_TD, shb_speech ); + *use_shb32 = 0; + move16(); } ELSE { @@ -932,6 +940,8 @@ void swb_pre_proc_ivas_fx( } Decimate_allpass_steep_fx( spchTmp, hBWE_TD->state_ana_filt_shb_fx, L_FRAME32k, shb_speech ); + *use_shb32 = 0; + move16(); Copy( shb_speech + L_FRAME16k - ( L_LOOK_16k + L_SUBFR16k ), hBWE_TD->old_speech_shb_fx, L_LOOK_16k + L_SUBFR16k ); @@ -971,6 +981,8 @@ void swb_pre_proc_ivas_fx( shb_speech[i] = mult_r( mult_r( i, 983 /*0.03f Q15*/ ), shb_speech[2 * delay - 1 - i] ); move16(); } + *use_shb32 = 0; + move16(); } return; -- GitLab