From ca5c58bb1eaec85cbb0926851cc422b6fe0e144c Mon Sep 17 00:00:00 2001 From: Sandesh Venkatesh Date: Sat, 28 Sep 2024 22:40:12 +0530 Subject: [PATCH] Core encoder and CPE function/sub-functions conversion/integration [x] core_enc functions converted/integrated: lsf_syn_mem_restore, ProcessIGF_ivas_fx, fb_tbe_enc_ivas_fx, fd_cng_enc, preemph calls in ivas_compute_core_buffer [x] CPE enc path functions converted/integrated: stereo_classifier, hp_20_fix32, tdm_ol_pitch_comparison, map_input_to_cpe_channels_ivas_fx, stereo_fd_cng_coherence, stereo_td_itd_mdct_stereo, stereo_tca_enc sub-functions --- lib_com/igf_base_fx.c | 2 +- lib_com/ivas_cnst.h | 1 + lib_com/ivas_prot.h | 53 +- lib_com/ivas_prot_fx.h | 102 ++ lib_com/ivas_rom_com_fx.c | 8 + lib_com/ivas_rom_com_fx.h | 4 +- lib_com/lsf_tools_fx.c | 80 + lib_com/prot.h | 2 +- lib_com/prot_fx.h | 37 +- lib_com/swb_tbe_com_fx.c | 4 +- lib_enc/acelp_core_enc.c | 64 +- lib_enc/fd_cng_enc.c | 338 +++- lib_enc/fd_cng_enc_fx.c | 2 + lib_enc/igf_enc.c | 10 +- lib_enc/igf_enc_fx.c | 50 +- lib_enc/init_enc.c | 6 + lib_enc/ivas_core_enc.c | 31 + lib_enc/ivas_core_pre_proc.c | 137 +- lib_enc/ivas_core_pre_proc_front.c | 271 ++- lib_enc/ivas_corecoder_enc_reconfig.c | 10 +- lib_enc/ivas_cpe_enc.c | 190 ++- lib_enc/ivas_enc.c | 8 +- lib_enc/ivas_ism_enc.c | 7 +- lib_enc/ivas_ism_metadata_enc.c | 6 +- lib_enc/ivas_mct_core_enc.c | 151 +- lib_enc/ivas_mct_enc.c | 124 +- lib_enc/ivas_mct_enc_mct.c | 289 ++++ lib_enc/ivas_sce_enc.c | 26 +- lib_enc/ivas_stat_enc.h | 38 +- lib_enc/ivas_stereo_classifier.c | 414 ++++- lib_enc/ivas_stereo_dft_enc.c | 9 +- lib_enc/ivas_stereo_dft_enc_itd.c | 9 +- lib_enc/ivas_stereo_dft_td_itd.c | 59 + lib_enc/ivas_stereo_ica_enc.c | 2221 +++++++++++++++++++++---- lib_enc/ivas_stereo_mdct_core_enc.c | 282 ++++ lib_enc/ivas_stereo_td_analysis.c | 103 +- lib_enc/ivas_stereo_td_enc.c | 349 +++- lib_enc/ivas_tcx_core_enc.c | 12 +- lib_enc/nois_est.c | 4 + lib_enc/pre_proc.c | 44 + lib_enc/prot_fx_enc.h | 21 +- lib_enc/speech_music_classif.c | 16 +- lib_enc/stat_enc.h | 26 +- lib_enc/swb_tbe_enc_fx.c | 162 ++ lib_enc/tcx_utils_enc.c | 130 +- lib_enc/transient_detection_fx.c | 1 + 46 files changed, 5315 insertions(+), 598 deletions(-) diff --git a/lib_com/igf_base_fx.c b/lib_com/igf_base_fx.c index 6b7b31be7..b087695b5 100644 --- a/lib_com/igf_base_fx.c +++ b/lib_com/igf_base_fx.c @@ -893,7 +893,7 @@ static void IGF_gridSetUp_ivas_fx( Word16 bitRateIndex, /* i : IGF bitrate index */ const Word32 sampleRate, /* i : sample rate */ Word16 frameLength, /* i : frame length */ - const Word16 transFac, /* i : transFac */ + const Word16 transFac, /* i : transFac, Q14 */ const Word16 igfMinFq /* i : IGF minimum frequency indicating lower start frequency for copy up */ ) { diff --git a/lib_com/ivas_cnst.h b/lib_com/ivas_cnst.h index 861e7517a..4cda51198 100644 --- a/lib_com/ivas_cnst.h +++ b/lib_com/ivas_cnst.h @@ -840,6 +840,7 @@ enum fea_names #define MAX_DELAYREGLEN 12 /* max regression length */ #define INV_MAX_DELAYREGLEN 0.083333333333333f /* (1/MAX_DELAYREGLEN) */ +#define INV_MAX_DELAYREGLEN_FX_Q15 2731 /* (1/MAX_DELAYREGLEN) */ #define MAX_INTERPOLATE 11 #define ADDED_MEM_DS 40 diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index f65fca8e8..a7883abe5 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -1768,19 +1768,6 @@ void stereo_dft_enc_analyze( float *input_mem[CPE_CHANNELS] /* i/o: input buffer memory */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_dft_enc_analyze_fx( - Encoder_State **sts, /* i/o: encoder state structure */ - const Word16 n_channels, /* i : number of input channels */ - const Word16 input_frame, /* i : input frame length */ - STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ - STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ - Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ - Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ - Word16 *q_input_mem - ); -#endif - float stereo_dft_enc_synthesize( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder DFT stereo handle */ float *output, /* o : output synthesis */ @@ -2285,22 +2272,6 @@ void stereo_dft_hybrid_ITD_flag( const Word16 hybrid_itd_max /* i : flag for hybrid ITD for very large ITDs */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_dft_enc_compute_itd_fx( - CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - Word32 *DFT_L, - Word16 *DFT_L_e, - Word32 *DFT_R, - Word16 *DFT_R_e, - const Word16 k_offset, - const Word16 input_frame, - const Word16 vad_flag_dtx[], - const Word16 vad_hover_flag[], - Word32 *bin_nrgL, - Word16 *bin_nrgL_e, - Word32 *bin_nrgR, - Word16 *bin_nrgR_e ); -#endif void stereo_dft_enc_compute_itd( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ float *DFT_L, @@ -2337,32 +2308,10 @@ void stereo_td_itd( float *input_mem[CPE_CHANNELS] /* i/o: input buffer memory */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_td_itd_fx( - ITD_DATA *hITD, /* i/o: ITD data structure */ - Word16 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX], /* o : ITD memory (only used in DFT Stereo) */ - Word16 *q_input_mem_itd, - const Word16 hybrid_itd_flag, /* i : flag for hybrid TD/FD ITD processing */ - const Word16 dft_ovl, /* i : size of DFT overlap */ - Encoder_State **sts, /* i/o: Encoder state structure */ - const Word16 input_frame, /* i : input frame length */ - Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ - Word16 *q_input_mem -); -#endif - void stereo_dft_dmx_out_reset( STEREO_DFT_DMX_DATA_HANDLE hStereoDftDmx /* i/o: DFT stereo DMX decoder */ ); -#ifdef IVAS_FLOAT_FIXED -void stereo_dft_unify_dmx_fx( - STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */ - Decoder_State *st0, /* i/o: decoder state structure */ - Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */ - Word32 *input_mem, /* i/o: mem of buffer DFT analysis */ - const Word16 prev_sid_nodata /* i : Previous SID/No data indicator */ -); -#endif + void stereo_dft_unify_dmx( STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */ Decoder_State *st0, /* i/o: decoder state structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index a30457c37..f71479f81 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -932,6 +932,17 @@ ivas_error ivas_ism_config_fx( const Word16 combined_format_flag /* i : flag indicating combined format */ ); +void stereo_dft_enc_analyze_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + const Word16 n_channels, /* i : number of input channels */ + const Word16 input_frame, /* i : input frame length */ + STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ + Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ + Word16 DFT_e[CPE_CHANNELS], /* o : DFT buffers */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem ); + Word16 IGF_MapBitRateToIndex( const Word32 brate, /* i : bitrate */ const Word16 bwidth, /* i : audio bandwidth */ @@ -954,6 +965,47 @@ void stereo_dft_config_fx( Word16 *bits_frame_nominal_2 /* o : secondary channel nominal bits per frame*/ ); +void stereo_td_itd_mdct_stereo_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ + const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : frame length */ +); + +void stereo_td_itd_fx( + ITD_DATA *hITD, /* i/o: ITD data structure */ + Word16 input_mem_itd_fx[CPE_CHANNELS][STEREO_DFT_OVL_MAX], /* o : ITD memory (only used in DFT Stereo) */ + Word16 *q_input_mem_itd, + const Word16 hybrid_itd_flag, /* i : flag for hybrid TD/FD ITD processing */ + const Word16 dft_ovl, /* i : size of DFT overlap */ + Encoder_State **sts, /* i/o: Encoder state structure */ + const Word16 input_frame, /* i : input frame length */ + Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ + Word16 *q_input_mem ); + +void stereo_dft_unify_dmx_fx( + STEREO_DFT_DEC_DATA_HANDLE hStereoDft, /* i/o: decoder stereo handle */ + Decoder_State *st0, /* i/o: decoder state structure */ + Word32 DFT[CPE_CHANNELS][STEREO_DFT_BUF_MAX], /* i/o: DFT buffers */ + Word32 *input_mem, /* i/o: mem of buffer DFT analysis */ + const Word16 prev_sid_nodata /* i : Previous SID/No data indicator */ +); + +void stereo_dft_enc_compute_itd_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ + Word32 *DFT_L, + Word16 *DFT_L_e, + Word32 *DFT_R, + Word16 *DFT_R_e, + const Word16 k_offset, + const Word16 input_frame, + const Word16 vad_flag_dtx[], + const Word16 vad_hover_flag[], + Word32 *bin_nrgL, + Word16 *bin_nrgL_e, + Word32 *bin_nrgR, + Word16 *bin_nrgR_e ); + Word16 stereo_dft_band_config_fx( Word16 *band_limits, /* o : DFT band limits */ const Word16 band_res, /* i : DFT band resolution */ @@ -1769,6 +1821,24 @@ void ivas_interpolate_3_over_1_allpass_fx( Word16 *mem_fx /* i/o: memory */ /* Q_input */ ); +void tdm_configure_enc_fx( + const Word16 ivas_format, /* i : IVAS format */ + const Word16 ism_mode, /* i : ISM mode in combined format */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word16 Etot_last_fx[CPE_CHANNELS], /* i/o: Energy of last frame Q8*/ + const Word16 tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ + const Word16 tdm_ratio_idx, /* i : ratio index */ + const Word16 tdm_ratio_idx_SM, /* i : ratio index in SM mode */ + const Word16 attack_flag, /* i : Primary channel attack flag */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +); + +void stereoFdCngCoherence_fx( + Encoder_State **sts, /* i/o: core encoder structures */ + const Word16 last_element_mode, /* i : last element mode */ + Word16 fft_buff[CPE_CHANNELS][2 * L_FFT], /* i : fft buffers for L and R channels fft_exp*/ + Word16 fft_exp ); + void ivas_wb_tbe_dec_fx( Decoder_State *st_fx, /* i/o: decoder state structure */ const Word16 coder_type, /* i : coding type */ @@ -2805,6 +2875,13 @@ void spectral_balancer_fx16( const Word16 coeff_set /* i : coefficient set */ ); +void spectral_balancer_fx( + Word32 *signal, /* i/o : signal Qx */ + Word32 *mem, /* i/o : mem Qx */ + const Word16 lg, /* i : input signal length */ + const Word16 coeff_set /* i : coefficient set */ +); + void stereo_icBWE_preproc_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ const Word16 input_frame, /* i : input frame length */ @@ -2941,4 +3018,29 @@ void ivas_smc_mode_selection_fx( const Word16 flag_spitch /* i : flag to indicate very short stable pitch*/ ); +void stereo_classifier_features_ivas_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const Word16 idchan, /* i : channel ID */ + const Word16 element_mode, /* i : element mode */ + const Word16 vad_flag, /* i : VAD flag */ + Word32 lsf_new_fx[], /* i : LSFs at the end of the frame */ + Word32 epsP_fx[], /* i : LP analysis residual energies for each iteration*/ + Word16 pitch[], /*q0 i : open-loop pitch values for quantiz. */ + Word16 voicing_fx[], /* i : OL maximum normalized correlation */ + Word32 cor_map_sum_fx, /* i : speech/music clasif. parameter */ + Word32 non_staX_fx, /* i : unbound non-stationarity for sp/mu clas. */ + Word32 sp_div_fx, /* i : spectral diversity feature */ + const Word16 clas, /* i : signal class */ + Word16 epsP_e, /*exponent for epsP_fx */ + Word16 voicing_e, /*exponent for voicing_fx */ + Word16 cor_map_sum_e, /*exponent for cor_map_sum_fx */ + Word16 non_staX_e, /*exponent for non_staX_fx */ + Word16 sp_div_e /*exponent for sp_div_fx */ +); + +void tdm_ol_pitch_comparison_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word16 pitch_fr[CPE_CHANNELS][NB_SUBFR], /* i/o: fractional pitch values, Q6 */ + Word16 voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains, Q15 */ +); #endif diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index 84b0e906d..86f6fdadf 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -1275,6 +1275,14 @@ const Word32 ica_sincInterp2_fx[2 * SINC_ORDER1 + 1] = { -4988604, 0 }; +const Word32 ica_sincInterp4_fx[2 * SINC_ORDER1 + 1] = { + 0, -7054484, -11890617, -10587094, 0, 17813376, 32618130, 29564408, 0, -46911780, -82209968, -71380208, 0, 105465072, 180201792, 153819952, 0, -226492960, -394310208, -349923872, 0, 621904832, 1345701248, 1925805312, 2147483647, 1925805312, 1345701248, 621904832, 0, -349923872, -394310208, -226492960, 0, 153819952, 180201792, 105465072, 0, -71380208, -82209968, -46911780, 0, 29564408, 32618130, 17813376, 0, -10587094, -11890617, -7054484, 0 +}; + +const Word32 ica_sincInterp6_fx[2 * SINC_ORDER1 + 1] = { + 0, -7481833, -15444702, -22462678, -25151328, -18893562, 0, 31359704, 68816112, 99516536, 106796512, 75709536, 0, -111862424, -234090752, -326303712, -341870816, -240232560, 0, 371151744, 833251584, 1319259392, 1748116096, 2042624128, 2147483647, 2042624128, 1748116096, 1319259392, 833251584, 371151744, 0, -240232560, -341870816, -326303712, -234090752, -111862424, 0, 75709536, 106796512, 99516536, 68816112, 31359704, 0, -18893562, -25151328, -22462678, -15444702, -7481833, 0 +}; + /*----------------------------------------------------------------------------------* * Stereo IC-BWE ROM tables *----------------------------------------------------------------------------------*/ diff --git a/lib_com/ivas_rom_com_fx.h b/lib_com/ivas_rom_com_fx.h index 6692f0afd..0e0714bea 100644 --- a/lib_com/ivas_rom_com_fx.h +++ b/lib_com/ivas_rom_com_fx.h @@ -92,7 +92,9 @@ extern const Word16 ivas_tan_panning_gain_dirac_tbl_fx[601]; * Stereo ICA ROM tables *----------------------------------------------------------------------------------*/ -extern const Word32 ica_sincInterp2_fx[]; +extern const Word32 ica_sincInterp2_fx[]; // Q31 +extern const Word32 ica_sincInterp4_fx[]; // Q31 +extern const Word32 ica_sincInterp6_fx[]; // Q31 /*----------------------------------------------------------------------------------* * Stereo IC-BWE ROM tables diff --git a/lib_com/lsf_tools_fx.c b/lib_com/lsf_tools_fx.c index dd395cba7..143821c93 100644 --- a/lib_com/lsf_tools_fx.c +++ b/lib_com/lsf_tools_fx.c @@ -3119,6 +3119,86 @@ void lsf_syn_mem_restore_fx( return; } +#ifdef IVAS_FLOAT_FIXED +void lsf_syn_mem_restore_ivas_fx( + Encoder_State *st_fx, /* o: state structure */ + Word16 btilt_code_fx, /* i: */ + Word32 gc_threshold_fx, /* i: */ + Word16 *clip_var_bck_fx, /* i: */ + Word16 next_force_sf_bck_fx, /* i: */ + Word16 *lsp_new, /* o: LSP vector to quantize */ + Word16 *lsp_mid, /* o: mid-frame LSP vector */ + Word16 clip_var, /* i: pitch clipping state var */ + Word16 *mem_AR, /* i: quantizer memory for AR model */ + Word16 *mem_MA, /* i: quantizer memory for MA model */ + Word16 *lsp_new_bck, /* i: LSP vector to quantize- backup */ + Word16 *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + Word32 *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + Word32 *Bin_E_old, /* i: FFT Bin energy 128 sets */ + Word16 *mem_syn_bck, /* i: synthesis filter memory */ + Word16 mem_w0_bck, /* i: memory of the weighting filter */ + Word16 streaklimit, /* i:LSF quantizer */ + Word16 pstreaklen /* i:LSF quantizer */ +) +{ + Word16 i; + LPD_state_HANDLE hLPDmem = st_fx->hLPDmem; + + /* restore lsf memories */ + st_fx->clip_var_fx[0] = clip_var; + move16(); + + FOR( i = 0; i < M; i++ ) + { + st_fx->mem_AR_fx[i] = mem_AR[i]; + move16(); + st_fx->mem_MA_fx[i] = mem_MA[i]; + move16(); + lsp_new[i] = lsp_new_bck[i]; + move16(); + lsp_mid[i] = lsp_mid_bck[i]; + move16(); + } + + st_fx->streaklimit_fx = streaklimit; + move16(); + st_fx->pstreaklen = pstreaklen; + move16(); + + FOR( i = 0; i < L_FFT; i++ ) + { + st_fx->Bin_E_fx[i] = Bin_E[i]; + move16(); + } + + FOR( i = 0; i < ( L_FFT / 2 ); i++ ) + { + st_fx->Bin_E_old_fx[i] = Bin_E_old[i]; + move32(); + } + + /* restoring memories */ + hLPDmem->mem_w0 = mem_w0_bck; + move16(); + + FOR( i = 0; i < M; i++ ) + { + hLPDmem->mem_syn[i] = mem_syn_bck[i]; + move16(); + } + + move16(); + hLPDmem->tilt_code = btilt_code_fx; + move32(); + hLPDmem->gc_threshold = gc_threshold_fx; + Copy( clip_var_bck_fx, st_fx->clip_var_fx, 6 ); + st_fx->next_force_safety_net = next_force_sf_bck_fx; + move16(); + + return; +} +#endif + /* Returns: codebook index */ Word16 tcxlpc_get_cdk( Word16 acelp_ext_mode /* (I) GC/VC indicator */ diff --git a/lib_com/prot.h b/lib_com/prot.h index c64a09f87..48761b078 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -10025,7 +10025,7 @@ void IGFEncApplyMono( float *pMDCTSpectrum, /* i/o: MDCT spectrum */ float *pPowerSpectrum, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ 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 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 */ ); diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 3ae3a0436..d6fedf92c 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -872,6 +872,29 @@ void lsf_syn_mem_restore_fx( Word16 pstreaklen /* i:LSF quantizer */ ); +#ifdef IVAS_FLOAT_FIXED +void lsf_syn_mem_restore_ivas_fx( + Encoder_State *st_fx, /* o: state structure */ + Word16 btilt_code_fx, /* i: */ + Word32 gc_threshold_fx, /* i: */ + Word16 *clip_var_bck_fx, /* i: */ + Word16 next_force_sf_bck_fx, /* i: */ + Word16 *lsp_new, /* o: LSP vector to quantize */ + Word16 *lsp_mid, /* o: mid-frame LSP vector */ + Word16 clip_var, /* i: pitch clipping state var */ + Word16 *mem_AR, /* i: quantizer memory for AR model */ + Word16 *mem_MA, /* i: quantizer memory for MA model */ + Word16 *lsp_new_bck, /* i: LSP vector to quantize- backup */ + Word16 *lsp_mid_bck, /* i: mid-frame LSP vector - backup */ + Word32 *Bin_E, /* i: FFT Bin energy 128 *2 sets */ + Word32 *Bin_E_old, /* i: FFT Bin energy 128 sets */ + Word16 *mem_syn_bck, /* i: synthesis filter memory */ + Word16 mem_w0_bck, /* i: memory of the weighting filter */ + Word16 streaklimit, /* i:LSF quantizer */ + Word16 pstreaklen /* i:LSF quantizer */ +); +#endif + void lsf_update_memory( Word16 narrowband, /* i : narrowband flag */ const Word16 qisf[], /* i : quantized xSF coefficients */ @@ -2994,10 +3017,10 @@ void interp_code_4over2_fx( void wb_tbe_extras_reset_synth_fx( Word16 state_lsyn_filt_shb[], Word16 state_lsyn_filt_dwn_shb[], Word16 state_32and48k_WB_upsample[], Word16 state_resamp_HB[] ); void elliptic_bpf_48k_generic_fx( - const Word16 input_fx[], /* i : i signal */ + const Word16 input_fx[], /* i : i signal Q_input_fx */ Word16 *Q_input_fx, Word16 output_fx[], /* o : output signal */ - Word32 memory_fx[][4], /* i/o: 4 arrays of 4 for memory */ + Word32 memory_fx[][4], /* i/o: 4 arrays of 4 for memory memory_fx_Q */ Word16 memory_fx_Q[], const Word16 full_band_bpf[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 Q13 */ ); @@ -10881,4 +10904,14 @@ void FEC_encode_ivas_fx( const Word32 total_brate, /* i : total codec bitrate */ const Word16 Q_synth /* i : input scaling */ ); + +ivas_error IGF_Reconfig_fx( + IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word16 igf, /* i : IGF on/off */ + const Word16 reset, /* i : reset flag */ + const Word32 brate, /* i : bitrate for configuration */ + const Word16 bwidth, /* i : signal bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +); #endif diff --git a/lib_com/swb_tbe_com_fx.c b/lib_com/swb_tbe_com_fx.c index 2f66f11ca..6cd0d3302 100644 --- a/lib_com/swb_tbe_com_fx.c +++ b/lib_com/swb_tbe_com_fx.c @@ -5370,9 +5370,9 @@ void wb_tbe_extras_reset_synth_fx( *-------------------------------------------------------------------*/ void elliptic_bpf_48k_generic_fx( - const Word16 input_fx[], /* i : input signal */ + const Word16 input_fx[], /* i : input signal Q_input_fx*/ Word16 *Q_input_fx, - Word16 output_fx[], /* o : output signal */ + Word16 output_fx[], /* o : output signal memory_fx_Q */ Word32 memory_fx2[][4], /* i/o: 4 arrays of 4 for memory */ Word16 memory_fx_Q[], const Word16 full_band_bpf_fx[][5] /* i : filter coefficients b0,b1,b2,a0,a1,a2 Q13 */ diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index df1191160..ede6d9591 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -110,16 +110,12 @@ ivas_error acelp_core_enc( /* SC-VBR - back-up memories for LSF quantizer and synthesis filter */ Word16 pstreaklen; float mem_MA[M], mem_AR[M], Bin_E[L_FFT], Bin_E_old[L_FFT / 2], lsp_new_bck[M], lsp_mid_bck[M], mem_syn_bck[M]; - float clip_var, mem_w0_bck, streaklimit; float q_env[NUM_ENV_CNG]; Word16 sid_bw = -1; float exc3[L_FRAME16k]; float syn1[L_FRAME16k]; - float tilt_code_bck; - float gc_threshold_bck; - float clip_var_bck[6]; Word16 next_force_sf_bck; Word16 uc_two_stage_flag; Word16 position; @@ -335,13 +331,10 @@ ivas_error acelp_core_enc( /* SC-VBR temporary variables */ pstreaklen = 0; move16(); - clip_var = 0; clip_var_fx = 0; move16(); - mem_w0_bck = 0; mem_w0_bck_fx = 0; move16(); - streaklimit = 0; streaklimit_fx = 0; move16(); @@ -1020,14 +1013,6 @@ ivas_error acelp_core_enc( } #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; - 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 ); @@ -1036,7 +1021,6 @@ ivas_error acelp_core_enc( 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[ii] = (float) mem_AR_fx[ii] / 2.56f; @@ -1045,8 +1029,6 @@ ivas_error acelp_core_enc( fixedToFloat_arr( lsp_new_bck_fx, lsp_new_bck, Q15, M ); fixedToFloat_arr( lsp_mid_bck_fx, lsp_mid_bck, Q15, M ); me2f_buf_16( mem_syn_bck_fx, st->hLPDmem->e_mem_syn, mem_syn_bck, M ); - mem_w0_bck = me2f( mem_w0_bck_fx, st->hLPDmem->e_mem_syn ); - streaklimit = fixedToFloat( streaklimit_fx, Q15 ); fixedToFloat_arr( lsp_new_fx, lsp_new, 15, M ); fixedToFloat_arr( lsp_mid_fx, lsp_mid, 15, M ); for ( i = 0; i < M; i++ ) @@ -1149,8 +1131,46 @@ ivas_error acelp_core_enc( if ( st->hSC_VBR->bump_up ) /* PPP failed, bump up */ { /* restore memories of LSF quantizer and synthesis filter */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( lsp_new_bck, lsp_new_bck_fx, Q15, M ); + floatToFixed_arr( lsp_mid_bck, lsp_mid_bck_fx, Q15, M ); + q_comm_Bin = s_min( Q_factor_arrL( st->Bin_E_old, L_FFT / 2 ), Q_factor_arrL( st->Bin_E, L_FFT ) ); + floatToFixed_arrL( Bin_E, Bin_E_fx, q_comm_Bin, L_FFT ); + floatToFixed_arrL( Bin_E_old, Bin_E_old_fx, q_comm_Bin, L_FFT / 2 ); + Word16 mem_syn = Q_factor_arr( mem_syn_bck, M ); + floatToFixed_arr( mem_syn_bck, mem_syn_bck_fx, mem_syn, M ); + for ( i = 0; i < M; i++ ) + { + mem_AR_fx[i] = (Word16) ( mem_AR[i] * 2.56f ); + mem_MA_fx[i] = (Word16) ( mem_MA[i] * 2.56f ); + } +#endif + lsf_syn_mem_restore_ivas_fx( st, tilt_code_bck_fx, gc_threshold_bck_fx, clip_var_bck_fx, next_force_sf_bck, lsp_new_fx, lsp_mid_fx, clip_var_fx, mem_AR_fx, mem_MA_fx, lsp_new_bck_fx, lsp_mid_bck_fx, Bin_E_fx, Bin_E_old_fx, mem_syn_bck_fx, mem_w0_bck_fx, streaklimit_fx, pstreaklen ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->hLPDmem->tilt_code_flt = fix16_to_float( st->hLPDmem->tilt_code, Q15 ); + st->hLPDmem->gc_threshold_flt = fix_to_float( st->hLPDmem->gc_threshold, Q16 ); + st->clip_var[0] = 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 ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); + fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, q_comm_Bin, L_FFT ); + fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, q_comm_Bin, L_FFT / 2 ); + fixedToFloat_arr( st->hLPDmem->mem_syn, st->hLPDmem->mem_syn_flt, mem_syn, M ); + st->hLPDmem->mem_w0_flt = me2f( st->hLPDmem->mem_w0, st->hLPDmem->e_mem_syn ); + for ( i = 0; i < M; i++ ) + { + st->mem_AR[i] = (float) st->mem_AR_fx[i] / 2.56f; + st->mem_MA[i] = (float) st->mem_MA_fx[i] / 2.56f; + } +#endif +#else lsf_syn_mem_restore( st, tilt_code_bck, gc_threshold_bck, clip_var_bck, next_force_sf_bck, lsp_new, lsp_mid, clip_var, mem_AR, mem_MA, lsp_new_bck, lsp_mid_bck, Bin_E, Bin_E_old, mem_syn_bck, mem_w0_bck, streaklimit, pstreaklen ); - +#endif /* Configure ACELP bit allocation */ config_acelp1_IVAS( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, -1, &( st->acelp_cfg ), hBstr->nb_bits_tot, st->coder_type, tc_subfr, 0, &nb_bits, unbits, 0, &uc_two_stage_flag, 0, 0, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); @@ -1289,7 +1309,7 @@ ivas_error acelp_core_enc( Word16 q_syn = Q_factor_arr( syn, L_FRAME16k ); q_syn = min( q_syn, Q_factor_arr( res, L_FRAME16k ) ); floatToFixed_arr16( syn, syn_fx, q_syn, L_FRAME16k ); - floatToFixed_arr16( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); + floatToFixed_arr( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); floatToFixed_arr16( res, res_fx, q_syn, L_FRAME16k ); #endif FEC_encode_ivas_fx( hBstr, st->acelp_cfg, syn_fx, st->coder_type, st->clas, pitch_buf_fx, res_fx, &st->Last_pulse_pos, st->L_frame, st->total_brate, q_syn ); @@ -1347,7 +1367,7 @@ ivas_error acelp_core_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Word16 voice_factors_fx[NB_SUBFR16k]; - floatToFixed_arr16( voice_factors, voice_factors_fx, Q15, 5 ); + floatToFixed_arr( voice_factors, voice_factors_fx, Q15, 5 ); st->hBWE_TD->bwe_non_lin_prev_scale_fx = floatToFixed( st->hBWE_TD->bwe_non_lin_prev_scale, Q30 ); @@ -1389,7 +1409,7 @@ ivas_error acelp_core_enc( #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Word16 pitch_buf_fx[NB_SUBFR16k]; - floatToFixed_arr16( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); + floatToFixed_arr( pitch_buf, pitch_buf_fx, Q6, NB_SUBFR16k ); floatToFixed_arr16( st->old_pitch_buf, st->old_pitch_buf_fx, Q6, 2 * NB_SUBFR16k ); Es_pred_fx = float_to_fix16( Es_pred, Q8 ); diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index a9883f927..4dab9cca6 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -42,11 +42,16 @@ #include "rom_com.h" #include "prot.h" #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot.h" #include "ivas_prot_fx.h" #include "stat_enc.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx.h" +#endif + /*-------------------------------------------------------------------* * createFdCngEnc() * @@ -131,30 +136,41 @@ void initFdCngEnc( } /* Initialize the Noise Estimator */ + set_f( hFdCngEnc->msPeriodog, 0.0f, NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msAlpha, 0.0f, NPART ); set_f( hFdCngEnc->msBminWin, 0.0f, NPART ); set_f( hFdCngEnc->msBminSubWin, 0.0f, NPART ); set_f( hFdCngEnc->msPsd, 0.0f, NPART ); set_f( hFdCngEnc->msNoiseFloor, 0.0f, NPART ); +#endif set_f( hFdCngEnc->msNoiseEst, 0.0f, NPART ); set_f( hFdCngEnc->energy_ho, 0.0f, NPART ); set_f( hFdCngEnc->msNoiseEst_old, 0.0f, NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msMinBuf, FLT_MAX, MSNUMSUBFR * NPART ); set_f( hFdCngEnc->msCurrentMin, FLT_MAX, NPART ); set_f( hFdCngEnc->msCurrentMinOut, FLT_MAX, NPART ); set_f( hFdCngEnc->msCurrentMinSubWindow, FLT_MAX, NPART ); +#endif set_s( hFdCngEnc->msLocalMinFlag, 0, NPART ); set_s( hFdCngEnc->msNewMinFlag, 0, NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msPsdFirstMoment, 0.0f, NPART ); set_f( hFdCngEnc->msPsdSecondMoment, 0.0f, NPART ); +#endif hFdCngEnc->msPeriodogBufPtr = 0; + set_f( hFdCngEnc->msPeriodogBuf, 0.0f, MSBUFLEN * NPART ); +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled set_f( hFdCngEnc->msLogPeriodog, 0.0f, NPART ); set_f( hFdCngEnc->msLogNoiseEst, 0.0f, NPART ); +#endif +#ifndef IVAS_FLOAT_FIXED set_f( hFdCngEnc->mem_coherence, EPSILON, 4 ); - +#endif return; } @@ -492,12 +508,180 @@ void resetFdCngEnc( return; } - /*-------------------------------------------------------------------* * perform_noise_estimation_enc() * * Perform noise estimation *-------------------------------------------------------------------*/ +void perform_noise_estimation_enc_ivas_fx( + Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp, + Word32 *enerBuffer, + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables */ + const Word32 input_Fs, /* i : input sampling rate */ + CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ +) +{ + Word16 i, j, s, s1, s2; + Word16 numBands; + Word16 numCoreBands = hFdCngEnc->hFdCngCom->numCoreBands; + move16(); + Word16 regularStopBand = hFdCngEnc->hFdCngCom->regularStopBand; + move16(); + Word16 numSlots = hFdCngEnc->hFdCngCom->numSlots; + move16(); + assert( numSlots == 16 ); + + Word32 numSlots_inv_fx = 134217728; + move32(); + Word32 *periodog = hFdCngEnc->hFdCngCom->periodog; + Word32 *ptr_per_fx = periodog; + Word16 npart = hFdCngEnc->hFdCngCom->npart; + move16(); + Word16 nFFTpart = hFdCngEnc->hFdCngCom->nFFTpart; + move16(); + Word16 nCLDFBpart = hFdCngEnc->hFdCngCom->nCLDFBpart; + move16(); + + Word16 *psize = hFdCngEnc->hFdCngCom->psize; + Word32 *msPeriodog_fx = hFdCngEnc->msPeriodog_fx; + Word32 *msNoiseEst_fx = hFdCngEnc->msNoiseEst_fx; + + Word16 *msLogPeriodog_fx = hFdCngEnc->msLogPeriodog_fx; + Word16 *msLogNoiseEst_fx = hFdCngEnc->msLogNoiseEst_fx; + + Word32 scaleEB_fx = 0; + move32(); + Word32 tmp; + + test(); + IF( hCPE != NULL && hCPE->hStereoDft != NULL ) + { + // band_res_dft = ( (float) input_Fs ) / hCPE->hStereoDft->NFFT; + // chan_width_f = 24000.f / CLDFB_NO_CHANNELS_MAX; + // chan_width_bins = chan_width_f / band_res_dft; + + ///* Scaling of Energy buffer to get energy per sample, same scaling as for band_energies, 3 is to compensate for the 1/3 scaling in calculate_energy_buffer */ + // scaleEB = 3 * 4.0f / ( hCPE->hStereoDft->NFFT * hCPE->hStereoDft->NFFT ); + + ///* Scale with number of bins in one band */ + // scaleEB = scaleEB / chan_width_bins; + + SWITCH( input_Fs ) + { + case 8000: + scaleEB_fx = 62912; + move32(); + BREAK; + case 16000: + scaleEB_fx = 15728; + move32(); + BREAK; + case 32000: + scaleEB_fx = 3928; + move32(); + BREAK; + case 48000: + scaleEB_fx = 1744; + move32(); + BREAK; + default: + assert( 0 && "invalid sample rate" ); + } + } + ELSE + { + scaleEB_fx = Mpy_32_16_1( numSlots_inv_fx, hFdCngEnc->hFdCngCom->scalingFactor ); + scaleEB_fx = L_shl( scaleEB_fx, 4 ); + } + + /* preemphasis compensation and grouping of per bin energies into msPeriodog */ + FOR( i = 0; i < nFFTpart; i++ ) + { + tmp = L_add( L_shr( band_energies[i], 1 ), L_shr( band_energies[i + NB_BANDS], 1 ) ); + msPeriodog_fx[i] = Mpy_32_16_1( tmp, preemphCompensation_fx[i] ); + move32(); + } + + /* exponent for fft part of msPeriodog */ + hFdCngEnc->msPeriodog_fx_exp_fft = add( band_energies_exp, PREEMPH_COMPENSATION_EXP ); + move16(); + + /* Adjust to the desired time resolution by averaging the periodograms over the time slots */ + FOR( j = numCoreBands; j < regularStopBand; j++ ) + { + *ptr_per_fx = Mpy_32_32( enerBuffer[j], scaleEB_fx ); + move32(); + + ptr_per_fx++; + move16(); + } + + /* exponent for cldfb part of msPeriodog */ + hFdCngEnc->hFdCngCom->exp_cldfb_periodog = add( sub( enerBuffer_exp, 4 ), CLDFBscalingFactor_EXP ); + move16(); + + numBands = sub( regularStopBand, numCoreBands ); + + IF( numBands > 0 ) + { + ///* Adjust CLDFB filterbank to the desired frequency resolution by averaging over spectral partitions for SID transmission */ + bandcombinepow( + periodog, + hFdCngEnc->hFdCngCom->exp_cldfb_periodog, + numBands, + hFdCngEnc->hFdCngCom->CLDFBpart, + nCLDFBpart, + hFdCngEnc->hFdCngCom->CLDFBpsize_inv, + &msPeriodog_fx[nFFTpart], + &hFdCngEnc->msPeriodog_fx_exp_cldfb ); + + ///* find common exponent for fft part and cldfb part of msperiodog */ + s1 = getScaleFactor32( msPeriodog_fx, nFFTpart ); + s2 = getScaleFactor32( &msPeriodog_fx[nFFTpart], nCLDFBpart ); + + s = s_max( sub( hFdCngEnc->msPeriodog_fx_exp_fft, s1 ), sub( hFdCngEnc->msPeriodog_fx_exp_cldfb, s2 ) ); + s1 = sub( s, hFdCngEnc->msPeriodog_fx_exp_fft ); + s2 = sub( s, hFdCngEnc->msPeriodog_fx_exp_cldfb ); + + hFdCngEnc->msPeriodog_fx_exp_fft = s; + move16(); + hFdCngEnc->msPeriodog_fx_exp_cldfb = s; + move16(); + + FOR( i = 0; i < nFFTpart; i++ ) + { + msPeriodog_fx[i] = L_shr( msPeriodog_fx[i], s1 ); + move32(); + } + + FOR( i = 0; i < nCLDFBpart; i++ ) + { + msPeriodog_fx[nFFTpart + i] = L_shr( msPeriodog_fx[nFFTpart + i], s_min( 31, s2 ) ); + move32(); + } + } + /* exponent for entire msPeriodog vector */ + hFdCngEnc->msPeriodog_fx_exp = hFdCngEnc->msPeriodog_fx_exp_fft; + move16(); + + /* Compress MS inputs */ + // compress_range_flt( msPeriodog, msLogPeriodog, npart ); + compress_range( msPeriodog_fx, hFdCngEnc->msPeriodog_fx_exp, msLogPeriodog_fx, npart ); + + + /* Call the minimum statistics routine for noise estimation */ + + minimum_statistics_fx( npart, nFFTpart, psize, msLogPeriodog_fx, hFdCngEnc->msNoiseFloor_fx, msLogNoiseEst_fx, hFdCngEnc->msAlpha_fx, hFdCngEnc->msPsd_fx, hFdCngEnc->msPsdFirstMoment_fx, + hFdCngEnc->msPsdSecondMoment_fx, hFdCngEnc->msMinBuf_fx, hFdCngEnc->msBminWin_fx, hFdCngEnc->msBminSubWin_fx, hFdCngEnc->msCurrentMin_fx, hFdCngEnc->msCurrentMinOut_fx, hFdCngEnc->msCurrentMinSubWindow_fx, hFdCngEnc->msLocalMinFlag, hFdCngEnc->msNewMinFlag, hFdCngEnc->msPeriodogBuf_fx, &( hFdCngEnc->msPeriodogBufPtr ), hFdCngEnc->hFdCngCom, + ENC, ( hCPE == NULL ) ? 0 : hCPE->element_mode ); + + /* Expand MS outputs */ + expand_range( msLogNoiseEst_fx, msNoiseEst_fx, &hFdCngEnc->msNoiseEst_fx_exp, hFdCngEnc->hFdCngCom->npart ); + + return; +} void perform_noise_estimation_enc( float *band_energies, /* i : energy in critical bands without minimum noise floor E_MIN*/ @@ -577,7 +761,6 @@ void perform_noise_estimation_enc( return; } - /*-------------------------------------------------------------------* * AdjustFirstSID() * @@ -1058,7 +1241,142 @@ float cng_energy( * * compute coherence of channels for use in FD-CNG *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereoFdCngCoherence_fx( + Encoder_State **sts, /* i/o: core encoder structures */ + const Word16 last_element_mode, /* i : last element mode */ + Word16 fft_buf_fx[CPE_CHANNELS][2 * L_FFT], /* i : fft buffers for L and R channels fft_exp*/ + Word16 fft_exp ) +{ + const Word16 *pt_fftL, *pt_fftR; + Word16 i_subfr, i; + Word32 cr, ci, eL, eR; + Word16 cr_exp, ci_exp, eL_exp, eR_exp; + Word32 *mem; + Word16 *mem_exp; + + IF( NE_16( last_element_mode, IVAS_CPE_MDCT ) ) + { + set32_fx( sts[0]->hFdCngEnc->mem_coherence_fx, EPSILON_FX, 4 ); + set16_fx( sts[0]->hFdCngEnc->mem_coherence_exp, 0, 4 ); + } + test(); + test(); + IF( EQ_32( sts[0]->core_brate, -1 ) || EQ_32( sts[1]->core_brate, -1 ) ) + { + /* case: at least one channel has triggered VAD -> ACTIVE FRAME */ + IF( EQ_32( sts[0]->core_brate, -1 ) ) + { + sts[1]->total_brate = sts[0]->total_brate; + move32(); + sts[1]->active_cnt = sts[0]->active_cnt; + move16(); + if ( GE_32( sts[1]->active_cnt, CNG_TYPE_HO ) ) + { + sts[1]->last_total_brate_cng = -1; + move16(); + } + } + IF( EQ_32( sts[1]->core_brate, -1 ) ) + { + sts[0]->total_brate = sts[1]->total_brate; + move32(); + sts[0]->active_cnt = sts[1]->active_cnt; + move16(); + if ( GE_16( sts[0]->active_cnt, CNG_TYPE_HO ) ) + { + sts[0]->last_total_brate_cng = -1; + move16(); + } + } + sts[0]->core_brate = -1; + move32(); + sts[1]->core_brate = -1; + move32(); + sts[0]->hDtxEnc->cnt_SID = 0; + move16(); + sts[1]->hDtxEnc->cnt_SID = 0; + move16(); + } + ELSE IF( LE_32( sts[0]->core_brate, SID_2k40 ) && LE_32( sts[1]->core_brate, SID_2k40 ) ) + { + /* case: no VAD for both channels -> INACTIVE FRAME */ + reset_indices_enc( sts[0]->hBstr, sts[0]->hBstr->nb_ind_tot ); + reset_indices_enc( sts[1]->hBstr, sts[1]->hBstr->nb_ind_tot ); + + /* synchronize SID sending for variable SID rate */ + IF( EQ_32( sts[0]->core_brate, sts[1]->core_brate ) ) + { + sts[0]->core_brate = SID_2k40; + move32(); + sts[1]->core_brate = SID_2k40; + move32(); + } + + /* synchronize SID counters */ + sts[0]->hDtxEnc->cnt_SID = s_min( sts[0]->hDtxEnc->cnt_SID, sts[1]->hDtxEnc->cnt_SID ); + sts[1]->hDtxEnc->cnt_SID = sts[0]->hDtxEnc->cnt_SID; + move16(); + move16(); + } + + pt_fftL = fft_buf_fx[0]; + pt_fftR = fft_buf_fx[1]; + mem = sts[0]->hFdCngEnc->mem_coherence_fx; + mem_exp = sts[0]->hFdCngEnc->mem_coherence_exp; + FOR( i_subfr = 0; i_subfr < 2; i_subfr++ ) + { + cr = ci = eL = eR = EPSILON_FX; + move32(); + move32(); + move32(); + move32(); + cr_exp = ci_exp = eL_exp = eR_exp = 0; + move16(); + move16(); + move16(); + move16(); + + cr = BASOP_Util_Add_Mant32Exp( cr, cr_exp, L_add( L_mult( pt_fftL[0], pt_fftR[0] ), L_mult( pt_fftL[L_FFT / 2], pt_fftR[L_FFT / 2] ) ), shl( fft_exp, 1 ), &cr_exp ); + eL = BASOP_Util_Add_Mant32Exp( eL, eL_exp, L_add( L_mult( pt_fftL[0], pt_fftL[0] ), L_mult( pt_fftL[L_FFT / 2], pt_fftL[L_FFT / 2] ) ), shl( fft_exp, 1 ), &eL_exp ); + eR = BASOP_Util_Add_Mant32Exp( eR, eR_exp, L_add( L_mult( pt_fftR[0], pt_fftR[0] ), L_mult( pt_fftR[L_FFT / 2], pt_fftR[L_FFT / 2] ) ), shl( fft_exp, 1 ), &eR_exp ); + + FOR( i = 1; i < L_FFT / 2; i++ ) + { + cr = BASOP_Util_Add_Mant32Exp( cr, cr_exp, L_add( L_mult( pt_fftL[i], pt_fftR[i] ), L_mult( pt_fftL[L_FFT - i], pt_fftR[L_FFT - i] ) ), shl( fft_exp, 1 ), &cr_exp ); + ci = BASOP_Util_Add_Mant32Exp( ci, ci_exp, L_add( L_mult( -pt_fftL[i], pt_fftR[L_FFT - i] ), L_mult( pt_fftL[L_FFT - i], pt_fftR[i] ) ), shl( fft_exp, 1 ), &ci_exp ); + eL = BASOP_Util_Add_Mant32Exp( eL, eL_exp, L_add( L_mult( pt_fftL[i], pt_fftL[i] ), L_mult( pt_fftL[L_FFT - i], pt_fftL[L_FFT - i] ) ), shl( fft_exp, 1 ), &eL_exp ); + eR = BASOP_Util_Add_Mant32Exp( eR, eR_exp, L_add( L_mult( pt_fftR[i], pt_fftR[i] ), L_mult( pt_fftR[L_FFT - i], pt_fftR[L_FFT - i] ) ), shl( fft_exp, 1 ), &eR_exp ); + } + test(); + test(); + IF( LE_32( sts[0]->ini_frame, 50 ) || ( sts[0]->vad_flag == 0 && sts[1]->vad_flag == 0 ) ) + { + mem[0] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[0], 31129 /*0.95f*/ ), mem_exp[0], Mpy_32_16_1( cr, 1638 /*0.05f*/ ), cr_exp, &mem_exp[0] ); + move32(); + mem[1] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[1], 31129 /*0.95f*/ ), mem_exp[1], Mpy_32_16_1( ci, 1638 /*0.05f*/ ), ci_exp, &mem_exp[1] ); + move32(); + mem[2] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[2], 31129 /*0.95f*/ ), mem_exp[2], Mpy_32_16_1( eL, 1638 /*0.05f*/ ), eL_exp, &mem_exp[2] ); + move32(); + mem[3] = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( mem[3], 31129 /*0.95f*/ ), mem_exp[3], Mpy_32_16_1( eR, 1638 /*0.05f*/ ), eR_exp, &mem_exp[3] ); + move32(); + } + + pt_fftL += L_FFT; + pt_fftR += L_FFT; + } + + Word16 sqr_inp, temp, sqr_out, sqr_inp_exp; + Word32 sqr_inp32 = BASOP_Util_Add_Mant32Exp( Mpy_32_32( mem[0], mem[0] ), shl( mem_exp[0], 1 ), Mpy_32_32( mem[1], mem[1] ), shl( mem_exp[1], 1 ), &sqr_inp_exp ); + sqr_inp = BASOP_Util_Divide3232_Scale( sqr_inp32, Mpy_32_32( mem[2], mem[3] ), &temp ); + sqr_inp_exp = add( temp, sub( sqr_inp_exp, add( mem_exp[2], mem_exp[3] ) ) ); + sqr_out = Sqrt16( sqr_inp, &sqr_inp_exp ); + sts[0]->hFdCngEnc->hFdCngCom->coherence_fx = shl_sat( sqr_out, sqr_inp_exp ); // Q15 expected. + move16(); + return; +} +#else void stereoFdCngCoherence( Encoder_State **sts, /* i/o: core encoder structures */ const int16_t last_element_mode, /* i : last element mode */ @@ -1156,7 +1474,7 @@ void stereoFdCngCoherence( return; } - +#endif /*-------------------------------------------------------------------* * FdCngEncodeMDCTStereoSID() @@ -1233,8 +1551,16 @@ void FdCngEncodeMDCTStereoSID_fx( move32(); FOR( p = 0; p < N; p++ ) { - t1 = BASOP_Util_Log2( lr_in_ptr_fx[ch][p] ); // Q25 - t2 = L_add( t1, L_shl( lr_in_ptr_e[ch], Q25 ) ); // Q25 + IF( lr_in_ptr_fx[ch][p] ) + { + t1 = BASOP_Util_Log2( lr_in_ptr_fx[ch][p] ); // Q25 + t2 = L_add( t1, L_shl( lr_in_ptr_e[ch], Q25 ) ); // Q25 + } + ELSE + { + t2 = 0; + move32(); + } ms_ptr_fx[ch][p] = Mpy_32_32( t2, TEN_MULT_LOG10_2_IN_Q29 ); // Q23 move32(); E_fx[ch] = L_add( E_fx[ch], L_shr( ms_ptr_fx[ch][p], 4 ) ); // Q19 diff --git a/lib_enc/fd_cng_enc_fx.c b/lib_enc/fd_cng_enc_fx.c index 48df8f4e3..3d133928b 100644 --- a/lib_enc/fd_cng_enc_fx.c +++ b/lib_enc/fd_cng_enc_fx.c @@ -133,6 +133,8 @@ void initFdCngEnc_fx( HANDLE_FD_CNG_ENC hsEnc, Word32 input_Fs, Word16 scale ) hsEnc->msPeriodogBufPtr = 0; move16(); set32_fx( hsEnc->msPsdSecondMoment_fx, 0, NPART ); + set32_fx( hsEnc->mem_coherence_fx, EPSILON_FX, 4 ); + set16_fx( hsEnc->mem_coherence_exp, 0, 4 ); return; diff --git a/lib_enc/igf_enc.c b/lib_enc/igf_enc.c index 928295720..178b1196e 100644 --- a/lib_enc/igf_enc.c +++ b/lib_enc/igf_enc.c @@ -2921,7 +2921,7 @@ static void IGF_Whitening( const int16_t igfGridIdx, /* i : Q0 | IGF grid index */ const int16_t isTransient, /* i : Q0 | flag indicating if transient is detected */ const int16_t last_core_acelp, /* i : Q0 | indicator if last frame was ACELP core */ - const int8_t isTNSActive, /* i : Q0 | indicator if TNS is active */ + const int16_t isTNSActive, /* i : Q0 | indicator if TNS is active */ const int16_t sp_aud_decision0, /* i : Q0 | first stage classifier decision */ const int32_t brate, /* i : Q0 | bitrate */ const int16_t element_mode /* i : Q0 | element mode */ @@ -3813,7 +3813,7 @@ void IGFEncSetMode_ivas_fx( set16_fx( hPrivateData->igfCurrWhiteningLevel, 0, IGF_MAX_TILES ); set16_fx( hPrivateData->igfPrevWhiteningLevel, 0, IGF_MAX_TILES ); set16_fx( hPrivateData->igfWhiteningHangoverCnt, 0, IGF_MAX_TILES ); - for ( i = 0; i < IGF_MAX_TILES; i++ ) + FOR( i = 0; i < IGF_MAX_TILES; i++ ) { set16_fx( hPrivateData->igfPastSFM_fx[i], -( ONE_IN_Q13 ), IGF_PAST_SFM_LEN ); } @@ -3836,6 +3836,7 @@ void IGFEncSetMode_ivas_fx( set16_fx( hPrivateData->prevSFM_FIR_SFB_TB_fx, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->prevSFM_IIR_SFB_TB_fx, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->prevDampingFactor_IIR_fx, -( ONE_IN_Q15 ), IGF_MAX_SFB ); + set16_fx( hPrivateData->prevDampingFactor_IIR_e, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->logSpec, 0, L_FRAME_PLUS ); set16_fx( hPrivateData->SFM_sb_fx, 0, IGF_MAX_SFB ); set16_fx( hPrivateData->SFM_tb_fx, 0, IGF_MAX_SFB ); @@ -4183,7 +4184,7 @@ void IGFEncApplyMono( float *pMDCTSpectrum, /* i/o: MDCT spectrum */ float *pPowerSpectrum, /* i/o: MDCT^2 + MDST^2 spectrum, or estimate */ 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 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 */ ) @@ -4424,7 +4425,7 @@ void IGFSaveSpectrumForITF( return; } - +#ifndef IVAS_FLOAT_FIXED ivas_error IGF_Reconfig( IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ const int16_t igf, /* i : IGF on/off */ @@ -4459,3 +4460,4 @@ ivas_error IGF_Reconfig( return error; } +#endif diff --git a/lib_enc/igf_enc_fx.c b/lib_enc/igf_enc_fx.c index 6d60e02c0..81907c403 100644 --- a/lib_enc/igf_enc_fx.c +++ b/lib_enc/igf_enc_fx.c @@ -8,7 +8,7 @@ #include "options.h" #include "cnst.h" #include "stl.h" -// #include "prot_fx.h" +#include "prot.h" #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #include "stat_enc.h" @@ -1506,3 +1506,51 @@ void IGFEncApplyMono_fx( const IGF_ENC_INSTANCE_HANDLE hInstance, /**< in PowerSpectrum_e, /* i: exponent of pPowerSpectrum */ igfGridIdx ); /* i: IGF grid index */ } + + +#ifdef IVAS_FLOAT_FIXED +ivas_error IGF_Reconfig_fx( + IGF_ENC_INSTANCE_HANDLE *hIGFEnc, /* i/o: instance handle of IGF Encoder */ + const Word16 igf, /* i : IGF on/off */ + const Word16 reset, /* i : reset flag */ + const Word32 brate, /* i : bitrate for configuration */ + const Word16 bwidth, /* i : signal bandwidth */ + const Word16 element_mode, /* i : IVAS element mode */ + const Word16 rf_mode /* i : flag to signal the RF mode */ +) +{ + ivas_error error; + + error = IVAS_ERR_OK; + move32(); + + test(); + test(); + test(); + IF( igf && *hIGFEnc == NULL ) + { + IF( ( *hIGFEnc = (IGF_ENC_INSTANCE_HANDLE) malloc( sizeof( IGF_ENC_INSTANCE ) ) ) == NULL ) + { + return ( IVAS_ERROR( IVAS_ERR_FAILED_ALLOC, "Can not allocate memory for hIGFEnc\n" ) ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGFEncSetMode( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); +#endif + IGFEncSetMode_ivas_fx( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); + } + ELSE IF( igf && reset ) + { +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + IGFEncSetMode( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); +#endif + IGFEncSetMode_ivas_fx( *hIGFEnc, brate, bwidth, element_mode, rf_mode ); + } + ELSE IF( !igf && *hIGFEnc != NULL ) + { + free( *hIGFEnc ); + *hIGFEnc = NULL; + } + + return error; +} +#endif // IVAS_FLOAT_FIXED diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c index 7c2358ca9..2bad84390 100644 --- a/lib_enc/init_enc.c +++ b/lib_enc/init_enc.c @@ -930,7 +930,13 @@ ivas_error init_encoder( /* Init Mode 2 core coder */ st->last_totalNoise = 0.f; +#ifdef IVAS_FLOAT_FIXED + st->last_totalNoise_fx = 0; +#endif set_f( st->totalNoise_increase_hist, 0.f, TOTALNOISE_HIST_SIZE ); +#ifdef IVAS_FLOAT_FIXED + set16_fx( st->totalNoise_increase_hist_fx, 0, TOTALNOISE_HIST_SIZE ); +#endif st->totalNoise_increase_len = 0; init_coder_ace_plus( st, st->last_total_brate, 0 /* initialization value */ ); diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index 5e0c00753..1f3c9fc91 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -1055,7 +1055,38 @@ ivas_error ivas_core_enc( if ( st->extl == FB_TBE ) { /* FB TBE encoder */ +#ifndef IVAS_FLOAT_FIXED fb_tbe_enc( st, st->input, fb_exc ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_fb_exc, Q_input; + Word16 fb_exc_fx[L_FRAME16k]; + Q_fb_exc = Q_factor_arr( fb_exc, L_FRAME16k ); + floatToFixed_arr( fb_exc, fb_exc_fx, Q_fb_exc, L_FRAME16k ); + // Q_input is being calculated inside already + Q_input = 0; + floatToFixed_arr( st->input_buff, st->input_buff_fx, Q_input, L_FRAME48k + L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ) ); + Word16 len_old_input_fhb_fx = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) - L_FRAME48k / 2; + st->hBWE_TD->old_input_fhb_fx_Q = Q_factor_arr( st->hBWE_TD->old_input_fhb, len_old_input_fhb_fx ); + floatToFixed_arr( st->hBWE_TD->old_input_fhb, st->hBWE_TD->old_input_fhb_fx, st->hBWE_TD->old_input_fhb_fx_Q, len_old_input_fhb_fx ); + st->hBWE_TD->prev_fb_energy_fx = floatToFixed( st->hBWE_TD->prev_fb_energy, st->hBWE_TD->prev_fb_energy_fx_Q ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[0], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[0], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[0], 4 ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[1], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[1], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[1], 4 ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[2], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[2], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[2], 4 ); + floatToFixed_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem[3], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[3], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[3], 4 ); +#endif + fb_tbe_enc_ivas_fx( st, st->input_fx, fb_exc_fx, Q_fb_exc ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( fb_exc_fx, fb_exc, Q_fb_exc, L_FRAME16k ); + fixedToFloat_arr( st->input_fx, st->input, Q_input, L_FRAME48k ); + fixedToFloat_arr( st->hBWE_TD->old_input_fhb_fx, st->hBWE_TD->old_input_fhb, st->hBWE_TD->old_input_fhb_fx_Q, len_old_input_fhb_fx ); + st->hBWE_TD->prev_fb_energy = fixedToFloat( st->hBWE_TD->prev_fb_energy_fx, st->hBWE_TD->prev_fb_energy_fx_Q ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[0], st->hBWE_TD->elliptic_bpf_2_48k_mem[0], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[0], 4 ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[1], st->hBWE_TD->elliptic_bpf_2_48k_mem[1], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[1], 4 ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[2], st->hBWE_TD->elliptic_bpf_2_48k_mem[2], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[2], 4 ); + fixedToFloat_arrL( st->hBWE_TD->elliptic_bpf_2_48k_mem_fx[3], st->hBWE_TD->elliptic_bpf_2_48k_mem[3], st->hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q[3], 4 ); +#endif +#endif } } } diff --git a/lib_enc/ivas_core_pre_proc.c b/lib_enc/ivas_core_pre_proc.c index ebfddf500..e0c293aa2 100644 --- a/lib_enc/ivas_core_pre_proc.c +++ b/lib_enc/ivas_core_pre_proc.c @@ -239,7 +239,16 @@ ivas_error pre_proc_ivas( Word16 q_fft_buff; - q_fft_buff = Q_factor_arr( fft_buff, ( 2 * L_FFT ) ); + q_fft_buff = Q_factor_arrL( fft_buff, ( 2 * L_FFT ) ); + + if ( q_fft_buff <= 16 ) + { + q_fft_buff = 0; + } + else + { + q_fft_buff = q_fft_buff - 16; + } if ( q_fft_buff >= 2 ) { @@ -657,7 +666,10 @@ ivas_error ivas_compute_core_buffers( ) { float *inp_16k, *new_inp_16k; - float tmp, mem_decim16k_dummy[2 * L_FILT_MAX]; +#ifndef IVAS_FLOAT_FIXED + float tmp; +#endif + float mem_decim16k_dummy[2 * L_FILT_MAX]; /*const*/ float *signal_in; int16_t delay, element_mode; #ifdef IVAS_FLOAT_FIXED @@ -1160,6 +1172,10 @@ ivas_error ivas_compute_core_buffers( st->mem_preemph_enc_flt = new_inp_16k[L_frame_tmp - 1]; } +#ifdef IVAS_FLOAT_FIXED + Word16 exp_new_inp_16k_fx = 0; + move16(); +#endif if ( input_Fs > 8000 && sr_core == INT_FS_16k && element_mode != IVAS_CPE_MDCT ) { if ( element_mode == IVAS_CPE_DFT ) @@ -1173,17 +1189,51 @@ ivas_error ivas_compute_core_buffers( { mvr2r( new_inp_16k - STEREO_DFT_OVL_16k, st->buf_speech_enc_flt + L_FRAME16k - STEREO_DFT_OVL_16k, L_FRAME16k + STEREO_DFT_OVL_16k ); } +#ifdef IVAS_FLOAT_FIXED + f2me_buf_16( new_inp_16k - STEREO_DFT_OVL_16k, new_inp_16k_fx - STEREO_DFT_OVL_16k, &exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + + PREEMPH_FX( new_inp_16k_fx - STEREO_DFT_OVL_16k, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + fixedToFloat_arr( new_inp_16k_fx - STEREO_DFT_OVL_16k, new_inp_16k - STEREO_DFT_OVL_16k, 15 - exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); +#else preemph( new_inp_16k - STEREO_DFT_OVL_16k, PREEMPH_FAC_16k_FLT, L_FRAME16k, &( st->mem_preemph16k ) ); tmp = st->mem_preemph16k; +#endif + +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + move16(); + f2me_buf_16( new_inp_16k - STEREO_DFT_OVL_16k + L_FRAME16k, new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, &exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); + Word16 tmp_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, PREEMPH_FAC_16k, STEREO_DFT_OVL_16k, &tmp_fx ); + fixedToFloat_arr( new_inp_16k_fx - STEREO_DFT_OVL_16k + L_FRAME16k, new_inp_16k - STEREO_DFT_OVL_16k + L_FRAME16k, 15 - exp_new_inp_16k_fx, STEREO_DFT_OVL_16k + L_FRAME16k ); +#else preemph( new_inp_16k - STEREO_DFT_OVL_16k + L_FRAME16k, PREEMPH_FAC_16k_FLT, STEREO_DFT_OVL_16k, &tmp ); +#endif } else if ( st->element_mode == IVAS_CPE_TD ) { if ( last_element_mode == IVAS_CPE_DFT ) { +#ifdef IVAS_FLOAT_FIXED + Word16 exp_inp_16k_mem_stereo_sw = 0; + move16(); + f2me_buf_16( st->inp_16k_mem_stereo_sw, st->inp_16k_mem_stereo_sw_fx, &exp_inp_16k_mem_stereo_sw, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + st->mem_preemph16k_DFT_fx = (Word16) floatToFixed( st->mem_preemph16k_DFT, 15 - exp_inp_16k_mem_stereo_sw ); + + st->mem_preemph16k_fx = st->mem_preemph16k_DFT_fx; + move16(); + Copy( st->inp_16k_mem_stereo_sw_fx, new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); + PREEMPH_FX( new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), PREEMPH_FAC_16k, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k, &st->mem_preemph16k_fx ); + + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_inp_16k_mem_stereo_sw ); + fixedToFloat_arr( new_inp_16k_fx - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), new_inp_16k - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), 15 - exp_inp_16k_mem_stereo_sw, L_MEM_RECALC_16K + STEREO_DFT_OVL_16k + L_MEM_RECALC_16K + L_FILT16k ); +#else st->mem_preemph16k = st->mem_preemph16k_DFT; mvr2r( st->inp_16k_mem_stereo_sw, new_inp_16k - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ); preemph( new_inp_16k - L_MEM_RECALC_16K - ( STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k ), PREEMPH_FAC_16k_FLT, STEREO_DFT_OVL_16k - L_MEM_RECALC_16K - L_FILT16k, &st->mem_preemph16k ); +#endif } st->mem_preemph16k_DFT = old_inp_16k[L_INP_MEM - STEREO_DFT_OVL_16k + L_FRAME16k - 1]; @@ -1192,43 +1242,90 @@ ivas_error ivas_compute_core_buffers( if ( last_element_mode == IVAS_CPE_MDCT ) { int16_t length_16k = NS2SA( INT_FS_16k, L_MEM_RECALC_SCH_NS - DELAY_FIR_RESAMPL_NS ); +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + move16(); + f2me_buf_16( new_inp_16k - lMemRecalc_16k - length_16k, new_inp_16k_fx - lMemRecalc_16k - length_16k, &exp_new_inp_16k_fx, lMemRecalc_16k + length_16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k - length_16k, PREEMPH_FAC, length_16k, &st->mem_preemph16k_fx ); + + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k - length_16k, new_inp_16k - lMemRecalc_16k - length_16k, 15 - exp_new_inp_16k_fx, lMemRecalc_16k + length_16k ); +#else preemph( new_inp_16k - lMemRecalc_16k - length_16k, PREEMPH_FAC_FLT, length_16k, &st->mem_preemph16k ); +#endif } if ( st->L_frame == L_FRAME16k ) { mvr2r( new_inp_16k - lMemRecalc_16k, st->buf_speech_enc_flt + L_FRAME16k - lMemRecalc_16k - L_FILT16k, L_FRAME16k + lMemRecalc_16k + L_FILT16k ); } +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k - lMemRecalc_16k, new_inp_16k_fx - lMemRecalc_16k, &exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k, new_inp_16k - lMemRecalc_16k, 15 - exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); +#else preemph( new_inp_16k - lMemRecalc_16k, PREEMPH_FAC_16k_FLT, L_FRAME16k, &( st->mem_preemph16k ) ); tmp = st->mem_preemph16k; +#endif +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k - lMemRecalc_16k, new_inp_16k_fx - lMemRecalc_16k, &exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); + Word16 tmp_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx - lMemRecalc_16k + L_FRAME16k, PREEMPH_FAC_16k, lMemRecalc_16k + L_FILT16k, &tmp_fx ); + fixedToFloat_arr( new_inp_16k_fx - lMemRecalc_16k + L_FRAME16k, new_inp_16k - lMemRecalc_16k + L_FRAME16k, 15 - exp_new_inp_16k_fx, lMemRecalc_16k + L_FRAME16k ); +#else preemph( new_inp_16k - lMemRecalc_16k + L_FRAME16k, PREEMPH_FAC_16k_FLT, lMemRecalc_16k + L_FILT16k, &tmp ); +#endif } else if ( element_mode == IVAS_SCE ) { +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k, new_inp_16k_fx, &exp_new_inp_16k_fx, L_FRAME16k ); + st->mem_preemph16k_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx, PREEMPH_FAC_16k, L_FRAME16k, &( st->mem_preemph16k_fx ) ); + st->mem_preemph16k = fixedToFloat( st->mem_preemph16k_fx, 15 - exp_new_inp_16k_fx ); + fixedToFloat_arr( new_inp_16k_fx, new_inp_16k, 15 - exp_new_inp_16k_fx, L_FRAME16k ); +#else preemph( new_inp_16k, PREEMPH_FAC_16k_FLT, L_FRAME16k, &( st->mem_preemph16k ) ); tmp = st->mem_preemph16k; +#endif + +#ifdef IVAS_FLOAT_FIXED + exp_new_inp_16k_fx = 0; + f2me_buf_16( new_inp_16k + L_FRAME16k, new_inp_16k_fx + L_FRAME16k, &exp_new_inp_16k_fx, L_FRAME16k + L_FILT16k ); + Word16 tmp_fx = (Word16) floatToFixed( st->mem_preemph16k, 15 - exp_new_inp_16k_fx ); + PREEMPH_FX( new_inp_16k_fx + L_FRAME16k, PREEMPH_FAC_16k, L_FILT16k, &tmp_fx ); + fixedToFloat_arr( new_inp_16k_fx + L_FRAME16k, new_inp_16k + L_FRAME16k, 15 - exp_new_inp_16k_fx, L_FRAME16k + L_FILT16k ); +#else preemph( new_inp_16k + L_FRAME16k, PREEMPH_FAC_16k_FLT, L_FILT16k, &tmp ); +#endif } - } - else if ( input_Fs > 8000 ) /* keep memory up-to-date in case of bitrate switching */ - { - if ( element_mode == IVAS_CPE_DFT ) - { - st->mem_preemph16k = new_inp_16k[L_frame_tmp - STEREO_DFT_OVL_16k - 1]; - } - else if ( element_mode == IVAS_CPE_TD ) - { - st->mem_preemph16k = new_inp_16k[L_frame_tmp - lMemRecalc_16k - 1]; - } - else if ( element_mode == IVAS_CPE_MDCT ) - { - st->mem_preemph16k = 0; - } - else /* SCE */ + else if ( input_Fs > 8000 ) /* keep memory up-to-date in case of bitrate switching */ { - st->mem_preemph16k = new_inp_16k[L_frame_tmp - 1]; + if ( element_mode == IVAS_CPE_DFT ) + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp - STEREO_DFT_OVL_16k - 1]; + } + else if ( element_mode == IVAS_CPE_TD ) + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp - lMemRecalc_16k - 1]; + } + else if ( element_mode == IVAS_CPE_MDCT ) + { + st->mem_preemph16k = 0; + } + else /* SCE */ + { + st->mem_preemph16k = new_inp_16k[L_frame_tmp - 1]; + } + st->mem_preemph16k_DFT = st->mem_preemph16k; } - st->mem_preemph16k_DFT = st->mem_preemph16k; } /*-----------------------------------------------------------------* diff --git a/lib_enc/ivas_core_pre_proc_front.c b/lib_enc/ivas_core_pre_proc_front.c index f6c125d12..f3b7fce10 100644 --- a/lib_enc/ivas_core_pre_proc_front.c +++ b/lib_enc/ivas_core_pre_proc_front.c @@ -46,6 +46,8 @@ #ifdef IVAS_FLOAT_FIXED #include "prot_fx_enc.h" +#include "ivas_prot_fx.h" +#include "prot_fx.h" #endif /*---------------------------------------------------------------* @@ -956,21 +958,24 @@ ivas_error pre_proc_front_ivas_fx( 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 */ + Word32 sp_div_fx; + 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 */ #endif - float hp_E[2]; /* Energy in HF */ + float hp_E[2]; /* Energy in HF */ Word16 flag_spitch; Word16 high_lpn_flag; float lsf_new[M]; + Word32 lsf_new_fx[M]; float band_energies[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ #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; + Word32 non_staX_fx; float stab_fac; Word16 alw_pitch_lag_12k8[2]; float alw_voicing[2]; @@ -991,6 +996,9 @@ ivas_error pre_proc_front_ivas_fx( Word16 old_pitch1; /* previous frame OL pitch[1] @12.8 kHz */ Word16 LR_localVAD; ivas_error error; + Word32 epsP_fx[17]; /*to be removed later*/ + Word32 cor_map_sum_fx; + push_wmops( "pre_proc_front" ); Word16 *signal_in_fx; @@ -1026,8 +1034,10 @@ ivas_error pre_proc_front_ivas_fx( Word16 new_inp_out_size; Word16 Q_new_inp; Word16 mem_decim_size; -#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING Word16 *wsp_fx; + Word16 pitch_fr_fx[NB_SUBFR]; + Word16 voicing_fr_fx[NB_SUBFR]; +#ifndef REMOVE_IVAS_UNUSED_PARAMETERS_WARNING Word16 Q_new; Word16 corr_shift_fx; #endif @@ -1267,10 +1277,7 @@ ivas_error pre_proc_front_ivas_fx( Copy( st->old_inp_12k8_fx, old_inp_12k8_fx, L_INP_MEM - L_FILT ); } 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(); @@ -1825,17 +1832,134 @@ ivas_error pre_proc_front_ivas_fx( *----------------------------------------------------------------*/ if ( st->hFdCngEnc != NULL ) { +#ifdef IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->last_totalNoise_fx = float_to_fix16( st->last_totalNoise, Q8 ); + st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, Q8 ); + + FOR( Word16 n = 0; n < TOTALNOISE_HIST_SIZE; n++ ) + { + st->totalNoise_increase_hist_fx[n] = float_to_fix16( st->totalNoise_increase_hist[n], Q8 ); + move16(); + } +#endif + resetFdCngEnc_fx( st ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 totalNoiseIncrease_fx = st->hNoiseEst->totalNoise_fx - st->last_totalNoise_fx; + st->last_totalNoise = fix16_to_float( st->last_totalNoise_fx, Q8 ); + IF( + ( totalNoiseIncrease_fx > 5 * 256 && st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE && st->ini_frame > 150 ) || + ( st->input_bwidth > st->last_input_bwidth ) || + ( st->last_core == AMR_WB_CORE ) ) + { + st->hFdCngEnc->hFdCngCom->init_old_flt = fix16_to_float( st->hFdCngEnc->hFdCngCom->init_old, Q15 ); + move16(); + } + + IF( totalNoiseIncrease_fx > 0 ) + { + IF( EQ_16( st->totalNoise_increase_len, TOTALNOISE_HIST_SIZE ) ) + { + FOR( Word16 ind = 0; i < TOTALNOISE_HIST_SIZE; ind++ ) + { + st->totalNoise_increase_hist[ind] = fix16_to_float( st->totalNoise_increase_hist_fx[ind + 1], Q8 ); + move16(); + } + } + ELSE + { + st->totalNoise_increase_hist[st->totalNoise_increase_len] = fix16_to_float( st->totalNoise_increase_hist_fx[st->totalNoise_increase_len], Q8 ); + move16(); + } + } +#endif +#else resetFdCngEnc( st ); +#endif if ( st->idchan == 0 || element_mode == IVAS_CPE_MDCT ) { if ( element_mode == IVAS_CPE_TD && lr_vad_enabled && band_energies_LR != NULL ) { - perform_noise_estimation_enc( band_energies_LR, enerBuffer, st->hFdCngEnc, input_Fs, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 band_energies_LR_fx[2 * NB_BANDS] = { 0 }; /* energy in critical bands without minimum noise floor E_MIN */ + Word16 band_energies_LR_fx_exp; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 enerBuffer_fx_loc[CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word16 enerBuffer_fx_exp; + + Word16 q_band_energies_LR = Q_factor_arrL( band_energies_LR, 2 * NB_BANDS ); + band_energies_LR_fx_exp = 31 - q_band_energies_LR; + floatToFixed_arrL( band_energies_LR, band_energies_LR_fx, ( 31 - band_energies_LR_fx_exp ), 2 * NB_BANDS ); + + Word16 q_enerBuffer = Q_factor_arrL( enerBuffer, CLDFB_NO_CHANNELS_MAX ); + enerBuffer_fx_exp = 31 - q_enerBuffer; + floatToFixed_arrL( enerBuffer, enerBuffer_fx_loc, ( 31 - enerBuffer_fx_exp ), CLDFB_NO_CHANNELS_MAX ); + + Word16 normmsPeriodog = Q_factor_arrL( st->hFdCngEnc->msPeriodog, NPART ); + st->hFdCngEnc->msPeriodog_fx_exp = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_cldfb = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_fft = 31 - normmsPeriodog; + floatToFixed_arrL( st->hFdCngEnc->msPeriodog, st->hFdCngEnc->msPeriodog_fx, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + + // not needed actuall its just output + Word16 normmsNoiseEst = Q_factor_arrL( st->hFdCngEnc->msNoiseEst, NPART ); + st->hFdCngEnc->msNoiseEst_fx_exp = 31 - normmsNoiseEst; + floatToFixed_arrL( st->hFdCngEnc->msNoiseEst, st->hFdCngEnc->msNoiseEst_fx, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + floatToFixed_arr( st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv_flt, st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv, 15, NPARTCLDFB ); +#endif + perform_noise_estimation_enc_ivas_fx( band_energies_LR_fx, band_energies_LR_fx_exp, enerBuffer_fx_loc, enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( st->hFdCngEnc->msNoiseEst_fx, st->hFdCngEnc->msNoiseEst, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + fixedToFloat_arrL( st->hFdCngEnc->msPeriodog_fx, st->hFdCngEnc->msPeriodog, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); +#endif } else { - perform_noise_estimation_enc( band_energies, enerBuffer, st->hFdCngEnc, input_Fs, hCPE ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 band_energies_fx[2 * NB_BANDS] = { 0 }; /* energy in critical bands without minimum noise floor E_MIN */ + Word16 band_energies_fx_exp; /* energy in critical bands without minimum noise floor E_MIN */ + Word32 enerBuffer_fx_loc[CLDFB_NO_CHANNELS_MAX] = { 0 }; + Word16 enerBuffer_fx_exp; + + Word16 q_band_energies = Q_factor_arrL( band_energies, 2 * NB_BANDS ); + band_energies_fx_exp = 31 - q_band_energies; + floatToFixed_arrL( band_energies, band_energies_fx, ( 31 - band_energies_fx_exp ), 2 * NB_BANDS ); + + + Word16 q_enerBuffer = Q_factor_arrL( enerBuffer, CLDFB_NO_CHANNELS_MAX ); + enerBuffer_fx_exp = 31 - q_enerBuffer; + floatToFixed_arrL( enerBuffer, enerBuffer_fx_loc, ( 31 - enerBuffer_fx_exp ), CLDFB_NO_CHANNELS_MAX ); + + Word16 normmsPeriodog = Q_factor_arrL( st->hFdCngEnc->msPeriodog, NPART ); + st->hFdCngEnc->msPeriodog_fx_exp = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_cldfb = 31 - normmsPeriodog; + st->hFdCngEnc->msPeriodog_fx_exp_fft = 31 - normmsPeriodog; + floatToFixed_arrL( st->hFdCngEnc->msPeriodog, st->hFdCngEnc->msPeriodog_fx, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + + // not needed actuall its just output + Word16 normmsNoiseEst = Q_factor_arrL( st->hFdCngEnc->msNoiseEst, NPART ); + st->hFdCngEnc->msNoiseEst_fx_exp = 31 - normmsNoiseEst; + floatToFixed_arrL( st->hFdCngEnc->msNoiseEst, st->hFdCngEnc->msNoiseEst_fx, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + floatToFixed_arr( st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv_flt, st->hFdCngEnc->hFdCngCom->CLDFBpsize_inv, 15, NPARTCLDFB ); + + Word16 normmsperiodog = Q_factor_arrL( st->hFdCngEnc->hFdCngCom->periodog_flt, PERIODOGLEN ); + st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog = 31 - normmsperiodog; + // floatToFixed_arrL( st->hFdCngEnc->hFdCngCom->periodog_flt, st->hFdCngEnc->hFdCngCom->periodog, 31 - st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog, PERIODOGLEN); + floatToFixed_arr( st->hFdCngEnc->msPeriodogBuf, st->hFdCngEnc->msPeriodogBuf_fx, 9, MSBUFLEN * NPART ); + st->hFdCngEnc->hFdCngCom->init_old = (Word16) ( st->hFdCngEnc->hFdCngCom->init_old_flt * ( 1 << 9 ) ); + st->hFdCngEnc->hFdCngCom->scalingFactor = (Word16) ( st->hFdCngEnc->hFdCngCom->scalingFactor * ( 1 << 30 ) ); +#endif + + perform_noise_estimation_enc_ivas_fx( band_energies_fx, band_energies_fx_exp, enerBuffer_fx_loc, enerBuffer_fx_exp, st->hFdCngEnc, input_Fs, hCPE ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( st->hFdCngEnc->msNoiseEst_fx, st->hFdCngEnc->msNoiseEst, 31 - st->hFdCngEnc->msNoiseEst_fx_exp, NPART ); + fixedToFloat_arr( st->hFdCngEnc->msPeriodogBuf_fx, st->hFdCngEnc->msPeriodogBuf, 9, MSBUFLEN * NPART ); + fixedToFloat_arrL( st->hFdCngEnc->msPeriodog_fx, st->hFdCngEnc->msPeriodog, 31 - st->hFdCngEnc->msPeriodog_fx_exp, NPART ); + // fixedToFloat_arrL(st->hFdCngEnc->hFdCngCom->periodog, st->hFdCngEnc->hFdCngCom->periodog_flt, 31 - st->hFdCngEnc->hFdCngCom->exp_cldfb_periodog, PERIODOGLEN); +#endif } } } @@ -1935,6 +2059,67 @@ ivas_error pre_proc_front_ivas_fx( /* Updates for adaptive lag window memory */ st->old_pitch_la = st->pitch[2]; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 q_wsp = Q_factor_arr( old_wsp, L_WSP ) - 5; + floatToFixed_arr( old_wsp, old_wsp_fx, q_wsp, L_WSP ); + floatToFixed_arr( st->voicing, st->voicing_fx, Q15, 3 ); + st->voicing_sm_fx = float_to_fix16( st->voicing_sm, Q15 ); + st->voicing0_sm_fx = float_to_fix16( st->voicing0_sm, Q15 ); + st->LF_EnergyRatio_sm_fx = float_to_fix16( st->LF_EnergyRatio_sm, Q7 ); + st->diff_sm_fx = floatToFixed_32( st->diff_sm, Q7 ); + st->energy_sm_fx = floatToFixed_32( st->energy_sm, Q7 ); + floatToFixed_arr( st->Bin_E, st->lgBin_E_fx, Q7, L_FFT / 2 ); // Function StableHighPitchDetect_fx excepts st->lgBin_E_fx to be in Q7 + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + /* Detection of very short stable pitch period */ + StableHighPitchDetect_fx( &flag_spitch, st->pitch, st->voicing_fx, wsp_fx, st->localVAD, &st->voicing_sm_fx, &st->voicing0_sm_fx, &st->LF_EnergyRatio_sm_fx, &st->predecision_flag, &st->diff_sm_fx, &st->energy_sm_fx, q_wsp, st->lgBin_E_fx ); + + /* 1/4 pitch precision improvement */ + IF( LE_32( element_brate, IVAS_32k ) ) + { + /* 1/4 pitch precision improvement */ + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[0], &pitch_fr_fx[0], &voicing_fr_fx[0], 0, wsp_fx, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[0], &pitch_fr_fx[1], &voicing_fr_fx[1], L_SUBFR, wsp_fx, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[1], &pitch_fr_fx[2], &voicing_fr_fx[2], 2 * L_SUBFR, wsp_fx, 7 ); + pitch_ol2_fx( PIT_MIN_EXTEND, st->pitch[1], &pitch_fr_fx[3], &voicing_fr_fx[3], 3 * L_SUBFR, wsp_fx, 7 ); + } + ELSE + { + pitch_fr_fx[0] = shl( st->pitch[0], 6 ); // Q6 + move16(); + pitch_fr_fx[1] = shl( st->pitch[0], 6 ); // Q6 + move16(); + pitch_fr_fx[2] = shl( st->pitch[1], 6 ); // Q6 + move16(); + pitch_fr_fx[3] = shl( st->pitch[1], 6 ); // Q6 + move16(); + + voicing_fr_fx[0] = st->voicing_fx[0]; // Q15 + move16(); + voicing_fr_fx[1] = st->voicing_fx[0]; // Q15 + move16(); + voicing_fr_fx[2] = st->voicing_fx[1]; // Q15 + move16(); + voicing_fr_fx[3] = st->voicing_fx[1]; // Q15 + move16(); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + st->diff_sm = fixedToFloat( st->diff_sm_fx, Q7 ); + st->energy_sm = fixedToFloat( st->energy_sm_fx, Q7 ); + st->LF_EnergyRatio_sm = fixedToFloat_16( st->LF_EnergyRatio_sm_fx, Q7 ); + st->voicing_sm = fixedToFloat_16( st->voicing_sm_fx, Q15 ); + st->voicing0_sm = fixedToFloat_16( st->voicing0_sm_fx, Q15 ); + + fixedToFloat_arr( voicing_fr_fx, voicing_fr, Q15, NB_SUBFR ); + fixedToFloat_arr( pitch_fr_fx, pitch_fr, Q6, NB_SUBFR ); + +#endif // IVAS_FLOAT_FIXED_CONVERSIONS +#else /* Detection of very short stable pitch period */ StableHighPitchDetect( &flag_spitch, st->pitch, st->voicing, st->Bin_E, wsp, st->localVAD, &st->voicing_sm, &st->voicing0_sm, &st->LF_EnergyRatio_sm, &st->predecision_flag, &st->diff_sm, &st->energy_sm ); @@ -1959,6 +2144,7 @@ ivas_error pre_proc_front_ivas_fx( voicing_fr[2] = st->voicing[1]; voicing_fr[3] = st->voicing[1]; } +#endif // IVAS_FLOAT_FIXED /*------------------------------------------------------------------* * Update estimated noise energy and voicing cut-off frequency @@ -2028,7 +2214,76 @@ ivas_error pre_proc_front_ivas_fx( if ( hStereoClassif != NULL ) { +#if 1 +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 cor_map_sum_e, non_staX_e, sp_div_e, epsP_e, max_e_Etot; + hStereoClassif->relE_buf_e = 0; + f2me( hStereoClassif->ave_ener_L, &hStereoClassif->ave_ener_L_fx, &hStereoClassif->ave_ener_L_fx_e ); + f2me( hStereoClassif->ave_ener_R, &hStereoClassif->ave_ener_R_fx, &hStereoClassif->ave_ener_R_fx_e ); + f2me_buf( hStereoClassif->Etot_buf, hStereoClassif->Etot_buf_fx, &hStereoClassif->e_Etot_buf_fx, 3 ); + floatToFixed_arr32( hStereoClassif->relE_buf, hStereoClassif->relE_buf_fx, 31 - hStereoClassif->relE_buf_e, 3 ); + hStereoClassif->relE_0_1_LT_fx = float_to_fix( hStereoClassif->relE_0_1_LT, 31 - hStereoClassif->relE_buf_e ); + hStereoClassif->relE_0_1_fx = float_to_fix( hStereoClassif->relE_0_1, 31 - hStereoClassif->relE_buf_e ); + f2me( hStereoClassif->Etot_up, &hStereoClassif->Etot_up_fx, &hStereoClassif->Etot_up_e ); + f2me( hStereoClassif->Etot_dn, &hStereoClassif->Etot_dn_fx, &hStereoClassif->Etot_dn_e ); + floatToFixed_arr32( lsf_new, lsf_new_fx, Q15, M ); + f2me( hStereoClassif->ratio_L, &hStereoClassif->ratio_L_fx, &hStereoClassif->ratio_L_e ); + hStereoClassif->lepsP_ch1_fx = float_to_fix( hStereoClassif->lepsP_ch1, Q15 ); + floatToFixed_arr32( hStereoClassif->lsf_ch1, hStereoClassif->lsf_ch1_fx, Q15, M ); + floatToFixed_arr32( hStereoClassif->xtalk_fv, hStereoClassif->xtalk_fv_fx, Q15, 58 ); + f2me_buf( hStereoClassif->voicing_ch1, hStereoClassif->voicing_ch1_fx, &hStereoClassif->voicing_ch1_e, 3 ); + f2me_buf_16( st->voicing, st->voicing_fx, &st->voicing_e, 3 ); + f2me( *cor_map_sum, &cor_map_sum_fx, &cor_map_sum_e ); + f2me( non_staX, &non_staX_fx, &non_staX_e ); + f2me( hStereoClassif->nchar_ch1, &hStereoClassif->nchar_ch1_fx, &hStereoClassif->nchar_ch1_e ); + f2me_buf( epsP, epsP_fx, &epsP_e, 17 ); + f2me( hStereoClassif->cor_map_sum_ch1, &hStereoClassif->cor_map_sum_ch1_fx, &hStereoClassif->cor_map_sum_ch1_e ); + f2me( hStereoClassif->non_sta_ch1, &hStereoClassif->non_sta_ch1_fx, &hStereoClassif->non_sta_ch1_e ); + f2me( hStereoClassif->sp_div_ch1, &hStereoClassif->sp_div_ch1_fx, &hStereoClassif->sp_div_ch1_e ); + f2me( hStereoClassif->nchar_ch1, &hStereoClassif->nchar_ch1_fx, &hStereoClassif->nchar_ch1_e ); + f2me( hStereoClassif->nchar_ch2, &hStereoClassif->nchar_ch2_fx, &hStereoClassif->nchar_ch2_e ); + f2me( hStereoClassif->dE1_ch1, &hStereoClassif->dE1_ch1_fx, &hStereoClassif->dE1_ch1_e ); + f2me( hStereoClassif->dE1_ch2, &hStereoClassif->dE1_ch2_fx, &hStereoClassif->dE1_ch2_e ); + f2me( hStereoClassif->ps_diff_ch1, &hStereoClassif->ps_diff_ch1_fx, &hStereoClassif->ps_diff_ch1_e ); + f2me( hStereoClassif->ps_sta_ch1, &hStereoClassif->ps_sta_ch1_fx, &hStereoClassif->ps_sta_ch1_e ); + f2me( hStereoClassif->ps_diff_ch2, &hStereoClassif->ps_diff_ch2_fx, &hStereoClassif->ps_diff_ch2_e ); + f2me( hStereoClassif->ps_sta_ch2, &hStereoClassif->ps_sta_ch2_fx, &hStereoClassif->ps_sta_ch2_e ); + f2me( sp_div, &sp_div_fx, &sp_div_e ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + max_e_Etot = max( hStereoClassif->e_Etot_buf_fx, max( hStereoClassif->Etot_up_e, hStereoClassif->Etot_dn_e ) ); + scale_sig32( hStereoClassif->Etot_buf_fx, 3, hStereoClassif->e_Etot_buf_fx - max_e_Etot ); + hStereoClassif->Etot_up_fx = L_shr( hStereoClassif->Etot_up_fx, max_e_Etot - hStereoClassif->Etot_up_e ); + hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, max_e_Etot - hStereoClassif->Etot_dn_e ); + hStereoClassif->Etot_up_e = hStereoClassif->Etot_dn_e = hStereoClassif->e_Etot_buf_fx = max_e_Etot; + stereo_classifier_features_ivas_fx( hStereoClassif, st->idchan, element_mode, localVAD_HE_SAD, lsf_new_fx, epsP_fx, + st->pitch, st->voicing_fx, cor_map_sum_fx, non_staX_fx, sp_div_fx, + st->clas, epsP_e, st->voicing_e, cor_map_sum_e, non_staX_e, sp_div_e ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + me2f_buf( hStereoClassif->Etot_buf_fx, hStereoClassif->e_Etot_buf_fx, hStereoClassif->Etot_buf, 3 ); + me2f_buf( hStereoClassif->relE_buf_fx, hStereoClassif->relE_buf_e, hStereoClassif->relE_buf, 10 ); + me2f_buf( hStereoClassif->lsf_ch1_fx, 16, hStereoClassif->lsf_ch1, 16 ); + me2f_buf( hStereoClassif->xtalk_fv_fx, 16, hStereoClassif->xtalk_fv, 58 ); + me2f_buf( hStereoClassif->voicing_ch1_fx, hStereoClassif->voicing_ch1_e, hStereoClassif->voicing_ch1, 3 ); + hStereoClassif->lepsP_ch1 = me2f( hStereoClassif->lepsP_ch1_fx, 16 ); + hStereoClassif->Etot_up = me2f( hStereoClassif->Etot_up_fx, hStereoClassif->Etot_up_e ); + hStereoClassif->Etot_dn = me2f( hStereoClassif->Etot_dn_fx, hStereoClassif->Etot_dn_e ); + hStereoClassif->relE_0_1 = me2f( hStereoClassif->relE_0_1_fx, hStereoClassif->relE_buf_e ); + hStereoClassif->relE_0_1_LT = me2f( hStereoClassif->relE_0_1_LT_fx, hStereoClassif->relE_buf_e ); + hStereoClassif->cor_map_sum_ch1 = me2f( hStereoClassif->cor_map_sum_ch1_fx, hStereoClassif->cor_map_sum_ch1_e ); + hStereoClassif->non_sta_ch1 = me2f( hStereoClassif->non_sta_ch1_fx, hStereoClassif->non_sta_ch1_e ); + hStereoClassif->sp_div_ch1 = me2f( hStereoClassif->sp_div_ch1_fx, hStereoClassif->sp_div_ch1_e ); + hStereoClassif->nchar_ch1 = me2f( hStereoClassif->nchar_ch1_fx, hStereoClassif->nchar_ch1_e ); + hStereoClassif->nchar_ch2 = me2f( hStereoClassif->nchar_ch2_fx, hStereoClassif->nchar_ch2_e ); + hStereoClassif->dE1_ch1 = me2f( hStereoClassif->dE1_ch1_fx, hStereoClassif->dE1_ch1_e ); + hStereoClassif->dE1_ch2 = me2f( hStereoClassif->dE1_ch2_fx, hStereoClassif->dE1_ch2_e ); + hStereoClassif->ps_diff_ch1 = me2f( hStereoClassif->ps_diff_ch1_fx, hStereoClassif->ps_diff_ch1_e ); + hStereoClassif->ps_sta_ch1 = me2f( hStereoClassif->ps_sta_ch1_fx, hStereoClassif->ps_sta_ch1_e ); + hStereoClassif->ps_diff_ch2 = me2f( hStereoClassif->ps_diff_ch2_fx, hStereoClassif->ps_diff_ch2_e ); + hStereoClassif->ps_sta_ch2 = me2f( hStereoClassif->ps_sta_ch2_fx, hStereoClassif->ps_sta_ch2_e ); +#endif +#else stereo_classifier_features( hStereoClassif, st->idchan, element_mode, localVAD_HE_SAD, lsf_new, epsP, st->pitch, st->voicing, *cor_map_sum, non_staX, sp_div, st->clas ); +#endif // IVAS_FLOAT_FIXED } /*----------------------------------------------------------------* diff --git a/lib_enc/ivas_corecoder_enc_reconfig.c b/lib_enc/ivas_corecoder_enc_reconfig.c index 1f7defcbc..1b2371267 100644 --- a/lib_enc/ivas_corecoder_enc_reconfig.c +++ b/lib_enc/ivas_corecoder_enc_reconfig.c @@ -34,6 +34,7 @@ #include "options.h" #include "ivas_cnst.h" #include "prot.h" +#include "prot_fx.h" #include "ivas_prot.h" #include "wmc_auto.h" @@ -414,8 +415,11 @@ ivas_error ivas_corecoder_enc_reconfig( st_ivas->hCPE[0]->hCoreCoder[n]->bits_frame_nominal * FRAMES_PER_SEC, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); - +#ifdef IVAS_FLOAT_FIXED + IF( ( error = IGF_Reconfig_fx( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) +#else if ( ( error = IGF_Reconfig( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) +#endif { return error; } @@ -472,7 +476,11 @@ ivas_error ivas_corecoder_enc_reconfig( st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ); +#ifdef IVAS_FLOAT_FIXED + IF( ( error = IGF_Reconfig_fx( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) +#else if ( ( error = IGF_Reconfig( &st_ivas->hCPE[0]->hCoreCoder[n]->hIGFEnc, st_ivas->hCPE[0]->hCoreCoder[n]->igf, 1, st_ivas->hCPE[0]->element_brate, st_ivas->hCPE[0]->hCoreCoder[n]->bwidth, st_ivas->hCPE[0]->hCoreCoder[n]->element_mode, st_ivas->hCPE[0]->hCoreCoder[n]->rf_mode ) ) != IVAS_ERR_OK ) +#endif { return error; } diff --git a/lib_enc/ivas_cpe_enc.c b/lib_enc/ivas_cpe_enc.c index b1d026f59..f67966815 100644 --- a/lib_enc/ivas_cpe_enc.c +++ b/lib_enc/ivas_cpe_enc.c @@ -88,6 +88,7 @@ ivas_error ivas_cpe_enc( 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 */ + Word16 fft_exp; #endif float ener[CPE_CHANNELS]; /* residual energy from Levinson-Durbin */ float relE[CPE_CHANNELS]; /* frame relative energy */ @@ -108,23 +109,29 @@ ivas_error ivas_cpe_enc( float old_wsp[CPE_CHANNELS][L_WSP]; /* old weighted input signal */ float pitch_fr[CPE_CHANNELS][NB_SUBFR]; /* fractional pitch values */ float voicing_fr[CPE_CHANNELS][NB_SUBFR]; /* fractional pitch gains */ + Word16 pitch_fr_fx[CPE_CHANNELS][NB_SUBFR]; /* Q6, fractional pitch values */ + Word16 voicing_fr_fx[CPE_CHANNELS][NB_SUBFR]; /* Q15, fractional pitch gains */ int16_t loc_harm[CPE_CHANNELS]; /* harmonicity flag */ float cor_map_sum[CPE_CHANNELS]; /* speech/music clasif. parameter */ int16_t vad_flag_dtx[CPE_CHANNELS]; /* HE-SAD flag with additional DTX HO */ float enerBuffer[CPE_CHANNELS][CLDFB_NO_CHANNELS_MAX]; /* energy buffer */ float currFlatness[CPE_CHANNELS]; /* flatness parameter */ - float fft_buff[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ - int16_t tdm_ratio_idx, tdm_ratio_idx_SM; /* temp. TD stereo parameters */ - int16_t tdm_SM_or_LRTD_Pri; /* temp. TD stereo parameters */ - float tdm_last_ratio; /* temp. TD stereo parameters */ - int16_t nb_bits; /* number of DFT stereo side bits */ - float fr_bands[CPE_CHANNELS][2 * NB_BANDS]; /* energy in frequency bands */ - float Etot_LR[CPE_CHANNELS]; /* total energy */ - float lf_E[CPE_CHANNELS][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ - int16_t localVAD_HE_SAD[CPE_CHANNELS]; /* HE-SAD flag without hangover, LR channels */ - float band_energies_LR[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ +#ifdef IVAS_FLOAT_FIXED + Word16 currFlatness_fx[CPE_CHANNELS]; /* flatness parameter Q7 */ +#endif + float fft_buff[CPE_CHANNELS][2 * L_FFT]; /* FFT buffer */ + int16_t tdm_ratio_idx, tdm_ratio_idx_SM; /* temp. TD stereo parameters */ + int16_t tdm_SM_or_LRTD_Pri; /* temp. TD stereo parameters */ + float tdm_last_ratio; /* temp. TD stereo parameters */ + int16_t nb_bits; /* number of DFT stereo side bits */ + float fr_bands[CPE_CHANNELS][2 * NB_BANDS]; /* energy in frequency bands */ + float Etot_LR[CPE_CHANNELS]; /* total energy */ + float lf_E[CPE_CHANNELS][2 * VOIC_BINS]; /* per bin spectrum energy in lf */ + int16_t localVAD_HE_SAD[CPE_CHANNELS]; /* HE-SAD flag without hangover, LR channels */ + float band_energies_LR[2 * NB_BANDS]; /* energy in critical bands without minimum noise floor E_MIN */ float orig_input[CPE_CHANNELS][L_FRAME48k]; float Etot_last[CPE_CHANNELS]; + Word16 Etot_last_fx[CPE_CHANNELS]; int32_t tmp, input_Fs; int16_t max_bwidth, ivas_format; ENCODER_CONFIG_HANDLE hEncoderConfig; @@ -156,6 +163,10 @@ ivas_error ivas_cpe_enc( tdm_ratio_idx_SM = -1; tdm_last_ratio = 0; + set16_fx( pitch_fr_fx[0], 0, NB_SUBFR ); + set16_fx( pitch_fr_fx[1], 0, NB_SUBFR ); + set16_fx( voicing_fr_fx[0], 0, NB_SUBFR ); + set16_fx( voicing_fr_fx[1], 0, NB_SUBFR ); /*------------------------------------------------------------------* * CPE initialization - core coder @@ -299,7 +310,18 @@ ivas_error ivas_cpe_enc( { RunTransientDetection( sts[n]->input, input_frame, sts[n]->hTranDet ); } +#ifndef IVAS_FLOAT_FIXED currFlatness[n] = GetTCXAvgTemporalFlatnessMeasure( sts[n]->hTranDet, NSUBBLOCKS, 0 ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( sts[n]->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange_flt, sts[n]->hTranDet->transientDetector.pSubblockEnergies->subblockNrgChange, 7, NSUBBLOCKS + MAX_TD_DELAY ); +#endif + currFlatness_fx[n] = GetTCXAvgTemporalFlatnessMeasure_ivas_fx( sts[n]->hTranDet, NSUBBLOCKS, 0 ); + move16(); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + currFlatness[n] = fix16_to_float( currFlatness_fx[n], Q7 ); +#endif +#endif } /* Synchonize detection for downmix-based stereo */ @@ -531,7 +553,7 @@ ivas_error ivas_cpe_enc( /* Time Domain ITD compensation using extrapolation */ stereo_td_itd_fx( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd_fx, hCPE->hStereoDft->q_input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem_fx, hCPE->q_input_mem ); - stereo_dft_enc_analyze_fx( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT_fx, hCPE->input_mem_fx, hCPE->q_input_mem ); + stereo_dft_enc_analyze_fx( sts, CPE_CHANNELS, input_frame, hCPE->hStereoDft, NULL, hCPE->hStereoDft->DFT_fx, hCPE->hStereoDft->DFT_fx_e, hCPE->input_mem_fx, hCPE->q_input_mem ); #else /* Time Domain ITD compensation using extrapolation */ stereo_td_itd( hCPE->hStereoDft->hItd, hCPE->hStereoDft->input_mem_itd, hCPE->hStereoDft->hConfig->hybrid_itd_flag, hCPE->hStereoDft->dft_ovl, sts, input_frame, hCPE->input_mem ); @@ -572,7 +594,61 @@ ivas_error ivas_cpe_enc( } else if ( hCPE->element_mode == IVAS_CPE_MDCT ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) + { + FOR( int16_t i = 0; i < CPE_CHANNELS; i++ ) + { + sts[i]->q_inp = Q_factor_arr( sts[i]->old_input_signal, 1965 ); // check length + hCPE->q_input_mem[i] = Q_factor_arr( &hCPE->input_mem[i][0], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + floatToFixed_arr( sts[i]->old_input_signal, sts[i]->old_input_signal_fx, sts[i]->q_inp, 1965 ); + floatToFixed_arr( &hCPE->input_mem[i][0], &hCPE->input_mem_fx[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + } + floatToFixed_arrL( hCPE->hStereoMdct->hItd->itd, hCPE->hStereoMdct->hItd->itd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoMdct->hItd->deltaItd, hCPE->hStereoMdct->hItd->deltaItd_fx, 16, STEREO_DFT_ENC_DFT_NB ); + floatToFixed_arrL( hCPE->hStereoClassif->xtalk_fv, hCPE->hStereoClassif->xtalk_fv_fx, 15, SSC_MAX_NFEA ); + floatToFixed_arrL( hCPE->hStereoClassif->unclr_fv, hCPE->hStereoClassif->unclr_fv_fx, 15, SSC_MAX_NFEA ); + floatToFixed_arr( hCPE->hCoreCoder[0]->voicing, hCPE->hCoreCoder[0]->voicing_fx, 15, 3 ); + f2me( hCPE->hStereoClassif->ave_ener_L, &hCPE->hStereoClassif->ave_ener_L_fx, &hCPE->hStereoClassif->ave_ener_L_fx_e ); + f2me( hCPE->hStereoClassif->ave_ener_R, &hCPE->hStereoClassif->ave_ener_R_fx, &hCPE->hStereoClassif->ave_ener_R_fx_e ); + f2me( hCPE->hStereoMdct->hItd->currFlatness, &hCPE->hStereoMdct->hItd->currFlatness_fx, &hCPE->hStereoMdct->hItd->currFlatness_fx_e ); + floatToFixed_arrL( hCPE->hStereoClassif->xtalk_score_buf, hCPE->hStereoClassif->xtalk_score_buf_fx, 31, XTALK_SCORE_BUF_LEN ); + hCPE->hStereoClassif->xtalk_wscore_fx = floatToFixed( hCPE->hStereoClassif->xtalk_wscore, 31 ); + hCPE->hStereoClassif->relE_0_1_fx = floatToFixed( hCPE->hStereoClassif->relE_0_1, 31 ); + floatToFixed_arrL( hCPE->hStereoClassif->unclr_relE_0_1_LT, hCPE->hStereoClassif->unclr_relE_0_1_LT_fx, 31, UNCLR_RC_ORDER ); + hCPE->hStereoClassif->unclr_wscore_fx = floatToFixed( hCPE->hStereoClassif->unclr_wscore, 31 ); + if ( hCPE->element_mode == IVAS_CPE_DFT && hCPE->hStereoDft->res_cod_mode[STEREO_DFT_OFFSET] ) + { + floatToFixed_arr( sts[1]->old_inp_12k8, sts[1]->old_inp_12k8_fx, 0, L_INP_MEM ); + } + } +#endif + stereo_td_itd_mdct_stereo_fx( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) + { + fixedToFloat_arrL( hCPE->hStereoMdct->hItd->itd_fx, hCPE->hStereoMdct->hItd->itd, 16, STEREO_DFT_ENC_DFT_NB ); + fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_fv_fx, hCPE->hStereoClassif->xtalk_fv, 15, SSC_MAX_NFEA ); + fixedToFloat_arrL( hCPE->hStereoClassif->unclr_fv_fx, hCPE->hStereoClassif->unclr_fv, 15, SSC_MAX_NFEA ); + hCPE->hStereoClassif->ave_ener_L = me2f( hCPE->hStereoClassif->ave_ener_L_fx, hCPE->hStereoClassif->ave_ener_L_fx_e ); + hCPE->hStereoClassif->ave_ener_R = me2f( hCPE->hStereoClassif->ave_ener_R_fx, hCPE->hStereoClassif->ave_ener_R_fx_e ); + hCPE->hStereoClassif->xtalk_score = fixedToFloat( hCPE->hStereoClassif->xtalk_score_fx, 31 ); + fixedToFloat_arrL( hCPE->hStereoClassif->xtalk_score_buf_fx, hCPE->hStereoClassif->xtalk_score_buf, 31, XTALK_SCORE_BUF_LEN ); + hCPE->hStereoClassif->xtalk_wscore = fixedToFloat( hCPE->hStereoClassif->xtalk_wscore_fx, 31 ); + // hCPE->hStereoClassif->prev_g_IPD = fixedToFloat( hCPE->hStereoClassif->prev_g_IPD_fx, 29 ); + // hCPE->hStereoClassif->prev_IPD = fixedToFloat( hCPE->hStereoClassif->prev_IPD_fx, 29 ); + FOR( int16_t i = 0; i < CPE_CHANNELS; i++ ) + { + // hCPE->q_input_mem[i] = Q_factor_arr( &hCPE->input_mem[i][0], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + // floatToFixed_arr( sts[i]->old_input_signal, sts[i]->old_input_signal_fx, sts[i]->q_inp, 1965 ); + fixedToFloat_arr( &hCPE->input_mem_fx[i][0], &hCPE->input_mem[i][0], hCPE->q_input_mem[i], NS2SA( input_Fs, STEREO_DFT_OVL_NS ) ); + } + } +#endif +#else stereo_td_itd_mdct_stereo( hCPE, vad_flag_dtx, vad_hover_flag, input_frame ); +#endif } /*----------------------------------------------------------------* @@ -787,7 +863,36 @@ ivas_error ivas_cpe_enc( /* MDCT stereo DTX: active/inactive frame decision; compute FD CNG coherence */ if ( hCPE->element_mode == IVAS_CPE_MDCT && hEncoderConfig->Opt_DTX_ON ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 max_e = -16, tmp_e, tmp_e2; + Word16 i; + + for ( i = 0; i < 2 * L_FFT; i++ ) + { + f2me_16( fft_buff[0][i], &fft_buff_fx[0][i], &tmp_e ); + f2me_16( fft_buff[1][i], &fft_buff_fx[1][i], &tmp_e2 ); + tmp_e = max( tmp_e, tmp_e2 ); + max_e = ( max_e > tmp_e ) ? max_e : tmp_e; + } + max_e += 2; + for ( i = 0; i < 2 * L_FFT; i++ ) + { + f2me_16( fft_buff[0][i], &fft_buff_fx[0][i], &tmp_e ); + f2me_16( fft_buff[1][i], &fft_buff_fx[1][i], &tmp_e2 ); + fft_buff_fx[0][i] = shr( fft_buff_fx[0][i], max_e - tmp_e ); + fft_buff_fx[1][i] = shr( fft_buff_fx[1][i], max_e - tmp_e2 ); + } + fft_exp = max_e; +#endif + stereoFdCngCoherence_fx( sts, hCPE->last_element_mode, fft_buff_fx, fft_exp ); + +#ifdef IVAS_FLOAT_FIXED + sts[0]->hFdCngEnc->hFdCngCom->coherence_flt = fixedToFloat( sts[0]->hFdCngEnc->hFdCngCom->coherence_fx, Q15 ); +#endif +#else stereoFdCngCoherence( sts, hCPE->last_element_mode, fft_buff ); +#endif /* Reset metadata */ if ( sts[0]->cng_sba_flag || ( ivas_format == SBA_FORMAT ) ) @@ -799,7 +904,27 @@ ivas_error ivas_cpe_enc( /*----------------------------------------------------------------* * Core codec configuration *----------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + /* IGF reconfiguration */ + FOR( n = 0; n < n_CoreChannels; n++ ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( NE_32( hCPE->last_element_brate, hCPE->element_brate ) || NE_16( hCPE->element_mode, hCPE->last_element_mode ) || ( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) && NE_16( sts[0]->bits_frame_nominal, last_bits_frame_nominal ) ) || NE_16( sts[n]->last_bwidth, sts[n]->bwidth ) ) && ( n == 0 || EQ_16( hCPE->element_mode, IVAS_CPE_MDCT ) ) ) + { + Word16 igf; + igf = getIgfPresent_fx( sts[n]->element_mode, L_mult0( sts[n]->bits_frame_nominal, FRAMES_PER_SEC ), sts[n]->max_bwidth, sts[n]->rf_mode ); + IF( NE_32( ( error = IGF_Reconfig_fx( &sts[n]->hIGFEnc, igf, 0, L_mult0( sts[n]->bits_frame_nominal, FRAMES_PER_SEC ), sts[n]->max_bwidth, sts[n]->element_mode, sts[n]->rf_mode ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } +#else /* IGF reconfiguration */ for ( n = 0; n < n_CoreChannels; n++ ) { @@ -813,7 +938,7 @@ ivas_error ivas_cpe_enc( } } } - +#endif if ( hCPE->element_mode == IVAS_CPE_MDCT && st_ivas->hMCT == NULL ) { /* set coded BW for MDCT stereo */ @@ -855,9 +980,46 @@ ivas_error ivas_cpe_enc( /* configure TD stereo encoder */ if ( hCPE->element_mode == IVAS_CPE_TD ) { - tdm_ol_pitch_comparison( hCPE, pitch_fr, voicing_fr ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( pitch_fr[0], pitch_fr_fx[0], Q6, NB_SUBFR ); + floatToFixed_arr( pitch_fr[1], pitch_fr_fx[1], Q6, NB_SUBFR ); + floatToFixed_arr( voicing_fr[0], voicing_fr_fx[0], Q15, NB_SUBFR ); + floatToFixed_arr( voicing_fr[1], voicing_fr_fx[1], Q15, NB_SUBFR ); + floatToFixed_arr( hCPE->hCoreCoder[0]->voicing, hCPE->hCoreCoder[0]->voicing_fx, Q15, 3 ); + floatToFixed_arr( hCPE->hCoreCoder[1]->voicing, hCPE->hCoreCoder[1]->voicing_fx, Q15, 3 ); + hCPE->hCoreCoder[0]->old_corr_fx = float_to_fix16( hCPE->hCoreCoder[0]->old_corr, Q15 ); + hCPE->hCoreCoder[0]->old_thres_fx = float_to_fix16( hCPE->hCoreCoder[0]->old_thres, Q15 ); +#endif + + tdm_ol_pitch_comparison_fx( hCPE, pitch_fr_fx, voicing_fr_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( pitch_fr_fx[0], pitch_fr[0], Q6, NB_SUBFR ); + fixedToFloat_arr( pitch_fr_fx[1], pitch_fr[1], Q6, NB_SUBFR ); + fixedToFloat_arr( voicing_fr_fx[0], voicing_fr[0], Q15, NB_SUBFR ); + fixedToFloat_arr( voicing_fr_fx[1], voicing_fr[1], Q15, NB_SUBFR ); + fixedToFloat_arr( hCPE->hCoreCoder[0]->voicing_fx, hCPE->hCoreCoder[0]->voicing, Q15, 3 ); + fixedToFloat_arr( hCPE->hCoreCoder[1]->voicing_fx, hCPE->hCoreCoder[1]->voicing, Q15, 3 ); + hCPE->hCoreCoder[1]->old_corr = fix16_to_float( hCPE->hCoreCoder[1]->old_corr_fx, Q15 ); + hCPE->hCoreCoder[1]->old_thres = fix16_to_float( hCPE->hCoreCoder[1]->old_thres_fx, Q15 ); +#endif +#else + tdm_ol_pitch_comparison( hCPE, pitch_fr, voicing_fr ); +#endif +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Etot_last_fx[0] = float_to_fix16( Etot_last[0], Q8 ); + Etot_last_fx[1] = float_to_fix16( Etot_last[1], Q8 ); +#endif + tdm_configure_enc_fx( ivas_format, st_ivas->ism_mode, hCPE, Etot_last_fx, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + sts[0]->hSpMusClas->tdm_lt_Etot = fix16_to_float( sts[0]->hSpMusClas->tdm_lt_Etot_fx, Q8 ); + sts[1]->hSpMusClas->tdm_lt_Etot = fix16_to_float( sts[1]->hSpMusClas->tdm_lt_Etot_fx, Q8 ); +#endif +#else tdm_configure_enc( ivas_format, st_ivas->ism_mode, hCPE, Etot_last, tdm_SM_or_LRTD_Pri, tdm_ratio_idx, tdm_ratio_idx_SM, attack_flag[0], nb_bits_metadata ); +#endif if ( hEncoderConfig->Opt_DTX_ON ) { diff --git a/lib_enc/ivas_enc.c b/lib_enc/ivas_enc.c index d37b71664..479c7a5a5 100644 --- a/lib_enc/ivas_enc.c +++ b/lib_enc/ivas_enc.c @@ -741,21 +741,23 @@ ivas_error ivas_enc( test(); IF( ( EQ_32( ivas_format, SBA_FORMAT ) ) && !( GT_16( st_ivas->sba_analysis_order, 1 ) ) ) { +#ifndef IVAS_FLOAT_FIXED hp20_flt( data_f[HOA_keep_ind[st_ivas->hSpar->hMdEnc->HOA_md_ind[i]]], input_frame, st_ivas->mem_hp20_in[i], input_Fs ); -#if 0 // To be enabled, precision loss observed +#else hp20_fix32( data_fx[HOA_keep_ind[st_ivas->hSpar->hMdEnc->HOA_md_ind[i]]], input_frame, st_ivas->mem_hp20_in_fx[i], input_Fs ); #endif } ELSE IF( !( EQ_32( ivas_format, MC_FORMAT ) && EQ_16( i, LFE_CHANNEL ) ) ) { +#ifndef IVAS_FLOAT_FIXED hp20_flt( data_f[i], input_frame, st_ivas->mem_hp20_in[i], input_Fs ); // To be removed -#if 0 // To be enabled, precision loss observed +#else hp20_fix32( data_fx[i], input_frame, st_ivas->mem_hp20_in_fx[i], input_Fs ); #endif } } -#if 0 /* Fixed to float conversion To be removed */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS for ( i = 0; i < n; i++ ) { fixedToFloat_arrL( data_fx[i], data_f[i], st_ivas->q_data_fx, input_frame ); diff --git a/lib_enc/ivas_ism_enc.c b/lib_enc/ivas_ism_enc.c index 714a1c62d..fbd42a4fa 100644 --- a/lib_enc/ivas_ism_enc.c +++ b/lib_enc/ivas_ism_enc.c @@ -658,6 +658,11 @@ ivas_error ivas_ism_enc( floatToFixed_arr16( st_ivas->hISMDTX->coh, st_ivas->hISMDTX->coh_fx, Q15, st_ivas->nchan_transport ); } } + FOR( int ch = 0; ch < st_ivas->hEncoderConfig->nchan_ism; ch++ ) + { + st_ivas->hIsmMetaData[ch]->azimuth_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->azimuth, Q22 ); + st_ivas->hIsmMetaData[ch]->elevation_fx = floatToFixed( st_ivas->hIsmMetaData[ch]->elevation, Q22 ); + } /*================flt-to-fix===================================*/ #endif ivas_ism_metadata_sid_enc( st_ivas->hISMDTX, flag_noisy_speech, nchan_ism, st_ivas->nchan_transport, st_ivas->ism_mode, st_ivas->hIsmMetaData, sid_flag, md_diff_flag, st_ivas->hSCE[st_ivas->nSCE - 1]->hMetaData, nb_bits_metadata ); @@ -877,7 +882,7 @@ FOR( sce_id = 0; sce_id < nchan_transport_ism; sce_id++ ) { Word16 igf; igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->rf_mode ); - IF( NE_32( ( error = IGF_Reconfig( &st->hIGFEnc, igf, 0, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) + IF( NE_32( ( error = IGF_Reconfig_fx( &st->hIGFEnc, igf, 0, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) { return error; } diff --git a/lib_enc/ivas_ism_metadata_enc.c b/lib_enc/ivas_ism_metadata_enc.c index 5c0165618..fdd17fa68 100644 --- a/lib_enc/ivas_ism_metadata_enc.c +++ b/lib_enc/ivas_ism_metadata_enc.c @@ -2616,7 +2616,7 @@ void ivas_ism_metadata_sid_enc( { IF( EQ_16( ch, hISMDTX->sce_id_dtx ) ) { - continue; + CONTINUE; } Word32 tmp = Mpy_32_32( L_shr( L_deposit_h( hISMDTX->coh_fx[ch] ), 1 ) /*Q30*/, L_deposit_h( sub( shl( 1, nBits_coh ), 1 ) ) ); // Q15 Word32 tmp_2 = L_add( tmp, 16384 /*0.5f in Q15*/ ); @@ -2638,10 +2638,6 @@ void ivas_ism_metadata_sid_enc( hIsmMetaData = hIsmMeta[ch]; #ifdef IVAS_FLOAT_FIXED - /*===============================flt-2-fix======================================*/ - hIsmMetaData->azimuth_fx = floatToFixed( hIsmMetaData->azimuth, Q22 ); - hIsmMetaData->elevation_fx = floatToFixed( hIsmMetaData->elevation, Q22 ); - /*===============================flt-2-fix======================================*/ idx_azimuth = ism_quant_meta_fx( hIsmMetaData->azimuth_fx, &valQ_fx, ism_azimuth_borders_fx, q_step_fx, q_step_border_fx, 1 << nBits_azimuth ); idx_elevation = ism_quant_meta_fx( hIsmMetaData->elevation_fx, &valQ_fx, ism_elevation_borders_fx, q_step_fx, q_step_border_fx, 1 << nBits_elevation ); #else diff --git a/lib_enc/ivas_mct_core_enc.c b/lib_enc/ivas_mct_core_enc.c index 788eee3ba..48a988970 100644 --- a/lib_enc/ivas_mct_core_enc.c +++ b/lib_enc/ivas_mct_core_enc.c @@ -43,6 +43,7 @@ #include "prot_fx_enc.h" #include "ivas_prot_fx.h" #include "prot_fx.h" +#include #endif @@ -761,7 +762,7 @@ void ivas_mct_core_enc( float *mdst_spectrum[MCT_MAX_CHANNELS][2] = { NULL }; float inv_spectrum_long[MCT_MAX_CHANNELS][L_FRAME48k]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ #if 0 - Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ + Word32 *orig_spectrum_fx[MCT_MAX_CHANNELS][2]; /* Pointers to MDCT output for a short block (L/R) */ #endif Word32 powerSpec_fx[MCT_MAX_CHANNELS][L_FRAME48k]; Word32 mdst_fx; @@ -1176,7 +1177,12 @@ void ivas_mct_core_enc( { if ( hMCT->currBlockDataCnt > 0 ) { +#ifdef IVAS_FLOAT_FIXED_ + /* High MLD cases are observed */ + mctStereoIGF_enc_fx( hMCT, sts, orig_spectrum_fx, powerSpec_fx, powerSpecMsInv_fx, inv_spectrum_fx, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, sp_aud_decision0 ); +#else mctStereoIGF_enc( hMCT, sts, orig_spectrum, powerSpec, powerSpecMsInv, inv_spectrum, sp_aud_decision0 ); +#endif // IVAS_FLOAT_FIXED } else { @@ -1201,7 +1207,150 @@ void ivas_mct_core_enc( { for ( n = 0; n < nSubframes; n++ ) { +#ifdef IVAS_FLOAT_FIXED_ + /* High MLD cases are observed */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[ch][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[ch][n], orig_spectrum_fx[ch][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + // Word32 powerSpec_fx[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + Word16 q_powerSpec; + q_powerSpec = L_get_q_buf1( &powerSpec[ch][n * L_subframeTCX], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( &powerSpec[ch][n * L_subframeTCX], &powerSpec_fx[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + floatToFixed_arr16( &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold_flt[0][0], &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + fixedToFloat_arrL32( &powerSpec_fx[ch][n * L_subframeTCX], &powerSpec[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + 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, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - 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, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); +#endif } } } diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index eca4da639..15bb49b78 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -160,6 +160,61 @@ static void map_input_to_cpe_channels( return; } +static void map_input_to_cpe_channels_ivas_fx( + const Encoder_Struct *st_ivas, /* i/o: IVAS encoder structure */ + Word32 *pdata[MAX_INPUT_CHANNELS], /* o : mapped input pointers */ + Word32 *data[MCT_MAX_CHANNELS] /* i : input channel data Qx */ +) +{ + Word16 i, n; + Word16 nchan_transport; + + nchan_transport = st_ivas->nchan_transport; + test(); + IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, SBA_ISM_FORMAT ) && EQ_32( st_ivas->ism_mode, ISM_SBA_MODE_DISC ) ) + { + nchan_transport = add( nchan_transport, st_ivas->hEncoderConfig->nchan_ism ); + } + i = 0; + move16(); + + FOR( n = 0; n < LFE_CHANNEL - 1; n++ ) + { + pdata[i] = data[n]; + i = add( i, 1 ); + } + test(); + test(); + IF( EQ_32( st_ivas->hEncoderConfig->ivas_format, MC_FORMAT ) && ( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) || EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) ) + { + FOR( n = LFE_CHANNEL + 1; n < nchan_transport; n++ ) + { + pdata[i] = data[n]; + i = add( i, 1 ); + } + pdata[i] = data[LFE_CHANNEL - 1]; + } + ELSE + { + FOR( ; n < nchan_transport; n++ ) + { + pdata[i] = data[n]; + i = add( i, 1 ); + } + } + + /* odd channel CPE*/ + test(); + test(); + test(); + IF( ( LT_16( nchan_transport, i_mult( st_ivas->nCPE, CPE_CHANNELS ) ) ) || ( ( EQ_32( st_ivas->mc_mode, MC_MODE_MCT ) || EQ_32( st_ivas->mc_mode, MC_MODE_PARAMUPMIX ) ) && LT_16( st_ivas->hMCT->nchan_out_woLFE, i_mult( st_ivas->nCPE, CPE_CHANNELS ) ) ) ) + { + pdata[st_ivas->nCPE * CPE_CHANNELS - 1] = NULL; + } + + return; +} + /*-------------------------------------------------------------------* * ivas_mct_enc() @@ -391,7 +446,45 @@ ivas_error ivas_mct_enc( switch_bw = set_bw_mct_fx( st_ivas->hCPE, st_ivas->nCPE ); /*for MC and MCT remove pointer to LFE input that has been processed separately */ +#ifndef IVAS_FLOAT_FIXED map_input_to_cpe_channels( st_ivas, pdata, data ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 *pdata_fx[MAX_INPUT_CHANNELS]; + Word32 data_fx_tmp[MCT_MAX_CHANNELS][960]; + Word32 *data_fx[MCT_MAX_CHANNELS]; + Word16 nchan_transport; + for ( int i = 0; i < MAX_INPUT_CHANNELS; i++ ) + { + pdata_fx[i] = NULL; + pdata[i] = NULL; + } + Word16 len = (Word16) ( st_ivas->hEncoderConfig->input_Fs / FRAMES_PER_SEC ); + nchan_transport = st_ivas->nchan_transport; + if ( st_ivas->hEncoderConfig->ivas_format == SBA_ISM_FORMAT && st_ivas->ism_mode == ISM_SBA_MODE_DISC ) + { + nchan_transport += st_ivas->hEncoderConfig->nchan_ism; + } + + for ( int i = 0; i < nchan_transport; i++ ) + { + data_fx[i] = data_fx_tmp[i]; + floatToFixed_arrL( data[i], data_fx[i], Q11, len ); + } + map_input_to_cpe_channels( st_ivas, pdata, data ); +#endif + map_input_to_cpe_channels_ivas_fx( st_ivas, pdata_fx, data_fx ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int i = 0; i < MCT_MAX_CHANNELS; i++ ) + { + if ( pdata_fx[i] == NULL ) + { + continue; + } + fixedToFloat_arrL( pdata_fx[i], pdata[i], Q11, len ); + } +#endif +#endif /* pre-processing */ FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) @@ -728,7 +821,36 @@ ivas_error mct_enc_reconfigure( { st_ivas->hCPE[st_ivas->nCPE - 1]->hCoreCoder[1]->mct_chan_mode = MCT_CHAN_MODE_IGNORE; } +#ifdef IVAS_FLOAT_FIXED + /* set correct nominal bitrates and igf config already here, otherwise we + * run into a number of problems; only do it when the bitrate changes */ + IF( NE_32( ivas_total_brate, st_ivas->hEncoderConfig->last_ivas_total_brate ) ) + { + FOR( cpe_id = 0; cpe_id < st_ivas->nCPE; cpe_id++ ) + { + FOR( n = 0; n < CPE_CHANNELS; n++ ) + { + st = st_ivas->hCPE[cpe_id]->hCoreCoder[n]; + + st->total_brate = st_ivas->hCPE[cpe_id]->element_brate; + move32(); + IF( NE_32( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) + { + st->bits_frame_nominal = extract_l( Mpy_32_32( st_ivas->hCPE[cpe_id]->element_brate, ONE_BY_FRAMES_PER_SEC_Q31 ) ); + move16(); + st->igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->bwidth, st->rf_mode ); + move16(); + + IF( NE_32( ( error = IGF_Reconfig_fx( &st->hIGFEnc, st->igf, 1, st_ivas->hCPE[cpe_id]->element_brate, st->bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) + { + return error; + } + } + } + } + } +#else /* set correct nominal bitrates and igf config already here, otherwise we * run into a number of problems; only do it when the bitrate changes */ if ( ivas_total_brate != st_ivas->hEncoderConfig->last_ivas_total_brate ) @@ -754,7 +876,7 @@ ivas_error mct_enc_reconfigure( } } } - +#endif /* Initialize MCT block data */ max_blocks = hMCT->nchan_out_woLFE / CPE_CHANNELS; diff --git a/lib_enc/ivas_mct_enc_mct.c b/lib_enc/ivas_mct_enc_mct.c index a0c1435b9..2a200c8a4 100644 --- a/lib_enc/ivas_mct_enc_mct.c +++ b/lib_enc/ivas_mct_enc_mct.c @@ -38,6 +38,9 @@ #include "ivas_prot_fx.h" #include "prot.h" #include "prot_fx.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#endif #include "wmc_auto.h" #include @@ -1801,7 +1804,150 @@ void mctStereoIGF_enc_fx( L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; +#ifdef IVAS_FLOAT_FIXED_ + /* High MLD cases are observed */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ( int 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 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[p_ch[ch]][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[p_ch[ch]][n], orig_spectrum_fx[p_ch[ch]][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], st->hTcxEnc->L_frameTCX / nSubframes ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, st->hTcxEnc->L_frameTCX / nSubframes ); + + // Word32 powerSpec_fx[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + Word16 q_powerSpec; + q_powerSpec = L_get_q_buf1( &powerSpec[p_ch[ch]][n * L_subframeTCX], L_subframeTCX ); + floatToFixed_arrL32( &powerSpec[p_ch[ch]][n * L_subframeTCX], &powerSpec_fx[p_ch[ch]][n * L_subframeTCX], q_powerSpec, L_subframeTCX ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[p_ch[ch]][n], &q_spectrum, &powerSpec_fx[p_ch[ch]][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, st->hTcxEnc->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( &powerSpec_fx[p_ch[ch]][n * L_subframeTCX], &powerSpec[p_ch[ch]][n * L_subframeTCX], q_powerSpec, L_subframeTCX ); + + if ( st->hIGFEnc ) + { + 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, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - 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 ( int 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, st->hTcxEnc->spectrum[n], (float *) orig_spectrum[p_ch[ch]][n], &powerSpec[p_ch[ch]][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch1], 0 ); +#endif } } } @@ -1830,7 +1976,150 @@ void mctStereoIGF_enc_fx( nSubframes = st->hTcxEnc->tcxMode == TCX_20 ? 1 : NB_DIV; for ( n = 0; n < nSubframes; n++ ) { +#ifdef IVAS_FLOAT_FIXED_ + /* High MLD cases are observed */ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ( int 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 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[ch][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[ch][n], orig_spectrum_fx[ch][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], st->hTcxEnc->L_frameTCX / nSubframes ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, st->hTcxEnc->L_frameTCX / nSubframes ); + + // Word32 powerSpec_fx[N_MAX + L_MDCT_OVLP_MAX]; /* Buffer for TCX20/TCX10 windowing */ + Word16 q_powerSpec; + q_powerSpec = L_get_q_buf1( &powerSpec[ch][n * L_subframeTCX], L_subframeTCX ); + floatToFixed_arrL32( &powerSpec[ch][n * L_subframeTCX], &powerSpec_fx[ch][n * L_subframeTCX], q_powerSpec, L_subframeTCX ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, st->hTcxEnc->L_frameTCX / nSubframes ); + fixedToFloat_arrL32( &powerSpec_fx[ch][n * L_subframeTCX], &powerSpec[ch][n * L_subframeTCX], q_powerSpec, L_subframeTCX ); + + if ( st->hIGFEnc ) + { + 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, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - 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 ( int 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, st->hTcxEnc->spectrum[n], (float *) orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, sp_aud_decision0[ch], 0 ); +#endif } } } diff --git a/lib_enc/ivas_sce_enc.c b/lib_enc/ivas_sce_enc.c index 453d08ba4..e50d1d9b3 100644 --- a/lib_enc/ivas_sce_enc.c +++ b/lib_enc/ivas_sce_enc.c @@ -254,27 +254,43 @@ ivas_error ivas_sce_enc( { ivas_write_format_sid( ivas_format, IVAS_SCE, st->hBstr ); } + + /*----------------------------------------------------------------* + * Core codec configuration + *----------------------------------------------------------------*/ + + /* IGF reconfiguration */ + if ( hSCE->last_element_brate != hSCE->element_brate || st->last_bwidth != st->bwidth ) + { + int16_t igf; + igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->rf_mode ); + if ( ( error = IGF_Reconfig( &st->hIGFEnc, igf, 0, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->element_mode, st->rf_mode ) ) != IVAS_ERR_OK ) + { + return error; + } + } #else IF( EQ_32( st->core_brate, SID_2k40 ) ) { ivas_write_format_sid_fx( ivas_format, IVAS_SCE, st->hBstr ); } -#endif /*----------------------------------------------------------------* * Core codec configuration *----------------------------------------------------------------*/ /* IGF reconfiguration */ - if ( hSCE->last_element_brate != hSCE->element_brate || st->last_bwidth != st->bwidth ) + test(); + IF( hSCE->last_element_brate != hSCE->element_brate || st->last_bwidth != st->bwidth ) { - int16_t igf; - igf = getIgfPresent( st->element_mode, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->rf_mode ); - if ( ( error = IGF_Reconfig( &st->hIGFEnc, igf, 0, st->bits_frame_nominal * FRAMES_PER_SEC, st->max_bwidth, st->element_mode, st->rf_mode ) ) != IVAS_ERR_OK ) + Word16 igf; + igf = getIgfPresent_fx( st->element_mode, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->rf_mode ); + IF( NE_32( ( error = IGF_Reconfig_fx( &st->hIGFEnc, igf, 0, L_mult0( st->bits_frame_nominal, FRAMES_PER_SEC ), st->max_bwidth, st->element_mode, st->rf_mode ) ), IVAS_ERR_OK ) ) { return error; } } +#endif /* set ACELP@12k8 / ACELP@16k flag for flexible ACELP core */ if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index fd9daf546..5366e0957 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -569,16 +569,22 @@ typedef struct stereo_tca_enc_data_structure float memChanL_DS[ADDED_MEM_DS]; /* left channel input speech memory for downmix */ float memChanR_DS[ADDED_MEM_DS]; /* right channel input speech memory for downmix */ +#ifndef IVAS_FLOAT_FIXED float mem_tempF; - float memdecim[12]; /* memory for pre-rmphasis filter for resampling */ +#endif + float memdecim[12]; /* memory for pre-rmphasis filter for resampling */ +#ifndef IVAS_FLOAT_FIXED float corrEstPrev[3][2 * L_NCSHIFT_DS + 1]; /* Prev correlation vector */ float corrEstLT[2 * L_NCSHIFT_DS + 1]; /* Long term correlation vector smoothed */ - float ica_envVarLT; +#endif + +#ifndef IVAS_FLOAT_FIXED float C_mem[2 * L_NCSHIFT_DS + 1]; float E1_mem, E2_mem; float delay_0_mem[MAX_DELAYREGLEN]; float smooth_dist_reg_prv_corr; +#endif Word32 memChanL_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH]; /* left channel input to correct at the cross-over */ Word32 memChanR_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH]; /* right channel input to correct at the cross-over */ @@ -586,15 +592,23 @@ typedef struct stereo_tca_enc_data_structure Word32 memChanL_DS_fx[ADDED_MEM_DS]; /* left channel input speech memory for downmix */ Word32 memChanR_DS_fx[ADDED_MEM_DS]; /* right channel input speech memory for downmix */ Word32 mem_tempF_fx; + Word16 mem_tempF_exp; Word32 memdecim_fx[12]; /* memory for pre-rmphasis filter for resampling */ Word32 corrEstPrev_fx[3][2 * L_NCSHIFT_DS + 1]; /* Prev correlation vector */ - Word32 corrEstLT_fx[2 * L_NCSHIFT_DS + 1]; /* Long term correlation vector smoothed */ + Word16 corrEstPrev_exp; + Word32 corrEstLT_fx[2 * L_NCSHIFT_DS + 1]; /* Long term correlation vector smoothed */ + Word16 corrEstLT_exp; - Word32 ica_envVarLT_fx; // Q20 + Word32 ica_envVarLT_fx; + Word16 ica_envVarLT_exp; Word32 C_mem_fx[2 * L_NCSHIFT_DS + 1]; + Word16 C_mem_exp[2 * L_NCSHIFT_DS + 1]; Word32 E1_mem_fx, E2_mem_fx; + Word16 E1_E2_mem_exp; Word32 delay_0_mem_fx[MAX_DELAYREGLEN]; - Word16 smooth_dist_reg_prv_corr_fx; + Word16 delay_0_mem_exp; + Word32 smooth_dist_reg_prv_corr_fx; + Word16 smooth_dist_reg_prv_corr_exp; Word16 LRTD_G_ATT_cnt; @@ -701,6 +715,7 @@ typedef struct ivas_stereo_classifier_data_structure float sp_div_ch1; float ps_diff_ch1, ps_diff_ch2; Word32 ps_diff_ch1_fx, ps_diff_ch2_fx; + Word16 ps_diff_ch1_e, ps_diff_ch2_e; float ps_sta_ch1, ps_sta_ch2; float prev_g_IPD; float prev_IPD; @@ -743,26 +758,39 @@ typedef struct ivas_stereo_classifier_data_structure // Above needs to remove once everything done Word32 voicing_ch1_fx[3]; + Word16 voicing_ch1_e; Word32 cor_map_sum_ch1_fx; + Word16 cor_map_sum_ch1_e; Word32 lsf_ch1_fx[M]; Word32 lepsP_ch1_fx; + Word16 lepsP_ch1_e; Word32 dE1_ch1_fx, dE1_ch2_fx; + Word16 dE1_ch1_e, dE1_ch2_e; Word32 nchar_ch1_fx, nchar_ch2_fx; + Word16 nchar_ch1_e, nchar_ch2_e; Word32 non_sta_ch1_fx; + Word16 non_sta_ch1_e; Word32 sp_div_ch1_fx; + Word16 sp_div_ch1_e; Word32 ps_sta_ch1_fx, ps_sta_ch2_fx; + Word16 ps_sta_ch1_e, ps_sta_ch2_e; Word32 prev_g_IPD_fx; // Q29 Word32 prev_IPD_fx; // Q29 Word32 prev_ratio_m1_m2_fx; // Q31 Word32 ratio_L_fx; + Word16 ratio_L_e; Word32 ave_ener_L_fx; /* average energy of the L channel Q(31-ave_ener_L_fx_e) */ Word16 ave_ener_L_fx_e; /* average energy of the L channel */ Word32 ave_ener_R_fx; /* average energy of the R channel Q(31-ave_ener_R_fx_e) */ Word16 ave_ener_R_fx_e; /* average energy of the R channel */ Word32 Etot_dn_fx; /* average energy in dB - lower bound */ + Word16 Etot_dn_e; /* average energy in dB - lower bound */ Word32 Etot_up_fx; /* average energy in dB - upper bound */ + Word16 Etot_up_e; /* average energy in dB - upper bound */ Word32 relE_buf_fx[UNCLR_L_RELE]; /* running buffer for relative energy Q31 */ + Word16 relE_buf_e; /* running buffer for relative energy Q31 */ Word32 Etot_buf_fx[UNCLR_L_ETOT]; /* running buffer for average energy in dB */ + Word16 e_Etot_buf_fx; /* exponent for Etot_buf_fx*/ Word32 relE_0_1_fx; /* relative energy in the current frame normalized to (0,1) Q31 */ Word32 relE_0_1_LT_fx; // Q31 Word32 unclr_relE_0_1_LT_fx[UNCLR_RC_ORDER]; // Q31 diff --git a/lib_enc/ivas_stereo_classifier.c b/lib_enc/ivas_stereo_classifier.c index 1d5624037..9eddc2fc4 100644 --- a/lib_enc/ivas_stereo_classifier.c +++ b/lib_enc/ivas_stereo_classifier.c @@ -42,7 +42,7 @@ #include "ivas_cnst.h" #include "wmc_auto.h" #include "prot_fx.h" - +#include "ivas_prot_fx.h" /*-------------------------------------------------------------------* * Local constants @@ -254,6 +254,7 @@ void stereo_classifier_init( hStereoClassif->ps_sta_ch2_fx = 0; #endif hStereoClassif->ps_diff_ch1 = 0.0f; + hStereoClassif->ps_diff_ch2 = 0.0f; hStereoClassif->ps_sta_ch1 = 0.0f; hStereoClassif->ps_sta_ch2 = 0.0f; @@ -412,7 +413,416 @@ void stereo_classifier_init_fx( * * Collect features for stereo classifiers *-----------------------------------------------------------------*/ +/* Information on ouputs: +hStereoClassif->Etot_buf_fx has expoenent hStereoClassif->e_Etot_buf_fx +hStereoClassif->relE_buf_fx has expoenent hStereoClassif->relE_buf_e +hStereoClassif->lsf_ch1_fx has exponent 16 +hStereoClassif->xtalk_fv_fx has exponent 16 +hStereoClassif->voicing_ch1_fx has exponent hStereoClassif->voicing_ch1_e +hStereoClassif->lepsP_ch1_fx has exponent 16 +hStereoClassif->Etot_up_fx has exponent hStereoClassif->Etot_up_e +hStereoClassif->Etot_dn_fx has exponent hStereoClassif->Etot_dn_e +hStereoClassif->relE_0_1_fx has exponent hStereoClassif->relE_buf_e +hStereoClassif->relE_0_1_LT_fx has exponent hStereoClassif->relE_buf_e +hStereoClassif->cor_map_sum_ch1_fx has exponent hStereoClassif->cor_map_sum_ch1_e +hStereoClassif->non_sta_ch1_fx has exponent hStereoClassif->non_sta_ch1_e +hStereoClassif->sp_div_ch1_fx has exponent hStereoClassif->sp_div_ch1_e +hStereoClassif->nchar_ch1_fx has exponent hStereoClassif->nchar_ch1_e +hStereoClassif->nchar_ch2_fx has exponent hStereoClassif->nchar_ch2_e +hStereoClassif->dE1_ch1_fx has exponent hStereoClassif->dE1_ch1_e +hStereoClassif->dE1_ch2_fx has exponent hStereoClassif->dE1_ch2_e +hStereoClassif->ps_diff_ch1_fx has exponent hStereoClassif->ps_diff_ch1_e +hStereoClassif->ps_sta_ch1_fx has exponent hStereoClassif->ps_sta_ch1_e +hStereoClassif->ps_diff_ch2_fx has exponent hStereoClassif->ps_diff_ch2_e +hStereoClassif->ps_sta_ch2_fx has exponent hStereoClassif->ps_sta_ch2_e +*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_classifier_features_ivas_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ + const Word16 idchan, /* i : channel ID */ + const Word16 element_mode, /* i : element mode */ + const Word16 vad_flag, /* i : VAD flag */ + Word32 lsf_new_fx[], /* i : LSFs at the end of the frame */ + Word32 epsP_fx[], /* i : LP analysis residual energies for each iteration*/ + Word16 pitch[], /*q0 i : open-loop pitch values for quantiz. */ + Word16 voicing_fx[], /* i : OL maximum normalized correlation */ + Word32 cor_map_sum_fx, /* i : speech/music clasif. parameter */ + Word32 non_staX_fx, /* i : unbound non-stationarity for sp/mu clas. */ + Word32 sp_div_fx, /* i : spectral diversity feature */ + const Word16 clas, /* i : signal class */ + Word16 epsP_e, /*exponent for epsP_fx */ + Word16 voicing_e, /*exponent for voicing_fx */ + Word16 cor_map_sum_e, /*exponent for cor_map_sum_fx */ + Word16 non_staX_e, /*exponent for non_staX_fx */ + Word16 sp_div_e /*exponent for sp_div_fx */ +) +{ + Word16 i, clas_ch2; + Word16 e_relE_0_1_fx; + Word16 ener_e; + Word32 lepsP_ch2_fx, ener_l_fx, ener_r_fx; + /* combine VAD flags from both channels */ + IF( idchan == 0 ) + { + hStereoClassif->vad_flag_glob = vad_flag; + } + ELSE + { + hStereoClassif->vad_flag_glob = s_or( hStereoClassif->vad_flag_glob, vad_flag ); + } + move16(); + + test(); + test(); + test(); + IF( ( EQ_16( element_mode, IVAS_CPE_DFT ) && idchan == 0 ) || ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( idchan, 1 ) ) ) + { + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->ave_ener_L_fx_e < 0 ) + { + hStereoClassif->ave_ener_L_fx = L_shl( hStereoClassif->ave_ener_L_fx, hStereoClassif->ave_ener_L_fx_e ); + hStereoClassif->ave_ener_L_fx_e = 0; + } + IF( hStereoClassif->ave_ener_R_fx_e < 0 ) + { + hStereoClassif->ave_ener_R_fx = L_shl( hStereoClassif->ave_ener_R_fx, hStereoClassif->ave_ener_R_fx_e ); + hStereoClassif->ave_ener_R_fx_e = 0; + } + move32(); + move16(); + /* update Etot_up and Etot_dn based on aEn */ + ener_l_fx = Mpy_32_16_1( BASOP_Util_Log10( L_add( L_shr( hStereoClassif->ave_ener_L_fx, 1 ), L_shr( ONE_IN_Q30, hStereoClassif->ave_ener_L_fx_e ) ), hStereoClassif->ave_ener_L_fx_e + 1 ), 10 << 11 ); /*q21*/ + ener_r_fx = Mpy_32_16_1( BASOP_Util_Log10( L_add( L_shr( hStereoClassif->ave_ener_R_fx, 1 ), L_shr( ONE_IN_Q30, hStereoClassif->ave_ener_R_fx_e ) ), hStereoClassif->ave_ener_R_fx_e + 1 ), 10 << 11 ); /*q21*/ + ener_e = 10; + move16(); + Copy32( &hStereoClassif->Etot_buf_fx[0], &hStereoClassif->Etot_buf_fx[1], UNCLR_L_ETOT - 1 ); + IF( GE_16( hStereoClassif->e_Etot_buf_fx, ener_e ) ) + { + hStereoClassif->Etot_buf_fx[0] = L_shl( L_max( 0, L_max( ener_l_fx, ener_r_fx ) ), sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); /*scaling from q25 to 31-e_Etot_buf_fx*/ + move32(); + } + ELSE + { + /*scaling Etot_buf_fx,Etot_up_fx and Etot_dn_fx to exponent ener_e*/ + hStereoClassif->Etot_buf_fx[0] = L_max( 0, L_max( ener_l_fx, ener_r_fx ) ); + hStereoClassif->Etot_buf_fx[1] = L_shr( hStereoClassif->Etot_buf_fx[1], sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->Etot_buf_fx[2] = L_shr( hStereoClassif->Etot_buf_fx[2], sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->Etot_up_fx = L_shr( hStereoClassif->Etot_up_fx, sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, sub( ener_e, hStereoClassif->e_Etot_buf_fx ) ); + hStereoClassif->e_Etot_buf_fx = ener_e; + move32(); + move32(); + move32(); + move32(); + move32(); + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + IF( EQ_16( hStereoClassif->aEn_raw[0], 6 ) || ( EQ_16( element_mode, IVAS_CPE_TD ) && EQ_16( hStereoClassif->aEn_raw[1], 6 ) ) ) + { + /* active signal, update upper bound */ + IF( LT_32( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_up_fx ) ) + { + /* energy decreases -> slower update */ + hStereoClassif->Etot_up_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_up_fx, /*0.99f Q15*/ 32440 ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 328 /*0.01f*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + ELSE + { + /* energy increases -> faster update */ + hStereoClassif->Etot_up_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_up_fx, 31130 /*0.95f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 1638 /*0.05f*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + move32(); + } + ELSE IF( ( EQ_16( element_mode, IVAS_CPE_DFT ) && hStereoClassif->aEn_raw[0] == 0 ) || + ( EQ_16( element_mode, IVAS_CPE_TD ) && hStereoClassif->aEn_raw[0] == 0 && hStereoClassif->aEn_raw[1] == 0 ) ) + { + /* inactive signal, update lower bound */ + IF( LT_32( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_dn_fx ) ) + { + /* energy decreases -> faster update */ + hStereoClassif->Etot_dn_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_dn_fx, 29491 /*0.9f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 3277 /*0.1f q15*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + ELSE + { + /* energy increases -> slower update */ + hStereoClassif->Etot_dn_fx = L_add( Mpy_32_16_1( hStereoClassif->Etot_dn_fx, 31130 /*0.95f q15*/ ), Mpy_32_16_1( hStereoClassif->Etot_buf_fx[0], 1638 /*0.05f q15*/ ) ); /*hStereoClassif->e_Etot_buf_fx*/ + } + move32(); + + IF( LT_32( hStereoClassif->Etot_dn_fx, L_shl( 30, sub( 31, hStereoClassif->e_Etot_buf_fx ) ) ) ) + { + /* do not decrease below lower bound threshold */ + hStereoClassif->Etot_dn_fx = L_shl( 30, sub( 31, hStereoClassif->e_Etot_buf_fx ) ); + move32(); + } + } + + /* upper bound is too low and close to lower bound -> update it */ + IF( LT_32( L_shr( hStereoClassif->Etot_up_fx, 1 ), L_add( L_shr( hStereoClassif->Etot_dn_fx, 1 ), L_shl( 20, sub( 30, hStereoClassif->e_Etot_buf_fx ) ) ) ) ) /*right shifted by 1 to avoid avoid overflow in addition*/ + { + hStereoClassif->Etot_dn_fx = L_shr( hStereoClassif->Etot_dn_fx, 1 ); + scale_sig32( hStereoClassif->Etot_buf_fx, 3, -1 ); + hStereoClassif->e_Etot_buf_fx = add( hStereoClassif->e_Etot_buf_fx, 1 ); + hStereoClassif->Etot_up_fx = L_add( hStereoClassif->Etot_dn_fx, L_shl( 20, sub( 31, hStereoClassif->e_Etot_buf_fx ) ) ); + move32(); + move32(); + move16(); + } + + /* normalize Etot to (0,1) */ + e_relE_0_1_fx = sub( 31, hStereoClassif->e_Etot_buf_fx ); + hStereoClassif->relE_0_1_fx = lin_interp32_fx( hStereoClassif->Etot_buf_fx[0], hStereoClassif->Etot_dn_fx, 0, hStereoClassif->Etot_up_fx, L_shr( 1932735283, hStereoClassif->e_Etot_buf_fx /*0.9f exp:Etot_buf_fx*/ ), 1, &e_relE_0_1_fx ); /*e_relE_0_1_fx is ouput exp*/ + e_relE_0_1_fx = sub( 31, e_relE_0_1_fx ); + move32(); + + /* update relE_buf */ + Copy32( &hStereoClassif->relE_buf_fx[0], &hStereoClassif->relE_buf_fx[1], UNCLR_L_RELE - 1 ); + hStereoClassif->relE_0_1_fx = L_shr( hStereoClassif->relE_0_1_fx, sub( hStereoClassif->relE_buf_e, e_relE_0_1_fx ) ); /*scaling down to exponent of e_relE_buf_fx*/ + hStereoClassif->relE_buf_fx[0] = hStereoClassif->relE_0_1_fx; /*scaling down to exponent of e_relE_buf_fx*/ + move32(); + move32(); + + IF( GE_32( hStereoClassif->relE_0_1_fx, hStereoClassif->relE_buf_fx[1] ) ) + { + hStereoClassif->relE_0_1_LT_fx = Mpy_32_16_1( hStereoClassif->relE_0_1_LT_fx, 29491 /*0.9f q15*/ ) + Mpy_32_16_1( hStereoClassif->relE_0_1_fx, 3277 /*0.1f q15*/ ); + } + ELSE + { + hStereoClassif->relE_0_1_LT_fx = Mpy_32_16_1( hStereoClassif->relE_0_1_LT_fx, 31129 /*0.95f q15*/ ) + Mpy_32_16_1( hStereoClassif->relE_0_1_fx, 1638 /*0.05f0 q15*/ ); + } + move32(); + + /* estimate VAD flag based on relative energy */ + IF( LT_32( hStereoClassif->relE_0_1_LT_fx, L_shr( 214748365, hStereoClassif->relE_buf_e ) ) ) + { + hStereoClassif->vad_relE = 0; + } + ELSE + { + hStereoClassif->vad_relE = 1; + } + move16(); + + /* combine classical VAD flag with VAD flag based on relative energy */ + hStereoClassif->vad_flag_glob = s_and( hStereoClassif->vad_flag_glob, hStereoClassif->vad_relE ); + move16(); + } + + IF( idchan == 0 ) + { + Copy32( lsf_new_fx, hStereoClassif->lsf_ch1_fx, M ); + hStereoClassif->lepsP_ch1_fx = L_shr( L_sub( BASOP_Util_Loge( L_add( epsP_fx[13], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ), BASOP_Util_Loge( L_add( epsP_fx[0], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ) ), 10 ); /*q15*/ + hStereoClassif->lepsP_ch1_e = 16; + move32(); + move16(); + + hStereoClassif->xtalk_fv_fx[E_lsf_1] = lsf_new_fx[0]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lsf_4] = lsf_new_fx[3]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lsf_9] = lsf_new_fx[8]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lsf_14] = lsf_new_fx[13]; /*q15*/ + hStereoClassif->xtalk_fv_fx[E_lepsP_13] = hStereoClassif->lepsP_ch1_fx; /*q15*/ + move32(); + move32(); + move32(); + move32(); + move32(); + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = 0; + move32(); + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->ratio_L_e < 0 ) + { + hStereoClassif->ratio_L_fx = L_shl( hStereoClassif->ratio_L_fx, hStereoClassif->ratio_L_e ); + hStereoClassif->ratio_L_e = 0; + move32(); + move16(); + } + FOR( i = 0; i < M; i++ ) + { + hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = L_add( hStereoClassif->xtalk_fv_fx[E_sum_d_LSF], L_abs( L_sub( lsf_new_fx[i], hStereoClassif->lsf_ch1_fx[i] ) ) ); /*q15*/ + move32(); + } + + test(); + test(); + IF( hStereoClassif->vad_flag_glob && ( hStereoClassif->ratio_L_fx > 0 && LT_32( L_shr( hStereoClassif->ratio_L_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->ratio_L_e ) ) ) ) ) + { + hStereoClassif->xtalk_fv_fx[E_sum_d_LSF] = 0; + move32(); + } + lepsP_ch2_fx = L_shr( L_sub( BASOP_Util_Loge( L_add( epsP_fx[13], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ), BASOP_Util_Loge( L_add( epsP_fx[0], L_shr( 21474 /*1e-5*2^31*/, epsP_e ) ), epsP_e ) ), 10 ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_lepsP_13] = L_abs( L_sub( hStereoClassif->lepsP_ch1_fx, lepsP_ch2_fx ) ); /*q15*/ + move32(); + } + + IF( idchan == 0 ) + { + Copy( pitch, hStereoClassif->pitch_ch1, 3 ); + Copy_Scale_sig_16_32_no_sat( voicing_fx, hStereoClassif->voicing_ch1_fx, 3, 16 ); + hStereoClassif->voicing_ch1_e = voicing_e; + move16(); + + hStereoClassif->xtalk_fv_fx[E_pitch] = Mult_32_16( L_shl( add( pitch[0], add( pitch[1], pitch[2] ) ), 15 ), 10923 ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_voicing] = Mult_32_16( L_add( voicing_fx[0], L_add( voicing_fx[1], voicing_fx[2] ) ), 10923 ); /*q15*/ + move32(); + move32(); + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_pitch] = 0; + hStereoClassif->xtalk_fv_fx[E_d_voicing] = 0; + FOR( i = 0; i < 3; i++ ) + { + hStereoClassif->xtalk_fv_fx[E_d_pitch] = L_add( hStereoClassif->xtalk_fv_fx[E_d_pitch], L_shl( abs_s( sub( pitch[i], hStereoClassif->pitch_ch1[i] ) ), Q15 ) ); + hStereoClassif->xtalk_fv_fx[E_d_voicing] = L_add( hStereoClassif->xtalk_fv_fx[E_d_voicing], L_abs( L_sub( L_shl( voicing_fx[i], voicing_e ), L_shr( hStereoClassif->voicing_ch1_fx[i], sub( 16, hStereoClassif->voicing_ch1_e ) ) ) ) ); + move32(); + move32(); + } + hStereoClassif->xtalk_fv_fx[E_d_pitch] = Mult_32_16( hStereoClassif->xtalk_fv_fx[E_d_pitch], 10923 /*1/3 q15*/ ); + hStereoClassif->xtalk_fv_fx[E_d_voicing] = Mult_32_16( hStereoClassif->xtalk_fv_fx[E_d_voicing], 10923 /*1/3 q15*/ ); + move32(); + move32(); + move32(); + move32(); + } + + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->nchar_ch1_e < 0 ) + { + hStereoClassif->nchar_ch1_fx = L_shl( hStereoClassif->nchar_ch1_fx, hStereoClassif->nchar_ch1_e ); + hStereoClassif->nchar_ch1_e = 0; + } + IF( hStereoClassif->nchar_ch2_e < 0 ) + { + hStereoClassif->nchar_ch2_fx = L_shl( hStereoClassif->nchar_ch2_fx, hStereoClassif->nchar_ch2_e ); + hStereoClassif->nchar_ch2_e = 0; + } + move32(); + move16(); + IF( idchan == 0 ) + { + hStereoClassif->cor_map_sum_ch1_fx = cor_map_sum_fx; + hStereoClassif->cor_map_sum_ch1_e = cor_map_sum_e; + hStereoClassif->non_sta_ch1_fx = non_staX_fx; + hStereoClassif->non_sta_ch1_e = non_staX_e; + hStereoClassif->sp_div_ch1_fx = sp_div_fx; + hStereoClassif->sp_div_ch1_e = sp_div_e; + hStereoClassif->xtalk_fv_fx[E_cor_map_sum] = L_shr( cor_map_sum_fx, sub( 16, cor_map_sum_e ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_nchar] = L_shr( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch1_e ) ) ), add( hStereoClassif->nchar_ch1_e, 1 ) ) /*q25*/, 10 ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_non_sta] = L_shr( non_staX_fx, sub( 16, non_staX_e ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_sp_div] = L_shr( BASOP_Util_Loge( L_add( L_shr( sp_div_fx, 1 ), L_shl( 1, sub( 31, add( sp_div_e, 1 ) ) ) ), add( sp_div_e, 1 ) ), 10 ); /*q15*/ + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + move32(); + move16(); + move16(); + move16(); + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_cor_map_sum] = L_abs( L_sub( L_shr( hStereoClassif->cor_map_sum_ch1_fx, sub( 16, hStereoClassif->cor_map_sum_ch1_e ) ) /*q15*/, L_shr( cor_map_sum_fx, sub( 16, cor_map_sum_e ) ) /*q15*/ ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_nchar] = L_abs( L_shr( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch1_e ) ) ), add( hStereoClassif->nchar_ch1_e, 1 ) ), BASOP_Util_Loge( L_add( L_shr( hStereoClassif->nchar_ch2_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->nchar_ch2_e ) ) ), add( hStereoClassif->nchar_ch2_e, 1 ) ) ) /*q25*/, 10 ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_non_sta] = L_abs( L_sub( L_shr( hStereoClassif->non_sta_ch1_fx, sub( 16, hStereoClassif->non_sta_ch1_e ) ) /*q15*/, L_shr( non_staX_fx, sub( 16, non_staX_e ) ) /*q15*/ ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_sp_div] = L_abs( L_shr( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->sp_div_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->sp_div_ch1_e ) ) ), add( hStereoClassif->sp_div_ch1_e, 1 ) ), BASOP_Util_Loge( L_add( L_shr( sp_div_fx, 1 ), L_shl( 1, sub( 30, sp_div_e ) ) ), add( sp_div_e, 1 ) ) ) /*q25*/, 10 ) ); /*q15*/ + move32(); + move32(); + move32(); + move32(); + } + + /* making negative exponent zero as we are using this exponent to scale 1 in next block*/ + IF( hStereoClassif->dE1_ch1_e < 0 ) + { + hStereoClassif->dE1_ch1_fx = L_shl( hStereoClassif->dE1_ch1_fx, hStereoClassif->dE1_ch1_e ); + hStereoClassif->dE1_ch1_e = 0; + } + IF( hStereoClassif->dE1_ch2_e < 0 ) + { + hStereoClassif->dE1_ch2_fx = L_shl( hStereoClassif->dE1_ch2_fx, hStereoClassif->dE1_ch2_e ); + hStereoClassif->dE1_ch2_e = 0; + } + move32(); + move16(); + + IF( idchan == 0 ) + { + hStereoClassif->xtalk_fv_fx[E_dE1] = L_shr( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch1_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->dE1_ch1_e ) ) ), hStereoClassif->dE1_ch1_e + 1 ) /*q25*/, 10 ); /*q15*/ + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_dE1] = L_shr( L_abs( L_sub( BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch1_fx, 1 ) /*right shifting to avoid overflow*/, L_shl( 1, sub( 30, hStereoClassif->dE1_ch1_e ) ) ), add( hStereoClassif->dE1_ch1_e, 1 ) ) /*q25*/, BASOP_Util_Loge( L_add( L_shr( hStereoClassif->dE1_ch2_fx, 1 ), L_shl( 1, sub( 30, hStereoClassif->dE1_ch2_e ) ) ), add( hStereoClassif->dE1_ch2_e, 1 ) ) /*q25*/ ) ), 10 ); /*right shifting the ouput of log by 10 to bring value to q15*/ + } + move32(); + + IF( idchan == 0 ) + { + IF( GT_16( clas, VOICED_CLAS ) ) + { + hStereoClassif->clas_ch1 = VOICED_CLAS; /*q0*/ + } + ELSE IF( LT_16( clas, VOICED_CLAS ) ) + { + hStereoClassif->clas_ch1 = UNVOICED_CLAS; + } + ELSE + { + hStereoClassif->clas_ch1 = clas; + } + move16(); + + hStereoClassif->xtalk_fv_fx[E_clas] = L_shl( hStereoClassif->clas_ch1, 15 ); /*q15*/ + } + ELSE + { + IF( GT_16( clas, VOICED_CLAS ) ) + { + clas_ch2 = VOICED_CLAS; + } + ELSE IF( LT_16( clas, VOICED_CLAS ) ) + { + clas_ch2 = UNVOICED_CLAS; + } + ELSE + { + clas_ch2 = clas; + } + move16(); + + hStereoClassif->xtalk_fv_fx[E_d_clas] = L_shl( L_abs( sub( hStereoClassif->clas_ch1 /*q0*/, clas_ch2 /*q0*/ ) ), 15 ); /*q15*/ + } + move32(); + + IF( idchan == 0 ) + { + hStereoClassif->xtalk_fv_fx[E_ps_diff] = L_shr( hStereoClassif->ps_diff_ch1_fx, sub( 16, hStereoClassif->ps_diff_ch1_e ) ); /*scaling to q15*/ + hStereoClassif->xtalk_fv_fx[E_ps_sta] = L_shr( hStereoClassif->ps_sta_ch1_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ); /*q15*/ + } + ELSE + { + hStereoClassif->xtalk_fv_fx[E_d_ps_diff] = L_abs( L_sub( L_shr( hStereoClassif->ps_diff_ch1_fx, sub( 16, hStereoClassif->ps_diff_ch1_e ) ) /*q15*/, L_shr( hStereoClassif->ps_diff_ch2_fx, sub( 16, hStereoClassif->ps_diff_ch2_e ) ) /*q15*/ ) ); /*q15*/ + hStereoClassif->xtalk_fv_fx[E_d_ps_sta] = L_abs( L_sub( L_shr( hStereoClassif->ps_sta_ch1_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ) /*q15*/, L_shr( hStereoClassif->ps_sta_ch2_fx, sub( 16, hStereoClassif->ps_sta_ch1_e ) ) /*q15*/ ) ); /*q15*/ + } + move32(); + move32(); + hStereoClassif->Etot_dn_e = hStereoClassif->Etot_up_e = hStereoClassif->e_Etot_buf_fx; /*updating the exponents*/ + move16(); + move16(); + return; +} +#else void stereo_classifier_features( STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier structure */ const int16_t idchan, /* i : channel ID */ @@ -645,7 +1055,7 @@ void stereo_classifier_features( return; } - +#endif /*-------------------------------------------------------------------* * Function unclr_classifier_td() diff --git a/lib_enc/ivas_stereo_dft_enc.c b/lib_enc/ivas_stereo_dft_enc.c index f2e351a97..c0d84f5be 100644 --- a/lib_enc/ivas_stereo_dft_enc.c +++ b/lib_enc/ivas_stereo_dft_enc.c @@ -1676,6 +1676,7 @@ void stereo_dft_enc_analyze_fx( STEREO_DFT_ENC_DATA_HANDLE hStereoDft, /* i/o: encoder stereo handle */ STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct, /* i/o: encoder MDCT stereo handle */ Word32 DFT[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC], /* o : DFT buffers */ + Word16 DFT_e[CPE_CHANNELS], /* o : DFT buffers */ Word16 *input_mem[CPE_CHANNELS], /* i/o: input buffer memory */ Word16 *q_input_mem ) { @@ -1798,9 +1799,9 @@ void stereo_dft_enc_analyze_fx( pDFT_R[add( add( dft_zp, dft_ovl ), i )] = L_shr( L_deposit_h( input[1][add( add( offset, dft_ovl ), i )] ), 1 ); move32(); } - hStereoDft->DFT_fx_e[0] = sub( 31, add( 15, sts[0]->q_inp ) ); + DFT_e[0] = sub( 31, add( 15, sts[0]->q_inp ) ); move16(); - hStereoDft->DFT_fx_e[1] = sub( 31, add( 15, sts[1]->q_inp ) ); + DFT_e[1] = sub( 31, add( 15, sts[1]->q_inp ) ); move16(); Word16 q_shift, guarded_bits; @@ -1813,7 +1814,7 @@ void stereo_dft_enc_analyze_fx( move32(); } - hStereoDft->DFT_fx_e[0] = sub( hStereoDft->DFT_fx_e[0], q_shift ); + DFT_e[0] = sub( DFT_e[0], q_shift ); move16(); FOR( Word16 j = 0; j < NFFT; j++ ) @@ -1822,7 +1823,7 @@ void stereo_dft_enc_analyze_fx( move32(); } - hStereoDft->DFT_fx_e[1] = sub( hStereoDft->DFT_fx_e[1], q_shift ); + DFT_e[1] = sub( DFT_e[1], q_shift ); move16(); rfft_fx( pDFT_L, trigo_enc, NFFT, -1 ); diff --git a/lib_enc/ivas_stereo_dft_enc_itd.c b/lib_enc/ivas_stereo_dft_enc_itd.c index 70820aaee..badadc4bb 100644 --- a/lib_enc/ivas_stereo_dft_enc_itd.c +++ b/lib_enc/ivas_stereo_dft_enc_itd.c @@ -40,6 +40,7 @@ #include "prot.h" #include "prot_fx.h" #include "ivas_prot.h" +#include "ivas_prot_fx.h" #include "ivas_cnst.h" #include "ivas_rom_com.h" #include "ivas_rom_enc.h" @@ -1329,17 +1330,17 @@ static float peak_detect( #ifdef IVAS_FLOAT_FIXED void stereo_dft_enc_compute_itd_fx( CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder structure */ - Word32 *DFT_L, + Word32 *DFT_L, /* i : exp : DFT_L_e */ Word16 *DFT_L_e, - Word32 *DFT_R, + Word32 *DFT_R, /* i : exp : DFT_R_e */ Word16 *DFT_R_e, const Word16 k_offset, const Word16 input_frame, const Word16 vad_flag_dtx[], const Word16 vad_hover_flag[], - Word32 *bin_nrgL, + Word32 *bin_nrgL, /* i : exp : bin_nrgL_e */ Word16 *bin_nrgL_e, - Word32 *bin_nrgR, + Word32 *bin_nrgR, /* i : exp : bin_nrgR_e */ Word16 *bin_nrgR_e ) { Word16 i, j; diff --git a/lib_enc/ivas_stereo_dft_td_itd.c b/lib_enc/ivas_stereo_dft_td_itd.c index c3673647f..1800950b7 100644 --- a/lib_enc/ivas_stereo_dft_td_itd.c +++ b/lib_enc/ivas_stereo_dft_td_itd.c @@ -824,3 +824,62 @@ void stereo_td_itd_mdct_stereo( return; } + +#ifdef IVAS_FLOAT_FIXED +void stereo_td_itd_mdct_stereo_fx( + CPE_ENC_HANDLE hCPE, /* i/o: CPE encoder handle */ + const Word16 vad_flag_dtx[], /* i : VAD dtx flags */ + const Word16 vad_hover_flag[], /* i : VAD hangover flags */ + const Word16 input_frame /* i : frame length */ +) +{ + Word16 i; + Word32 bin_nrgL_fx[STEREO_DFT_N_32k_ENC]; + Word16 bin_nrgL_e[STEREO_DFT_N_32k_ENC]; + Word32 bin_nrgR_fx[STEREO_DFT_N_32k_ENC]; + Word16 bin_nrgR_e[STEREO_DFT_N_32k_ENC]; + Word32 DFT_fx[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC]; + Word16 DFT_e[CPE_CHANNELS]; + Word16 DFT_tmp_e[CPE_CHANNELS][STEREO_DFT_N_MAX_ENC]; + STEREO_MDCT_ENC_DATA_HANDLE hStereoMdct; + + IF( hCPE->hStereoMdct != NULL && hCPE->hStereoMdct->hItd != NULL ) + { + hStereoMdct = hCPE->hStereoMdct; + + hCPE->hStereoMdct->hItd->td_itd_32k[STEREO_DFT_OFFSET] = 0; + move16(); + hStereoMdct->hItd->td_itd[STEREO_DFT_OFFSET] = 0; + move16(); + + /* Update the parameters */ + FOR( i = 0; i < STEREO_DFT_OFFSET; i++ ) + { + hStereoMdct->hItd->deltaItd_fx[i] = hStereoMdct->hItd->deltaItd_fx[i + 1]; + move32(); + hStereoMdct->hItd->td_itd[i] = hStereoMdct->hItd->td_itd[i + 1]; + move16(); + hStereoMdct->hItd->td_itd_32k[i] = hStereoMdct->hItd->td_itd_32k[i + 1]; + move16(); + } + + stereo_dft_enc_analyze_fx( hCPE->hCoreCoder, CPE_CHANNELS, input_frame, NULL, hStereoMdct, DFT_fx, DFT_e, hCPE->input_mem_fx, hCPE->q_input_mem ); + + FOR( i = 0; i < STEREO_DFT_N_MAX_ENC; i++ ) + { + DFT_tmp_e[0][i] = DFT_e[0]; + move16(); + DFT_tmp_e[1][i] = DFT_e[1]; + move16(); + } + + /*call ITD function*/ + stereo_dft_enc_compute_itd_fx( hCPE, DFT_fx[0], DFT_tmp_e[0], DFT_fx[1], DFT_tmp_e[1], STEREO_DFT_OFFSET, input_frame, vad_flag_dtx, vad_hover_flag, bin_nrgL_fx, bin_nrgL_e, bin_nrgR_fx, bin_nrgR_e ); + + /* Time Domain ITD compensation using extrapolation */ + stereo_td_itd_fx( hStereoMdct->hItd, NULL, NULL, 1, hStereoMdct->hDft_ana->dft_ovl, hCPE->hCoreCoder, input_frame, hCPE->input_mem_fx, hCPE->q_input_mem ); + } + + return; +} +#endif diff --git a/lib_enc/ivas_stereo_ica_enc.c b/lib_enc/ivas_stereo_ica_enc.c index 4ea6055b2..6f80d59c4 100644 --- a/lib_enc/ivas_stereo_ica_enc.c +++ b/lib_enc/ivas_stereo_ica_enc.c @@ -45,14 +45,28 @@ #ifdef IVAS_FLOAT_FIXED #include "ivas_prot_fx.h" +#include "ivas_rom_com_fx.h" #endif /*--------------------------------------------------------------- * Local function prototypes * ---------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED +static void unclr_calc_corr_features_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ + Word32 buf1[], /* i : left channel */ + Word32 buf2[], /* i : right channel */ + Word16 q_com, + const Word16 length, /* i : length of input signal buffers */ + Word32 corrEst[], /* i : buffer containing inter-channel correlation values */ + Word16 corrEst_exp, + const int16_t lagSearchRange[], /* i : minimum and maximum lags for corrEst[] */ + Word32 *corrEst_ncorr, /* o : norm. x-correlation btw. current and previous correlation buffers */ + Word16 *corrEst_ncorr_exp ); +#else static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, STEREO_TCA_ENC_HANDLE hStereoTCA, const float buf1[], const float buf2[], const int16_t length, const float corrEst[], const int16_t lagSearchRange[], float *corrEst_ncorr ); - +#endif /*-------------------------------------------------------------------* * Local constants @@ -67,6 +81,17 @@ static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, STER #define SMOOTH_DIST_FACTOR 0.4f #define SMOOTH_ENV_FACTOR 0.6f +#define XL_BIAS_FX_Q15 6554 +#define XH_BIAS_FX_Q15 13107 +#define XL_WIDTH_FX_Q15 3932 +#define XH_WIDTH_FX_Q15 4915 +#define SMOOTH_DIST_FACTOR_FX_Q15 14418 +#define A_BIAS_FX_Q15 3277 +#define B_BIAS_FX_Q15 -16384 +#define A_WIDTH_FX_Q31 32212264 +#define B_WIDTH_FX_Q31 32212192 +#define SMOOTH_ENV_FACTOR_FX_Q15 19661 + #define A_BIAS ( ( XH_BIAS - XL_BIAS ) / ( YH_DIST - YL_DIST ) ) #define B_BIAS ( XH_BIAS - ( A_BIAS * YH_DIST ) ) #define A_WIDTH ( ( XH_WIDTH - XL_WIDTH ) / ( YH_DIST - YL_DIST ) ) @@ -78,7 +103,125 @@ static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, STER * * Temporal channel adjustment of LA samples in target channel * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void tcaTargetCh_LA_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, + Word32 *ptrChanL, + Word32 *ptrChanR, + Word16 *q_com, + const Word16 currentNCShift, + const Word16 input_frame ) +{ + Word16 i, j; + Word16 tempS, temp, sine_inp; + Word32 tempF1, tempF2, gAdj; + Word16 tempF1_exp, tempF2_exp, gAdj_exp; + + Word32 *ref, *target; + Word16 ref_exp, target_exp, target_exp_temp[L_FRAME48k + L_FRAME48k]; + Word16 win[240]; /* 5 ms at 48 kHz */ + + ref_exp = sub( 31, *q_com ); + target_exp = sub( 31, *q_com ); + set16_fx( target_exp_temp, target_exp, L_FRAME48k + 30 ); + + IF( EQ_16( hStereoTCA->refChanIndx, L_CH_INDX ) ) + { + ref = ptrChanL; + target = ptrChanR; + } + ELSE + { + ref = ptrChanR; + target = ptrChanL; + } + + tempS = NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ); + tempF1 = 0; + move32(); + tempF1_exp = 0; + move32(); + tempF2 = 0; + move32(); + tempF2_exp = 0; + move16(); + FOR( i = 0; i < sub( input_frame, currentNCShift ); i++ ) + { + tempF1 = BASOP_Util_Add_Mant32Exp( tempF1, tempF1_exp, L_abs( ref[i] ), ref_exp, &tempF1_exp ); + tempF2 = BASOP_Util_Add_Mant32Exp( tempF2, tempF2_exp, L_abs( target[i + currentNCShift] ), target_exp, &tempF2_exp ); + } + + IF( tempF1 == 0 ) + { + gAdj = ONE_IN_Q31; + move32(); + gAdj_exp = 0; + move16(); + } + ELSE + { + Word32 deno = BASOP_Util_Add_Mant32Exp( tempF1, tempF1_exp, -21475 /*0.00001f in Q31*/, 0, &temp ); + Word16 deno_exp; + IF( deno > 0 ) + { + deno = tempF1; + deno_exp = tempF1_exp; + } + ELSE + { + deno = 21475; + deno_exp = 0; + } + move32(); + move32(); + gAdj = BASOP_Util_Divide3232_Scale_cadence( tempF2, deno, &gAdj_exp ); + gAdj_exp = add( gAdj_exp, sub( tempF2_exp, deno_exp ) ); + } + + FOR( i = 0; i < tempS; i++ ) + { + sine_inp = BASOP_Util_Divide1616_Scale( add( shl( i, 10 ), 512 ), shl( tempS, 1 ), &temp ); + sine_inp = shl_sat( sine_inp, add( temp, -10 ) ); + win[i] = getSineWord16R2( shr( sine_inp, 1 ) ); + move16(); + } + + j = 0; + move16(); + + Word16 exp_com = target_exp_temp[0]; + move16(); + FOR( i = sub( input_frame, add( currentNCShift, tempS ) ); i < sub( input_frame, currentNCShift ); ( i++, j++ ) ) + { + target[i + currentNCShift] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( Mpy_32_16_1( gAdj, win[j] ), ref[i] ), add( ref_exp, gAdj_exp ), Mpy_32_16_1( target[i + currentNCShift], sub( MAX_16, win[j] ) ), target_exp, &temp ); + move32(); + target_exp_temp[i + currentNCShift] = temp; + move16(); + exp_com = s_max( exp_com, temp ); + } + + FOR( ; i < input_frame; i++ ) + { + target[i + currentNCShift] = Mpy_32_32( gAdj, ref[i] ); + move32(); + target_exp_temp[i + currentNCShift] = add( gAdj_exp, ref_exp ); + move16(); + exp_com = s_max( exp_com, target_exp_temp[i + currentNCShift] ); + } + + FOR( i = 0; i < input_frame; i++ ) + { + target[i] = L_shl( target[i], sub( target_exp_temp[i], exp_com ) ); + move32(); + ref[i] = L_shl( ref[i], sub( ref_exp, exp_com ) ); + move32(); + } + *q_com = sub( 31, exp_com ); + move16(); + return; +} +#else static void tcaTargetCh_LA( STEREO_TCA_ENC_HANDLE hStereoTCA, float *ptrChanL, @@ -132,7 +275,7 @@ static void tcaTargetCh_LA( return; } - +#endif /*--------------------------------------------------------------- * spectral_balancer() * @@ -232,6 +375,88 @@ void spectral_balancer_fx16( return; } + +void spectral_balancer_fx( + Word32 *signal, /* i/o : signal Qx */ + Word32 *mem, /* i/o : mem Qx */ + const Word16 lg, /* i : input signal length */ + const Word16 coeff_set /* i : coefficient set */ +) +{ + Word16 i; + Word32 x0, x1, x2, y0, y1, y2; + Word32 a1, a2, b0, b1, b2; + + y1 = mem[0]; + y2 = mem[1]; + x0 = mem[2]; + x1 = mem[3]; + move32(); + move32(); + move32(); + move32(); + + /* hp filter 60Hz at 3dB for 8000KHz sampling rate + 1. [b,a] = butter(1, 60.0/8000.0, 'high'); + 2. spectral_balancing_filter + < maybe not needed>> + b =[1, -1] [1, -0.6] + a =[1, -0.95395255590776329] [1, 0.5] */ + IF( coeff_set == 0 ) + { + a1 = 401466258; // Q29 + move32(); + a2 = -146144282; // Q29 + move32(); + b0 = 271120363; // Q29 + move32(); + b1 = -542240726; // Q29 + move32(); + b2 = 271120363; // Q29 + move32(); + } + ELSE + { + a1 = -72242031; // Q29 + move32(); + a2 = -208379437; // Q29 + move32(); + b0 = 536870912; // Q29 + move32(); + b1 = -1072703858; // Q29 + move32(); + b2 = 536870912; // Q29 + move32(); + } + + FOR( i = 0; i < lg; i++ ) + { + x2 = x1; + move16(); + x1 = x0; + move16(); + x0 = signal[i]; + move16(); + y0 = W_extract_l( W_shr( W_mac_32_32( W_mac_32_32( W_mac_32_32( W_mac_32_32( W_mult_32_32( a1, y1 ), a2, y2 ), b0, x0 ), b1, x1 ), b2, x2 ), 30 ) ); // Qx + signal[i] = y0; + move16(); + y2 = y1; + move16(); + y1 = y0; + move16(); + } + + mem[0] = y1; + move32(); + mem[1] = y2; + move32(); + mem[2] = x0; + move32(); + mem[3] = x1; + move32(); + + return; +} #endif // IVAS_FLOAT_FIXED void spectral_balancer( @@ -297,7 +522,60 @@ void spectral_balancer( * * De-emphasize and resample the L and R channels. * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void deEmphResample( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA encoder handle */ + const Word32 *tempChan1_fx, /* i : Stereo data Qx*/ + const Word32 *tempChan2_fx, /* i : Stereo data Qx*/ + Word32 *chan1_fx, // Qx + Word32 *chan2_fx, // Qx + const Word16 input_frame, + const Word16 dsFactor ) +{ + Word32 buf1_fx[L_FRAME48k], buf2_fx[L_FRAME48k]; + Word32 tempBuf1_fx[2 * L_FRAME_DS], tempBuf2_fx[2 * L_FRAME_DS]; + Word16 i; + Word16 dsFac1, dsFac2; + + /* Estimate first and second stage downsample factors */ + dsFac1 = shr( dsFactor, 1 ); + dsFac2 = idiv1616( dsFactor, dsFac1 ); + + /* convert stereo data to two distinct channels, e.g., L, R */ + Copy32( tempChan1_fx, buf1_fx, input_frame ); + Copy32( tempChan2_fx, buf2_fx, input_frame ); + + /* De-emphasis, 1/(1-mu z^-1), and resample, stage 1 */ + + deemph_fx_32( 0, buf1_fx, PREEMPH_FAC_16k, input_frame, &hStereoTCA->memdecim_fx[0] ); + deemph_fx_32( 0, buf2_fx, PREEMPH_FAC_16k, input_frame, &hStereoTCA->memdecim_fx[1] ); + + FOR( i = 0; i < idiv1616( input_frame, dsFac1 ); i++ ) + { + tempBuf1_fx[i] = buf1_fx[i * dsFac1]; + move32(); + tempBuf2_fx[i] = buf2_fx[i * dsFac1]; + move32(); + } + + /* De-emphasis, 1/(1-mu z^-1), and resample, stage 2 */ + deemph_fx_32( 0, tempBuf1_fx, PREEMPH_FAC_16k, idiv1616( input_frame, dsFac1 ), &hStereoTCA->memdecim_fx[2] ); + deemph_fx_32( 0, tempBuf2_fx, PREEMPH_FAC_16k, idiv1616( input_frame, dsFac1 ), &hStereoTCA->memdecim_fx[3] ); + + FOR( i = 0; i < idiv1616( input_frame, dsFactor ); i++ ) + { + chan1_fx[i] = tempBuf1_fx[i * dsFac2]; + move32(); + chan2_fx[i] = tempBuf2_fx[i * dsFac2]; + move32(); + } + spectral_balancer_fx( chan1_fx, &hStereoTCA->memdecim_fx[4], idiv1616( input_frame, dsFactor ), 0 ); /*4 mem */ + spectral_balancer_fx( chan2_fx, &hStereoTCA->memdecim_fx[8], idiv1616( input_frame, dsFactor ), 0 ); /*4 mem */ + + return; +} +#else static void deEmphResample( STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA encoder handle */ const float *tempChan1, /* i : Stereo data */ @@ -345,14 +623,117 @@ static void deEmphResample( return; } - +#endif /*--------------------------------------------------------------- * utilCrossCorr_mod() * * Biased crossCorr estimation between buf1, buf2 over the * lag range of (lagSearchRange[0], lagSearchRange[1]). * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void utilCrossCorr_mod_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ + const Word32 *buf1, + const Word32 *buf2, + const Word16 q_com, + Word32 *corrEst, /* o : correlation estimate */ + Word16 *corrEst_Exp, /* o : correlation estimate */ + const Word16 *lagSearchRange, + const Word16 len ) +{ + Word32 C, E1, E2, C_C_mem; + Word16 i, j, E1_exp, E2_exp, E1E2_exp, Inv_Tot_E_exp, k, C_exp, exp; + Word16 Inv_Tot_E, corrEst_exp[2 * L_NCSHIFT_DS + 1]; + Word64 L64_sum; + + set16_fx( corrEst_exp, -1000, 2 * L_NCSHIFT_DS + 1 ); + E1_exp = sub( 31, q_com ); + E2_exp = sub( 31, q_com ); + + E1 = sum2_32_exp_fx( buf1, len, &E1_exp, 2 ); + E2 = sum2_32_exp_fx( buf2, len, &E2_exp, 2 ); + + E1E2_exp = s_max( E1_exp, E2_exp ); + E1 = L_shl( E1, sub( E1_exp, E1E2_exp ) ); + E2 = L_shl( E2, sub( E2_exp, E1E2_exp ) ); + + Word32 E1_mul = BASOP_Util_Add_Mant32Exp( E1, E1E2_exp, hStereoTCA->E1_mem_fx, hStereoTCA->E1_E2_mem_exp, &E1_exp ); + Word32 E2_mul = BASOP_Util_Add_Mant32Exp( E2, E1E2_exp, hStereoTCA->E2_mem_fx, hStereoTCA->E1_E2_mem_exp, &E2_exp ); + Word32 sqr_inp = Mpy_32_32( E1_mul, E2_mul ); + Word16 sq_exp = add( E1_exp, E2_exp ); + + IF( sqr_inp ) + { + sqr_inp = Sqrt32( sqr_inp, &sq_exp ); + sqr_inp = Mpy_32_32( sqr_inp, 1342177280 /* 320 in Q22*/ ); + sq_exp = add( sq_exp, 9 ); + Inv_Tot_E = BASOP_Util_Divide3232_Scale( ONE_IN_Q31, sqr_inp, &Inv_Tot_E_exp ); + Inv_Tot_E_exp = add( Inv_Tot_E_exp, sub( 0, sq_exp ) ); + } + ELSE + { + Inv_Tot_E = 25088; /* 98.82 in Q8 */ + Inv_Tot_E_exp = 7; + } + + hStereoTCA->E1_mem_fx = E1; + hStereoTCA->E2_mem_fx = E2; + hStereoTCA->E1_E2_mem_exp = E1E2_exp; + move16(); + + *corrEst_Exp = corrEst_exp[0]; + + for ( i = lagSearchRange[0], j = 0; i <= 0; i++, j++ ) + { + L64_sum = 1; + move64(); + FOR( k = 0; k < len; k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k], buf2[k + i] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + C = W_extract_h( L64_sum ); // ener_side_q + C_exp = sub( 31, sub( add( add( shl( q_com, 1 ), 1 ), k ), 32 ) ); + C_C_mem = BASOP_Util_Add_Mant32Exp( C, C_exp, hStereoTCA->C_mem_fx[j], hStereoTCA->C_mem_exp[j], &exp ); + corrEst[j] = Mpy_32_16_1( C_C_mem, Inv_Tot_E ); + corrEst_exp[j] = add( Inv_Tot_E_exp, exp ); + *corrEst_Exp = s_max( *corrEst_Exp, corrEst_exp[j] ); + hStereoTCA->C_mem_fx[j] = C; + hStereoTCA->C_mem_exp[j] = C_exp; + } + + for ( ; i <= lagSearchRange[1]; i++, j++ ) + { + L64_sum = 1; + move64(); + FOR( k = 0; k < len; k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k - i], buf2[k] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + C = W_extract_h( L64_sum ); // ener_side_q + C_exp = sub( 31, sub( add( add( shl( q_com, 1 ), 1 ), k ), 32 ) ); + C_C_mem = BASOP_Util_Add_Mant32Exp( C, C_exp, hStereoTCA->C_mem_fx[j], hStereoTCA->C_mem_exp[j], &exp ); + corrEst[j] = Mpy_32_16_1( C_C_mem, Inv_Tot_E ); + corrEst_exp[j] = add( Inv_Tot_E_exp, exp ); + *corrEst_Exp = s_max( *corrEst_Exp, corrEst_exp[j] ); + hStereoTCA->C_mem_fx[j] = C; + hStereoTCA->C_mem_exp[j] = C_exp; + } + /* Rescaling buffers */ + + FOR( i = 0; i < ( 2 * L_NCSHIFT_DS + 1 ); i++ ) + { + corrEst[i] = L_shl( corrEst[i], sub( corrEst_exp[i], *corrEst_Exp ) ); + move32(); + } + + return; +} +#else static void utilCrossCorr_mod( STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ const float *buf1, @@ -389,64 +770,195 @@ static void utilCrossCorr_mod( return; } - - +#endif /*--------------------------------------------------------------- * utilCrossCorr() * * crossCorr estimation between buf1, buf2 over the * lag range of (lagSearchRange[0], lagSearchRange[1]). * ---------------------------------------------------------------*/ - -static void utilCrossCorr( - const float *buf1, - const float *buf2, - const float *win, - float *corrEst, /* o : correlation estimate */ - const int16_t *lagSearchRange, - const int16_t len, - const int16_t winSymmFlag ) +#ifdef IVAS_FLOAT_FIXED +static void utilCrossCorr_fx( + const Word32 *buf1, // buf1_q + Word16 buf1_q, + const Word32 *buf2, // buf2_q + Word16 buf2_q, + const Word32 *win, + Word32 *corrEst, /* o : correlation estimate corrEst_e */ + Word16 *corrEst_e, + const Word16 *lagSearchRange, + const Word16 len, + const Word16 winSymmFlag ) { - float tempBuf1[L_FRAME48k]; - float tempBuf2[L_FRAME48k]; - float temp, scale; - int16_t i, j; + Word32 tempBuf1[L_FRAME48k]; + Word32 tempBuf2[L_FRAME48k]; + Word32 temp, scale; + Word16 res_e, tmp_e; + Word64 L64_sum; + Word16 i, j, k; + Word16 corrEstTemp_e[N_MAX_SHIFT_CHANGE + 1]; + Word16 max_e = MIN16B; + move16(); + + Word16 gb1 = s_max( 0, sub( find_guarded_bits_fx( len ), getScaleFactor32( buf1, len ) ) ); + Word16 gb2 = s_max( 0, sub( find_guarded_bits_fx( len ), getScaleFactor32( buf2, len ) ) ); /* Apply windowing */ - if ( win != NULL ) + IF( win != NULL ) { - if ( winSymmFlag == 0 ) + IF( EQ_16( winSymmFlag, 0 ) ) { - v_mult( buf1, win, tempBuf1, len ); - v_mult( buf2, win, tempBuf2, len ); + v_mult_fixed( buf1, win, tempBuf1, len ); + v_mult_fixed( buf2, win, tempBuf2, len ); } - else + ELSE { - v_mult( buf1, win, tempBuf1, ( len >> 1 ) ); - v_mult( buf2, win, tempBuf2, ( len >> 1 ) ); + v_mult_fixed( buf1, win, tempBuf1, ( len >> 1 ) ); + v_mult_fixed( buf2, win, tempBuf2, ( len >> 1 ) ); - for ( i = ( len >> 1 ); i < len; i++ ) + FOR( i = shr( len, 1 ); i < len; i++ ) { - tempBuf1[i] = win[len - 1 - i] * buf1[i]; - tempBuf2[i] = win[len - 1 - i] * buf2[i]; + tempBuf1[i] = Mpy_32_32( win[len - 1 - i], buf1[i] ); + move32(); + tempBuf2[i] = Mpy_32_32( win[len - 1 - i], buf2[i] ); + move32(); } } } - else + ELSE { - mvr2r( buf1, tempBuf1, len ); - mvr2r( buf2, tempBuf2, len ); + Copy32( buf1, tempBuf1, len ); + Copy32( buf2, tempBuf2, len ); } - temp = sum2_f( tempBuf1, len ); - temp *= sum2_f( tempBuf2, len ); - scale = ( temp == 0 ) ? 1.0f : inv_sqrt( temp ); + Word16 temp1_e = sub( Q31, buf1_q ); + Word16 temp2_e = sub( Q31, buf2_q ); - /* starting point of lag search range should be less than the ending point */ - assert( lagSearchRange[0] <= lagSearchRange[1] ); + temp = sum2_32_exp_fx( tempBuf1, len, &temp1_e, gb1 ); // temp1_e + temp = Mpy_32_32( temp, sum2_32_exp_fx( tempBuf2, len, &temp2_e, gb2 ) ); // temp2_e + temp2_e = add( temp1_e, temp2_e ); - /* first part of noncausal corr est. */ - for ( i = lagSearchRange[0], j = 0; i <= min( 0, lagSearchRange[1] ); i++, j++ ) + IF( temp == 0 ) + { + scale = MAXVAL_WORD32; + move32(); + } + ELSE + { + scale = Isqrt_lc( temp, &temp2_e ); // temp2_e + } + + /* starting point of lag search range should be less than the ending point */ + assert( lagSearchRange[0] <= lagSearchRange[1] ); + + /* first part of noncausal corr est. */ + for ( i = lagSearchRange[0], j = 0; i <= s_min( 0, lagSearchRange[1] ); ( i++, j++ ) ) + { + L64_sum = 0; + move64(); + FOR( k = 0; k < add( len, i ); k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k - i], buf2[k] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + temp = W_extract_h( L64_sum ); + res_e = sub( 31, sub( add( add( add( buf1_q, buf2_q ), 1 ), k ), 32 ) ); + + corrEst[j] = L_deposit_h( BASOP_Util_Divide3216_Scale( temp, ( len + i ), &tmp_e ) ); + move32(); + corrEstTemp_e[j] = add( tmp_e, sub( res_e, 15 ) ); + move16(); + max_e = s_max( max_e, corrEstTemp_e[j] ); + } + + /* second part of noncausal corr est. */ + for ( ; i <= lagSearchRange[1]; ( i++, j++ ) ) + { + L64_sum = 1; + move64(); + FOR( k = 0; k < sub( len, i ); k++ ) + { + L64_sum = W_mac_32_32( L64_sum, buf1[k], buf2[k + i] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + temp = W_extract_h( L64_sum ); + res_e = sub( 31, sub( add( add( add( buf1_q, buf2_q ), 1 ), k ), 32 ) ); + + corrEst[j] = L_deposit_h( BASOP_Util_Divide3216_Scale( temp, ( len - i ), &tmp_e ) ); + move32(); + corrEstTemp_e[j] = add( tmp_e, sub( res_e, 15 ) ); + move16(); + max_e = s_max( max_e, corrEstTemp_e[j] ); + move16(); + } + + + FOR( i = 0; i < j; i++ ) + { + corrEst[i] = L_shr( corrEst[i], sub( max_e, corrEstTemp_e[i] ) ); + move32(); + } + + *corrEst_e = max_e; + move16(); + v_multc_fixed( corrEst, scale, corrEst, j ); + *corrEst_e = add( *corrEst_e, temp2_e ); + move16(); + + return; +} +#else +static void utilCrossCorr( + const float *buf1, + const float *buf2, + const float *win, + float *corrEst, /* o : correlation estimate */ + const int16_t *lagSearchRange, + const int16_t len, + const int16_t winSymmFlag ) +{ + float tempBuf1[L_FRAME48k]; + float tempBuf2[L_FRAME48k]; + float temp, scale; + int16_t i, j; + + /* Apply windowing */ + if ( win != NULL ) + { + if ( winSymmFlag == 0 ) + { + v_mult( buf1, win, tempBuf1, len ); + v_mult( buf2, win, tempBuf2, len ); + } + else + { + v_mult( buf1, win, tempBuf1, ( len >> 1 ) ); + v_mult( buf2, win, tempBuf2, ( len >> 1 ) ); + + for ( i = ( len >> 1 ); i < len; i++ ) + { + tempBuf1[i] = win[len - 1 - i] * buf1[i]; + tempBuf2[i] = win[len - 1 - i] * buf2[i]; + } + } + } + else + { + mvr2r( buf1, tempBuf1, len ); + mvr2r( buf2, tempBuf2, len ); + } + + temp = sum2_f( tempBuf1, len ); + temp *= sum2_f( tempBuf2, len ); + scale = ( temp == 0 ) ? 1.0f : inv_sqrt( temp ); + + /* starting point of lag search range should be less than the ending point */ + assert( lagSearchRange[0] <= lagSearchRange[1] ); + + /* first part of noncausal corr est. */ + for ( i = lagSearchRange[0], j = 0; i <= min( 0, lagSearchRange[1] ); i++, j++ ) { temp = dotp( tempBuf1 - i, tempBuf2, ( len + i ) ); corrEst[j] = temp / ( len + i ); @@ -462,7 +974,7 @@ static void utilCrossCorr( return; } - +#endif /*--------------------------------------------------------------- * corrStatsEst() * @@ -470,292 +982,503 @@ static void utilCrossCorr( * ---------------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED -static void corrStatsEst( - STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */ - const float *buf1, /* i : channel 1 */ - const float *buf2, /* i : channel 2 */ - const int16_t bufLenDS, /* i : buffer length */ - const int16_t dsFactor, /* i : buffer length */ - const int16_t vad_flag1, /* i : VAD flag channel 1 */ - const int16_t vad_flag2, /* i : VAD flag channel 2 */ +static Word16 TRUNC_FX( Word32 inp, Word16 exp ) +{ + Word16 ouptut; + Word32 temp; + + temp = L_shr( inp, sub( 31, exp ) ); + test(); + IF( GT_32( temp, 32767 ) || LT_32( temp, -32768 ) ) + { + IF( temp < 0 ) + { + ouptut = -32768; + } + ELSE + { + ouptut = 32767; + } + move16(); + } + ELSE + { + IF( NE_32( temp, L_shl_sat( 1, sub( 31, exp ) ) ) ) + { + Word32 temp1 = L_add_sat( inp, L_shl_sat( 1, sub( 31, add( exp, 1 ) ) ) ); + ouptut = (Word16) L_shr( temp1, sub( 31, exp ) ); + + IF( temp < 0 ) + { + ouptut = add( ouptut, 1 ); + } + } + ELSE + { + ouptut = (Word16) temp; + move16(); + } + } + return ouptut; +} +static void corrStatsEst_fx( + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: Stereo TCA Encoder handle */ + Word32 *buf1_fx, /* i : channel 1 q_com*/ + Word32 *buf2_fx, /* i : channel 2 q_com*/ + Word16 q_com, + const Word16 bufLenDS, /* i : buffer length */ + const Word16 dsFactor, /* i : buffer length */ + const Word16 vad_flag1, /* i : VAD flag channel 1 */ + const Word16 vad_flag2, /* i : VAD flag channel 2 */ STEREO_CLASSIF_HANDLE hStereoClassif /* i/o: stereo classifier handle */ ) { - int16_t lagSearchRange[2]; - float corrEst[2 * L_NCSHIFT_DS + 1]; - int16_t corrLagStats[3]; - float *tempRK; - const float *winInterp; - float rInterp[MAX_INTERPOLATE]; - int16_t interpMin, interpMax, interpLen; - int16_t i, j, k, m; - float tempF, alpha; - float win_bias; - int16_t tempLen, win_width; - float loc_weight_win[4 * L_NCSHIFT_DS + 1]; - float X_hat, Y_hat, XY_hat, X_SQR_hat; - float alpha_reg, beta_reg, reg_prv_corr, dist_reg_prv_corr, bias_par, width_par; - float k1, k2, temp_A, temp_B; - int16_t stmp; - float corrEst_ncorr; + Word16 lagSearchRange[2]; + Word32 corrEst_fx[2 * L_NCSHIFT_DS + 1]; + Word16 corrLagStats[3]; + Word32 *tempRK_fx; + const Word32 *winInterp_fx; + Word32 rInterp_fx[MAX_INTERPOLATE]; + Word16 rInterp_exp[MAX_INTERPOLATE]; + Word16 interpMin, interpMax, interpLen; + Word16 i, j, k, m; + Word16 win_bias_fx; + Word16 tempLen, win_width; + Word16 loc_weight_win_fx[4 * L_NCSHIFT_DS + 1]; + Word32 X_hat_fx, Y_hat_fx, XY_hat_fx, X_SQR_hat_fx; + Word32 alpha_reg_fx, beta_reg_fx, reg_prv_corr_fx, dist_reg_prv_corr_fx, bias_par_fx, width_par_fx; + Word16 alpha_reg_exp, beta_reg_exp, reg_prv_corr_exp, dist_reg_prv_corr_exp, bias_par_exp, width_par_exp; + + Word16 alpha_fx; + Word16 k1_fx, k2_fx; + Word32 temp_A_fx, temp_B_fx, tempF_fx; + Word16 stmp; + Word32 corrEst_ncorr_fx, temp32; + Word16 corrEst_exp, corrEst_ncorr_exp, temp; + Word16 X_hat_exp, Y_hat_exp, XY_hat_exp, X_SQR_hat_exp, exp; /* init of regression parameters*/ - X_hat = 0; - X_SQR_hat = 0; - XY_hat = 0; + X_hat_fx = 0; + move32(); + X_hat_exp = 0; + move16(); + X_SQR_hat_fx = 0; + move32(); + X_SQR_hat_exp = 0; + move16(); + XY_hat_fx = 0; + move32(); + XY_hat_exp = 0; + move16(); /* Initializations */ - alpha = 0.7f; + alpha_fx = 22938; /* 0.7 in Q15*/ + move16(); lagSearchRange[0] = -L_NCSHIFT_DS; + move16(); lagSearchRange[1] = L_NCSHIFT_DS; + move16(); tempLen = ( 2 * L_NCSHIFT_DS + 1 ); + move16(); - set_s( corrLagStats, 0, 3 ); + set16_fx( corrLagStats, 0, 3 ); /* First iteration of xcorr estimation */ - utilCrossCorr_mod( hStereoTCA, buf1, buf2, corrEst, lagSearchRange, bufLenDS - L_XCORRMEM_DS ); + utilCrossCorr_mod_fx( hStereoTCA, buf1_fx, buf2_fx, q_com, corrEst_fx, &corrEst_exp, lagSearchRange, sub( bufLenDS, L_XCORRMEM_DS ) ); /* calculate features for the UNCLR classifier */ - unclr_calc_corr_features( hStereoClassif, hStereoTCA, buf1, buf2, bufLenDS - L_XCORRMEM_DS, corrEst, lagSearchRange, &corrEst_ncorr ); + unclr_calc_corr_features_fx( hStereoClassif, hStereoTCA, buf1_fx, buf2_fx, q_com, sub( bufLenDS, L_XCORRMEM_DS ), corrEst_fx, corrEst_exp, lagSearchRange, &corrEst_ncorr_fx, &corrEst_ncorr_exp ); - for ( i = 1; i < 3; i++ ) + FOR( i = 1; i < 3; i++ ) { - v_add( hStereoTCA->corrEstPrev[i], hStereoTCA->corrEstPrev[0], hStereoTCA->corrEstPrev[0], tempLen ); + v_add_32( hStereoTCA->corrEstPrev_fx[i], hStereoTCA->corrEstPrev_fx[0], hStereoTCA->corrEstPrev_fx[0], tempLen ); } /* back up the corrEst */ - for ( i = 0; i < 2; i++ ) + FOR( i = 0; i < 2; i++ ) { - mvr2r( hStereoTCA->corrEstPrev[i + 1], hStereoTCA->corrEstPrev[i], tempLen ); + Copy32( hStereoTCA->corrEstPrev_fx[i + 1], hStereoTCA->corrEstPrev_fx[i], tempLen ); } - mvr2r( corrEst, hStereoTCA->corrEstPrev[2], tempLen ); - -#ifdef IVAS_FLOAT_FIXED - Word32 buf1_fx[160]; - Word32 buf2_fx[160]; - Word16 buf1_q, buf2_q, guard_bits; - Word32 temp_A_fx, temp_B_fx; - f2me_buf( buf1, buf1_fx, &buf1_q, 160 ); - f2me_buf( buf2, buf2_fx, &buf2_q, 160 ); - buf1_q = sub( 31, buf1_q ); - buf2_q = sub( 31, buf2_q ); - Word16 buf_q = s_min( buf1_q, buf2_q ); - guard_bits = find_guarded_bits_fx( 160 ); - scale_sig32( buf1_fx, 160, sub( sub( buf_q, guard_bits ), buf1_q ) ); - scale_sig32( buf2_fx, 160, sub( sub( buf_q, guard_bits ), buf2_q ) ); - buf_q = sub( buf_q, guard_bits ); -#endif -#ifdef IVAS_FLOAT_FIXED - temp_A_fx = sumAbs_fx( buf1_fx, L_FRAME_DS - L_XCORRMEM_DS ) + sumAbs_fx( buf2_fx, L_FRAME_DS - L_XCORRMEM_DS ); - temp_B_fx = sumAbs_fx( buf1_fx + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) + sumAbs_fx( buf2_fx + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ); - temp_A = fixedToFloat( temp_A_fx, buf_q ); - temp_B = fixedToFloat( temp_B_fx, buf_q ); -#else - temp_A = sumAbs( buf1, L_FRAME_DS - L_XCORRMEM_DS ) + sumAbs( buf2, L_FRAME_DS - L_XCORRMEM_DS ); - temp_B = sumAbs( buf1 + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) + sumAbs( buf2 + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ); -#endif - tempF = temp_A + temp_B + hStereoTCA->mem_tempF; - hStereoTCA->mem_tempF = temp_B; + temp = getScaleFactor32( corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); + scale_sig32( corrEst_fx, 2 * L_NCSHIFT_DS + 1, temp ); + corrEst_exp = sub( corrEst_exp, temp ); - alpha = 0.93f; - if ( tempF > 4.0f * hStereoTCA->ica_envVarLT ) - { - alpha = 0.83f; - } - else if ( tempF > 2.0f * hStereoTCA->ica_envVarLT ) + IF( GT_16( corrEst_exp, hStereoTCA->corrEstPrev_exp ) ) { - alpha = 0.85f; + scale_sig32( hStereoTCA->corrEstPrev_fx[0], 2 * L_NCSHIFT_DS + 1, sub( hStereoTCA->corrEstPrev_exp, corrEst_exp ) ); + scale_sig32( hStereoTCA->corrEstPrev_fx[1], 2 * L_NCSHIFT_DS + 1, sub( hStereoTCA->corrEstPrev_exp, corrEst_exp ) ); + Copy32( corrEst_fx, hStereoTCA->corrEstPrev_fx[2], tempLen ); + hStereoTCA->corrEstPrev_exp = corrEst_exp; + move16(); } - else if ( tempF > hStereoTCA->ica_envVarLT ) + ELSE { - alpha = 0.90f; + Copy32( corrEst_fx, hStereoTCA->corrEstPrev_fx[2], tempLen ); + scale_sig32( hStereoTCA->corrEstPrev_fx[2], 2 * L_NCSHIFT_DS + 1, sub( corrEst_exp, hStereoTCA->corrEstPrev_exp ) ); } + scale_sig32( hStereoTCA->corrEstPrev_fx[0], 2 * L_NCSHIFT_DS + 1, -1 ); + scale_sig32( hStereoTCA->corrEstPrev_fx[1], 2 * L_NCSHIFT_DS + 1, -1 ); + scale_sig32( hStereoTCA->corrEstPrev_fx[2], 2 * L_NCSHIFT_DS + 1, -1 ); + hStereoTCA->corrEstPrev_exp = add( hStereoTCA->corrEstPrev_exp, 1 ); + move16(); + Word32 buf1_fx_temp[L_FRAME_DS]; + Word32 buf2_fx_temp[L_FRAME_DS]; - hStereoTCA->corrStatsSmoothFac = alpha; + Copy32( buf1_fx, buf1_fx_temp, L_FRAME_DS ); + Copy32( buf2_fx, buf2_fx_temp, L_FRAME_DS ); - /* long term corr Stats estimation */ - v_multc( hStereoTCA->corrEstLT, alpha, hStereoTCA->corrEstLT, 2 * L_NCSHIFT_DS + 1 ); - v_multc( corrEst, 1.0f - alpha, corrEst, 2 * L_NCSHIFT_DS + 1 ); - v_add( hStereoTCA->corrEstLT, corrEst, hStereoTCA->corrEstLT, 2 * L_NCSHIFT_DS + 1 ); + scale_sig32( buf1_fx_temp, L_FRAME_DS, -4 ); + scale_sig32( buf2_fx_temp, L_FRAME_DS, -4 ); - hStereoTCA->ica_envVarLT = SMOOTH_ENV_FACTOR * hStereoTCA->ica_envVarLT + ( 1 - SMOOTH_ENV_FACTOR ) * tempF; + temp_A_fx = L_add( sumAbs_fx( buf1_fx_temp, L_FRAME_DS - L_XCORRMEM_DS ), sumAbs_fx( buf2_fx_temp, L_FRAME_DS - L_XCORRMEM_DS ) ); + temp_B_fx = L_add( sumAbs_fx( buf1_fx_temp + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ), sumAbs_fx( buf2_fx_temp + ( L_FRAME_DS - L_XCORRMEM_DS ), L_XCORRMEM_DS ) ); - mvr2r( hStereoTCA->corrEstLT, corrEst, 2 * L_NCSHIFT_DS + 1 ); - Y_hat = hStereoTCA->delay_0_mem[0]; - /* Note: keep X_hat and X_SQR_hat calculations inside the loop to allow future tuning of MAX_DELAYREGLEN */ - for ( i = 1; i < MAX_DELAYREGLEN; i++ ) - { - X_hat += (float) i; - Y_hat += hStereoTCA->delay_0_mem[i]; - XY_hat += i * hStereoTCA->delay_0_mem[i]; - X_SQR_hat += (float) ( i * i ); - } - X_hat *= INV_MAX_DELAYREGLEN; - Y_hat *= INV_MAX_DELAYREGLEN; - XY_hat *= INV_MAX_DELAYREGLEN; - X_SQR_hat *= INV_MAX_DELAYREGLEN; + tempF_fx = BASOP_Util_Add_Mant32Exp( L_add( temp_A_fx, temp_B_fx ), sub( 31, sub( q_com, 4 ) ), hStereoTCA->mem_tempF_fx, hStereoTCA->mem_tempF_exp, &temp ); + Word16 tempF_exp = temp; + hStereoTCA->mem_tempF_fx = temp_B_fx; + move32(); + hStereoTCA->mem_tempF_exp = sub( 31, sub( q_com, 4 ) ); + move16(); - beta_reg = 0; - tempF = X_SQR_hat - ( X_hat * X_hat ); - if ( tempF != 0 ) + alpha_fx = 30474 /* 0.93f in Q15*/; + move16(); + IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, add( hStereoTCA->ica_envVarLT_exp, 2 ), &temp ) > 0 ) { - beta_reg = ( XY_hat - X_hat * Y_hat ) / tempF; + alpha_fx = 27197 /* 0.83f in Q15*/; } - alpha_reg = ( Y_hat - beta_reg * X_hat ); - reg_prv_corr = beta_reg * MAX_DELAYREGLEN + alpha_reg; - - if ( TRUNC( reg_prv_corr ) <= -L_NCSHIFT_DS ) + ELSE IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, add( hStereoTCA->ica_envVarLT_exp, 1 ), &temp ) > 0 ) { - reg_prv_corr = -L_NCSHIFT_DS + 1; + alpha_fx = 27853 /* 0.85f in Q15*/; } - - if ( TRUNC( reg_prv_corr ) >= L_NCSHIFT_DS ) + ELSE IF( BASOP_Util_Add_Mant32Exp( tempF_fx, tempF_exp, -hStereoTCA->ica_envVarLT_fx, hStereoTCA->ica_envVarLT_exp, &temp ) > 0 ) { - reg_prv_corr = L_NCSHIFT_DS - 1; + alpha_fx = 29491 /* 0.9f in Q15*/; } + move16(); + hStereoTCA->corrStatsSmoothFac_fx = alpha_fx; + move32(); - bias_par = A_BIAS * hStereoTCA->smooth_dist_reg_prv_corr + B_BIAS; - bias_par = min( bias_par, XH_BIAS ); - bias_par = max( bias_par, XL_BIAS ); + /* long term corr Stats estimation */ + v_multc_fixed_16( hStereoTCA->corrEstLT_fx, alpha_fx, hStereoTCA->corrEstLT_fx, 2 * L_NCSHIFT_DS + 1 ); + v_multc_fixed_16( corrEst_fx, sub( MAX_16, alpha_fx ), corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); + v_add_fixed_me( hStereoTCA->corrEstLT_fx, hStereoTCA->corrEstLT_exp, corrEst_fx, corrEst_exp, hStereoTCA->corrEstLT_fx, &hStereoTCA->corrEstLT_exp, 2 * L_NCSHIFT_DS + 1, 0 ); - width_par = A_WIDTH * hStereoTCA->smooth_dist_reg_prv_corr + B_WIDTH; - width_par = min( width_par, XH_WIDTH ); - width_par = max( width_par, XL_WIDTH ); + hStereoTCA->ica_envVarLT_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->ica_envVarLT_fx, SMOOTH_ENV_FACTOR_FX_Q15 ), hStereoTCA->ica_envVarLT_exp, Mpy_32_16_1( tempF_fx, ONE_IN_Q15 - SMOOTH_ENV_FACTOR_FX_Q15 ), tempF_exp, &hStereoTCA->ica_envVarLT_exp ); // SMOOTH_ENV_FACTOR_FX_Q15 + move32(); - win_width = (int16_t) ( width_par * ( 4 * L_NCSHIFT_DS + 1 ) ); - win_bias = bias_par; - k1 = 0.5f * ( 1.0f + win_bias ); - k2 = 0.5f * ( 1.0f - win_bias ); + Copy32( hStereoTCA->corrEstLT_fx, corrEst_fx, 2 * L_NCSHIFT_DS + 1 ); + corrEst_exp = hStereoTCA->corrEstLT_exp; + move16(); - for ( i = 0; i < ( 2 * L_NCSHIFT_DS - 2 * win_width ); i++ ) + Y_hat_fx = hStereoTCA->delay_0_mem_fx[0]; + move32(); + Y_hat_exp = hStereoTCA->delay_0_mem_exp; + move16(); + + /* Note: keep X_hat and X_SQR_hat calculations inside the loop to allow future tuning of MAX_DELAYREGLEN */ + FOR( i = 1; i < MAX_DELAYREGLEN; i++ ) { - loc_weight_win[i] = win_bias; + X_hat_fx = BASOP_Util_Add_Mant32Exp( X_hat_fx, X_hat_exp, L_shl( i, 27 ), 4, &X_hat_exp ); + Y_hat_fx = BASOP_Util_Add_Mant32Exp( Y_hat_fx, Y_hat_exp, hStereoTCA->delay_0_mem_fx[i], hStereoTCA->delay_0_mem_exp, &Y_hat_exp ); + XY_hat_fx = BASOP_Util_Add_Mant32Exp( XY_hat_fx, XY_hat_exp, Mpy_32_32( hStereoTCA->delay_0_mem_fx[i], L_shl( i, 27 ) ), add( 4, hStereoTCA->delay_0_mem_exp ), &XY_hat_exp ); + X_SQR_hat_fx = BASOP_Util_Add_Mant32Exp( X_SQR_hat_fx, X_SQR_hat_exp, Mpy_32_32( L_shl( i, 27 ), L_shl( i, 27 ) ), 8, &X_SQR_hat_exp ); } - for ( i = ( 2 * L_NCSHIFT_DS - 2 * win_width ); i <= ( 2 * L_NCSHIFT_DS + 2 * win_width ); i++ ) + X_hat_fx = Mpy_32_16_1( X_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + Y_hat_fx = Mpy_32_16_1( Y_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + XY_hat_fx = Mpy_32_16_1( XY_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + X_SQR_hat_fx = Mpy_32_16_1( X_SQR_hat_fx, INV_MAX_DELAYREGLEN_FX_Q15 ); + + beta_reg_fx = 0; + move32(); + beta_reg_exp = 0; + move16(); + tempF_fx = BASOP_Util_Add_Mant32Exp( X_SQR_hat_fx, X_SQR_hat_exp, L_negate( Mpy_32_32( X_hat_fx, X_hat_fx ) ), shl( X_hat_exp, 1 ), &tempF_exp ); + + IF( tempF_fx != 0 ) { - loc_weight_win[i] = k1 + k2 * cosf( EVS_PI * ( ( i - 2 * L_NCSHIFT_DS ) / ( 2.0f * win_width ) ) ); + temp32 = BASOP_Util_Add_Mant32Exp( XY_hat_fx, XY_hat_exp, L_negate( Mpy_32_32( X_hat_fx, Y_hat_fx ) ), add( X_hat_exp, Y_hat_exp ), &exp ); + beta_reg_fx = BASOP_Util_Divide3232_Scale_cadence( temp32, tempF_fx, &beta_reg_exp ); + if ( beta_reg_fx ) + { + beta_reg_exp = add( beta_reg_exp, sub( exp, tempF_exp ) ); + } } - for ( i = ( 2 * L_NCSHIFT_DS + 2 * win_width ); i < ( 4 * L_NCSHIFT_DS + 1 ); i++ ) + alpha_reg_fx = BASOP_Util_Add_Mant32Exp( Y_hat_fx, Y_hat_exp, L_negate( Mpy_32_32( X_hat_fx, beta_reg_fx ) ), add( X_hat_exp, beta_reg_exp ), &alpha_reg_exp ); + reg_prv_corr_fx = BASOP_Util_Add_Mant32Exp( alpha_reg_fx, alpha_reg_exp, Mpy_32_32( beta_reg_fx, L_shl( MAX_DELAYREGLEN, 27 ) ), add( 4, beta_reg_exp ), ®_prv_corr_exp ); + + IF( LE_16( TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ), -L_NCSHIFT_DS ) ) { - loc_weight_win[i] = win_bias; + reg_prv_corr_fx = -L_NCSHIFT_DS + 1; + move32(); + reg_prv_corr_exp = 31; + move16(); } - for ( i = 0, j = L_NCSHIFT_DS - TRUNC( reg_prv_corr ); i < 2 * L_NCSHIFT_DS + 1; i++, j++ ) + IF( GE_16( TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ), L_NCSHIFT_DS ) ) { - corrEst[i] *= loc_weight_win[j]; + reg_prv_corr_fx = L_NCSHIFT_DS - 1; + move32(); + reg_prv_corr_exp = 31; + move16(); } - if ( hStereoTCA->prevTargetGain < 0.8f && vad_flag1 ) + bias_par_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->smooth_dist_reg_prv_corr_fx, A_BIAS_FX_Q15 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, L_shl( B_BIAS_FX_Q15, Q16 ), 0, &bias_par_exp ); + + Word32 XH_BIAS_tmp = L_shl( XH_BIAS_FX_Q15, Q16 ); + Word32 XL_BIAS_tmp = L_shl( XL_BIAS_FX_Q15, Q16 ); + + IF( bias_par_exp < 0 ) + { + bias_par_fx = L_shl( bias_par_fx, bias_par_exp ); + bias_par_exp = 0; + move16(); + } + ELSE + { + XH_BIAS_tmp = L_shr( XH_BIAS_tmp, bias_par_exp ); + XL_BIAS_tmp = L_shr( XL_BIAS_tmp, bias_par_exp ); + } + + bias_par_fx = L_min( bias_par_fx, XH_BIAS_tmp ); + bias_par_fx = L_max( bias_par_fx, XL_BIAS_tmp ); + bias_par_fx = L_shr( bias_par_fx, bias_par_exp ); + bias_par_exp = 0; + move16(); + + width_par_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoTCA->smooth_dist_reg_prv_corr_fx, A_WIDTH_FX_Q31 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, B_WIDTH_FX_Q31, 0, &width_par_exp ); + Word32 XH_WIDTH_tmp = L_shl( XH_WIDTH_FX_Q15, Q16 ); + Word32 XL_WIDTH_tmp = L_shl( XL_WIDTH_FX_Q15, Q16 ); + + IF( width_par_exp < 0 ) + { + width_par_fx = L_shl( width_par_fx, width_par_exp ); + width_par_exp = 0; + move16(); + } + ELSE + { + XH_WIDTH_tmp = L_shr( XH_WIDTH_tmp, width_par_exp ); + XL_WIDTH_tmp = L_shr( XL_WIDTH_tmp, width_par_exp ); + } + width_par_fx = L_min( width_par_fx, XH_WIDTH_tmp ); + width_par_fx = L_max( width_par_fx, XL_WIDTH_tmp ); + width_par_fx = L_shl( width_par_fx, width_par_exp ); + width_par_exp = 0; + move16(); + + win_width = (Word16) L_shr( Mpy_32_32( width_par_fx, 1350565888 /* ( 4L_NCSHIFT_DS + 1 ) in Q23 */ ), sub( 31, add( width_par_exp, 8 ) ) ); + + win_bias_fx = round_fx( bias_par_fx ); // Q15 + + k1_fx = add( MAX_16 >> 1, shr( win_bias_fx, 1 ) ); // Q15 + k2_fx = sub( MAX_16 >> 1, shr( win_bias_fx, 1 ) ); // Q15 + + FOR( i = 0; i < sub( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i++ ) + { + loc_weight_win_fx[i] = win_bias_fx; // Q15 + move16(); + } + + FOR( i = sub( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i <= add( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i++ ) + { + Word16 cos_inp = BASOP_Util_Divide1616_Scale( sub( i, 2 * L_NCSHIFT_DS ), shl( win_width, 1 ), &exp ); + cos_inp = shr_sat( cos_inp, sub( 0, exp ) ); + cos_inp = getCosWord16R2( shr( cos_inp, 1 ) ); + loc_weight_win_fx[i] = add( k1_fx, mult( k2_fx, cos_inp ) ); + move16(); + } + + FOR( i = add( 2 * L_NCSHIFT_DS, shl( win_width, 1 ) ); i < ( 4 * L_NCSHIFT_DS + 1 ); i++ ) + { + loc_weight_win_fx[i] = win_bias_fx; // Q15 + move16(); + } + + Word16 x = TRUNC_FX( reg_prv_corr_fx, reg_prv_corr_exp ); + move16(); + for ( i = 0, j = sub( L_NCSHIFT_DS, x ); i < 2 * L_NCSHIFT_DS + 1; i++, j++ ) + { + corrEst_fx[i] = Mpy_32_16_1( corrEst_fx[i], loc_weight_win_fx[j] ); + move32(); + } + test(); + test(); + IF( LT_32( hStereoTCA->prevTargetGain_fx, 429496730 /*0.8f in Q29*/ ) && vad_flag1 ) { /* ch 2 is prev reference channel */ - v_multc( corrEst, 1.2f, corrEst, L_NCSHIFT_DS + 1 ); - v_multc( corrEst + L_NCSHIFT_DS + 1, 0.833f, corrEst + L_NCSHIFT_DS + 1, L_NCSHIFT_DS ); + v_multc_fixed( corrEst_fx, 644245095 /*1.2f in Q29*/, corrEst_fx, L_NCSHIFT_DS + 1 ); + v_multc_fixed( corrEst_fx + L_NCSHIFT_DS + 1, 447213470 /* 0.833 in Q29*/, corrEst_fx + L_NCSHIFT_DS + 1, L_NCSHIFT_DS ); + corrEst_exp = add( corrEst_exp, 2 ); } - else if ( hStereoTCA->prevTargetGain > 1.2f && vad_flag1 ) + ELSE IF( GT_32( hStereoTCA->prevTargetGain_fx, 644245094 /*1.2f in Q29*/ ) && vad_flag1 ) { /* ch 1 is prev reference channel */ - v_multc( corrEst, 0.833f, corrEst, L_NCSHIFT_DS ); - v_multc( corrEst + L_NCSHIFT_DS, 1.2f, corrEst + L_NCSHIFT_DS, L_NCSHIFT_DS + 1 ); + v_multc_fixed( corrEst_fx, 447213470 /* 0.833 f in Q29*/, corrEst_fx, L_NCSHIFT_DS ); + v_multc_fixed( corrEst_fx + L_NCSHIFT_DS, 644245095 /*1.2f in Q29*/, corrEst_fx + L_NCSHIFT_DS, L_NCSHIFT_DS + 1 ); + corrEst_exp = add( corrEst_exp, 2 ); } - - if ( corrEst_ncorr > 0.8f && vad_flag1 ) + test(); + IF( BASOP_Util_Add_Mant32Exp( corrEst_ncorr_fx, corrEst_ncorr_exp, -429496730 /*0.8f in Q29*/, 2, &exp ) > 0 && vad_flag1 ) { - i = max( 0, hStereoTCA->prevCorrLagStats[0] - 1 + L_NCSHIFT_DS ); - j = min( 2 * L_NCSHIFT_DS, hStereoTCA->prevCorrLagStats[0] + 1 + L_NCSHIFT_DS ); - k = j - i + 1; - v_multc( corrEst + i, 1.2f, corrEst + i, k ); + i = s_max( 0, add( hStereoTCA->prevCorrLagStats[0], -1 + L_NCSHIFT_DS ) ); + j = s_min( 2 * L_NCSHIFT_DS, add( hStereoTCA->prevCorrLagStats[0], 1 + L_NCSHIFT_DS ) ); + k = add( sub( j, i ), 1 ); + + v_multc_fixed( corrEst_fx, ONE_IN_Q29 /*1.0f in Q29*/, corrEst_fx, i ); // to allign in same exp + v_multc_fixed( corrEst_fx + i, 644245095 /*1.2f in Q29*/, corrEst_fx + i, k ); + v_multc_fixed( corrEst_fx + i + k, ONE_IN_Q29 /*1.0f in Q29*/, corrEst_fx + i + k, sub( 2 * L_NCSHIFT_DS + 1, i + k ) ); // to allign in same exp + corrEst_exp = add( corrEst_exp, 2 ); } /* Initial corr lag estimate */ - corrLagStats[0] = maximum( corrEst, ( lagSearchRange[1] - lagSearchRange[0] + 1 ), &tempF ); - corrLagStats[0] += lagSearchRange[0]; + corrLagStats[0] = maximum_32_fx( corrEst_fx, add( sub( lagSearchRange[1], lagSearchRange[0] ), 1 ), &tempF_fx ); + move16(); + tempF_exp = corrEst_exp; + move16(); + corrLagStats[0] = add( corrLagStats[0], lagSearchRange[0] ); + move16(); - stmp = corrLagStats[0] * dsFactor; - hStereoClassif->unclr_fv[E_corrLagStats0] = (float) stmp; - hStereoClassif->xtalk_fv[E_corrLagStats0] = (float) stmp; - hStereoClassif->xtalk_fv[E_ica_corr_value0] = tempF; + stmp = i_mult( corrLagStats[0], dsFactor ); + hStereoClassif->unclr_fv_fx[E_corrLagStats0] = L_shl( stmp, Q15 ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrLagStats0] = L_shl( stmp, Q15 ); + move32(); + hStereoClassif->xtalk_fv_fx[E_ica_corr_value0] = L_shl( tempF_fx, sub( tempF_exp, Q16 ) ); + move32(); - if ( vad_flag1 == 0 && alpha > 0.7f ) + test(); + if ( vad_flag1 == 0 && GT_16( alpha_fx, 22938 /* 0.7f in Q15 */ ) ) { corrLagStats[0] = 0; + move16(); } - dist_reg_prv_corr = fabsf( reg_prv_corr - corrLagStats[0] ); - - if ( vad_flag1 == 1 && vad_flag2 == 1 ) + dist_reg_prv_corr_fx = L_abs( BASOP_Util_Add_Mant32Exp( reg_prv_corr_fx, reg_prv_corr_exp, -corrLagStats[0], Q31, &dist_reg_prv_corr_exp ) ); + test(); + IF( EQ_16( vad_flag1, 1 ) && EQ_16( vad_flag2, 1 ) ) { - hStereoTCA->smooth_dist_reg_prv_corr = SMOOTH_DIST_FACTOR * hStereoTCA->smooth_dist_reg_prv_corr + ( 1.0f - SMOOTH_DIST_FACTOR ) * dist_reg_prv_corr; - - mvr2r( &( hStereoTCA->delay_0_mem[1] ), &( hStereoTCA->delay_0_mem[0] ), MAX_DELAYREGLEN - 1 ); - hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1] = 0.2f * hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1] + 0.8f * corrLagStats[0]; + hStereoTCA->smooth_dist_reg_prv_corr_fx = BASOP_Util_Add_Mant32Exp( Mpy_32_16_1( hStereoTCA->smooth_dist_reg_prv_corr_fx, SMOOTH_DIST_FACTOR_FX_Q15 ), hStereoTCA->smooth_dist_reg_prv_corr_exp, Mpy_32_16_1( dist_reg_prv_corr_fx, MAX_16 - SMOOTH_DIST_FACTOR_FX_Q15 ), dist_reg_prv_corr_exp, &hStereoTCA->smooth_dist_reg_prv_corr_exp ); + move32(); + Copy32( &( hStereoTCA->delay_0_mem_fx[1] ), &( hStereoTCA->delay_0_mem_fx[0] ), MAX_DELAYREGLEN - 1 ); - if ( fabsf( reg_prv_corr - hStereoTCA->delay_0_mem[0] ) > 25 ) + hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1] = BASOP_Util_Add_Mant32Exp( Mpy_32_32( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], 429496730 /* 0.2 in Q31*/ ), hStereoTCA->delay_0_mem_exp, L_mult0( 26214 /* 0.8 in Q15*/, corrLagStats[0] ), Q16, &temp ); + move32(); + Word32 inpp = L_abs( BASOP_Util_Add_Mant32Exp( reg_prv_corr_fx, reg_prv_corr_exp, -hStereoTCA->delay_0_mem_fx[0], hStereoTCA->delay_0_mem_exp, &exp ) ); + inpp = L_shr( inpp, sub( Q31, exp ) ); + IF( GT_32( inpp, 25 ) ) { - set_f( &( hStereoTCA->delay_0_mem[0] ), hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1], MAX_DELAYREGLEN - 1 ); + set32_fx( &( hStereoTCA->delay_0_mem_fx[0] ), hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], MAX_DELAYREGLEN - 1 ); + hStereoTCA->delay_0_mem_exp = temp; + move16(); + } + ELSE + { + IF( GT_16( temp, hStereoTCA->delay_0_mem_exp ) ) + { + scale_sig32( hStereoTCA->delay_0_mem_fx, MAX_DELAYREGLEN - 1, sub( hStereoTCA->delay_0_mem_exp, temp ) ); + hStereoTCA->delay_0_mem_exp = temp; + move16(); + } + ELSE + { + hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1] = L_shl( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], sub( temp, hStereoTCA->delay_0_mem_exp ) ); + move32(); + } } } - else + ELSE { - hStereoTCA->smooth_dist_reg_prv_corr = 0.; + hStereoTCA->smooth_dist_reg_prv_corr_fx = 0; + move32(); + hStereoTCA->smooth_dist_reg_prv_corr_exp = 0; + move16(); } - - if ( vad_flag1 == 0 || vad_flag2 == 0 ) + test(); + IF( vad_flag1 == 0 || vad_flag2 == 0 ) { - corrLagStats[0] = TRUNC( hStereoTCA->delay_0_mem[MAX_DELAYREGLEN - 1] ); + corrLagStats[0] = TRUNC_FX( hStereoTCA->delay_0_mem_fx[MAX_DELAYREGLEN - 1], hStereoTCA->delay_0_mem_exp ); + move32(); } /* second iteration of xcorr update @ inputFs with interp*/ - tempRK = hStereoTCA->corrEstLT - lagSearchRange[0] + corrLagStats[0]; - set_f( rInterp, 0, MAX_INTERPOLATE ); + tempRK_fx = hStereoTCA->corrEstLT_fx + add( -lagSearchRange[0], corrLagStats[0] ); + set32_fx( rInterp_fx, 0, MAX_INTERPOLATE ); + set16_fx( rInterp_exp, 0, MAX_INTERPOLATE ); /* select the Rk interp sinc window */ - winInterp = ica_sincInterp4 + SINC_ORDER1; - if ( dsFactor == 2 ) + winInterp_fx = ica_sincInterp4_fx + SINC_ORDER1; + + IF( EQ_16( dsFactor, 2 ) ) { - winInterp = ica_sincInterp2 + SINC_ORDER1; + winInterp_fx = ica_sincInterp2_fx + SINC_ORDER1; } - else if ( dsFactor == 6 ) + ELSE IF( EQ_16( dsFactor, 6 ) ) { - winInterp = ica_sincInterp6 + SINC_ORDER1; + winInterp_fx = ica_sincInterp6_fx + SINC_ORDER1; } - corrLagStats[1] = corrLagStats[0] * dsFactor; - - interpMin = max( -( dsFactor - 1 ), -corrLagStats[1] - L_NCSHIFT_DS * dsFactor ); - interpMax = min( ( dsFactor - 1 ), L_NCSHIFT_DS * dsFactor - corrLagStats[1] ); - interpLen = interpMax - interpMin + 1; + corrLagStats[1] = i_mult( corrLagStats[0], dsFactor ); + move16(); + interpMin = s_max( -sub( dsFactor, 1 ), -add( corrLagStats[1], i_mult( L_NCSHIFT_DS, dsFactor ) ) ); + interpMax = s_min( sub( dsFactor, 1 ), sub( i_mult( L_NCSHIFT_DS, dsFactor ), corrLagStats[1] ) ); + interpLen = add( sub( interpMax, interpMin ), 1 ); for ( i = interpMin, k = 0; i <= interpMax; i++, k++ ) { - rInterp[k] = 0.0f; - for ( j = -SINC_ORDER1 / dsFactor; j <= SINC_ORDER1 / dsFactor; j++ ) + rInterp_fx[k] = 0; + move32(); + FOR( j = -idiv1616( SINC_ORDER1, dsFactor ); j <= idiv1616( SINC_ORDER1, dsFactor ); j++ ) { - m = j * dsFactor; - if ( ( m - i >= -SINC_ORDER1 ) && ( m - i <= SINC_ORDER1 ) ) + m = i_mult( j, dsFactor ); + test(); + IF( GE_16( sub( m, i ), -SINC_ORDER1 ) && LE_16( sub( m, i ), SINC_ORDER1 ) ) { - if ( j > lagSearchRange[1] - corrLagStats[0] ) + IF( GT_16( j, sub( lagSearchRange[1], corrLagStats[0] ) ) ) { - rInterp[k] += winInterp[m - i] * tempRK[lagSearchRange[1] - corrLagStats[0]]; + rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[lagSearchRange[1] - corrLagStats[0]], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); + move32(); + rInterp_exp[k] = temp; + move16(); } - else if ( j < lagSearchRange[0] - corrLagStats[0] ) + ELSE IF( LT_16( j, sub( lagSearchRange[0], corrLagStats[0] ) ) ) { - rInterp[k] += winInterp[m - i] * tempRK[lagSearchRange[0] - corrLagStats[0]]; + rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[lagSearchRange[0] - corrLagStats[0]], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); + move32(); + rInterp_exp[k] = temp; + move16(); } - else + ELSE { - rInterp[k] += winInterp[m - i] * tempRK[j]; + rInterp_fx[k] = BASOP_Util_Add_Mant32Exp( rInterp_fx[k], rInterp_exp[k], Mpy_32_32( tempRK_fx[j], winInterp_fx[m - i] ), hStereoTCA->corrEstLT_exp, &temp ); + move32(); + rInterp_exp[k] = temp; + move16(); } } } } - corrLagStats[1] += ( maximum( rInterp, interpLen, &tempF ) + interpMin ); + temp = rInterp_exp[0]; + move16(); + FOR( i = 0; i < MAX_INTERPOLATE; i++ ) + { + temp = s_max( temp, rInterp_exp[i] ); + } + + FOR( i = 0; i < MAX_INTERPOLATE; i++ ) + { + rInterp_fx[i] = L_shl( rInterp_fx[i], sub( rInterp_exp[i], temp ) ); + move32(); + } + + corrLagStats[1] = add( corrLagStats[1], add( maximum_32_fx( rInterp_fx, interpLen, &tempF_fx ), interpMin ) ); + move16(); /* save corr lag stats for the current frame */ - mvs2s( corrLagStats, hStereoTCA->corrLagStats, 3 ); + Copy( corrLagStats, hStereoTCA->corrLagStats, 3 ); return; } @@ -1027,7 +1750,6 @@ static void corrStatsEst( return; } #endif - /*--------------------------------------------------------------- * Function estDownmixGain() * @@ -1104,7 +1826,150 @@ static void estDownmixGain( * * Recalculates the memories corresponding to the previous frame. * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void icaMemUpdate_fx( + Encoder_State **sts, /* i/o: encoder state structure */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word32 *bufChanL, /* i/o: L signal correction from previous frame q_com*/ + Word32 *bufChanR, /* i/o: R signal correction from previous frame q_com*/ + Word16 q_com, + const Word16 lMemRecalc, /* i : memory length at input Sampling Rate */ + const Word16 lMemRecalc_SCh, /* i : SCh memory length at input Sampling Rate*/ + const Word16 input_frame /* i : frame length */ +) +{ + Word32 *ptr1, *ptr2; + Word16 i; + Word32 ratio_L, One_m_Ratio; + + IF( EQ_16( hCPE->element_mode, IVAS_CPE_TD ) ) + { + /* Recalc of the memories - Downmix @ inputFs */ + /*----------------------------------------------------------------* + * Create first part of the mixture using the old ratios + *----------------------------------------------------------------*/ + + IF( hCPE->hStereoTD->tdm_last_SM_flag ) + { + ratio_L = hCPE->hStereoTD->tdm_last_ratio_SM_fx; + move32(); + One_m_Ratio = L_sub( ratio_L, MAX_32 ); + } + ELSE + { + ratio_L = hCPE->hStereoTD->tdm_last_ratio_fx; + move32(); + One_m_Ratio = L_sub( MAX_32, ratio_L ); + } + + ptr1 = sts[0]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ); + ptr2 = sts[1]->input32_fx - add( lMemRecalc, lMemRecalc_SCh ); + + IF( EQ_16( hCPE->last_element_mode, IVAS_CPE_TD ) ) + { + IF( hCPE->hStereoTD->flag_skip_DMX ) + { + FOR( i = lMemRecalc_SCh; i < add( lMemRecalc, lMemRecalc_SCh ); i++ ) + { + ptr1[i] = bufChanL[i]; + move32(); + ptr2[i] = bufChanR[i]; + move32(); + } + } + ELSE + { + FOR( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + ptr1[i] = L_add( Mpy_32_32( bufChanR[i], One_m_Ratio ), Mpy_32_32( bufChanL[i], ratio_L ) ); + move32(); + ptr2[i] = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + move32(); + } + } + } + ELSE + { + Word16 fac, incr; + Word32 tmp1, tmp2; + + /* reset the past input signal (the signal is used in SWB BWE) */ + set32_fx( sts[1]->input32_fx - input_frame, 0, input_frame ); + + IF( hCPE->hStereoTD->flag_skip_DMX ) + { + /* reconstruction of the Secondary channel past segment */ + FOR( i = 0; i < lMemRecalc_SCh; i++ ) + { + ptr2[i] = L_add( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + move32(); + } + + /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ + fac = div_s( 1, lMemRecalc ); // Q15 + incr = fac; // Q15 + move16(); + + FOR( i = lMemRecalc_SCh; i < add( lMemRecalc, lMemRecalc_SCh ); i++ ) + { + tmp1 = bufChanL[i]; + move32(); + tmp2 = bufChanR[i]; + move32(); + + ptr1[i] = L_add( Mpy_32_16_1( ptr1[i], sub( MAX_16, fac ) ), Mpy_32_16_1( tmp1, fac ) ); + move32(); + + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + move32(); + + fac = add_sat( fac, incr ); + } + } + ELSE + { + /* reconstruction of the Secondary channel past segment */ + FOR( i = 0; i < lMemRecalc_SCh; i++ ) + { + ptr2[i] = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + move32(); + } + + /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ + fac = div_s( 1, lMemRecalc ); // Q15 + incr = fac; // Q15 + move16(); + FOR( i = lMemRecalc_SCh; i < add( lMemRecalc, lMemRecalc_SCh ); i++ ) + { + tmp1 = L_add( Mpy_32_32( bufChanR[i], One_m_Ratio ), Mpy_32_32( bufChanL[i], ratio_L ) ); + tmp2 = L_sub( Mpy_32_32( bufChanL[i], One_m_Ratio ), Mpy_32_32( bufChanR[i], ratio_L ) ); + + ptr1[i] = L_add( Mpy_32_16_1( ptr1[i], sub( MAX_16, fac ) ), Mpy_32_16_1( tmp1, fac ) ); + move32(); + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + move32(); + + fac = add_sat( fac, incr ); + } + } + } + } + + IF( hCPE->hStereoICBWE != NULL ) + { + assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS ); + i = NS2SA( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS ); + Copy_Scale_sig_32_16( bufChanL + sub( add( lMemRecalc, lMemRecalc_SCh ), i ), hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], i, -Q16 ); + Copy_Scale_sig_32_16( bufChanR + sub( add( lMemRecalc, lMemRecalc_SCh ), i ), hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], i, -Q16 ); + hCPE->hStereoICBWE->q_dataChan_fx = sub( q_com, Q16 ); + move16(); + } + return; +} +#else static void icaMemUpdate( Encoder_State **sts, /* i/o: encoder state structure */ CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ @@ -1178,63 +2043,624 @@ static void icaMemUpdate( fac = 1.0f / (float) lMemRecalc; incr = fac; - for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) - { - tmp1 = bufChanL[i]; - tmp2 = bufChanR[i]; + for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + tmp1 = bufChanL[i]; + tmp2 = bufChanR[i]; + + ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + + fac += incr; + } + } + else + { + /* reconstruction of the Secondary channel past segment */ + for ( i = 0; i < lMemRecalc_SCh; i++ ) + { + ptr2[i] = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + } + + /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ + fac = 1.0f / (float) lMemRecalc; + incr = fac; + + for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) + { + tmp1 = bufChanR[i] * One_m_Ratio + bufChanL[i] * ratio_L; + tmp2 = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + + ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; + /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ + ptr2[i] = tmp2; + + fac += incr; + } + } + } + } + + if ( hCPE->hStereoICBWE != NULL ) + { + assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS ); + i = NS2SA( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS ); + mvr2r( bufChanL + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[0], i ); + mvr2r( bufChanR + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[1], i ); + } + + return; +} +#endif +/*--------------------------------------------------------------- + * stereo_tca_enc() + * + * Stereo temporal inter-channel adjustment/allocation processing module; + * Downmix, convert L/R to M/S. + * ---------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void stereo_tca_enc( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const int16_t input_frame /* i : length of a frame per channel */ +) +{ + /* temp variables */ + int16_t i, dsFactor, lMemRecalc; + Encoder_State **sts; + STEREO_TCA_ENC_HANDLE hStereoTCA; + + /* Buffers, input Left and right channels @ input_Fs*/ + int16_t lMemRecalc_SCh; + float bufChanL[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + float bufChanR[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + float input_mem_loc[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )]; + float *ptrChanL, *ptrChanR; +#ifdef IVAS_FLOAT_FIXED + set_f( bufChanL, 0.0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set_f( bufChanR, 0.0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set_f( input_mem_loc[0], 0.0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + set_f( input_mem_loc[1], 0.0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + Word32 input_mem_loc_fx[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )]; + Word32 bufChanL_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + Word32 bufChanR_fx[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; + Word32 *ptrChanL_fx, *ptrChanR_fx; + + set32_fx( bufChanL_fx, 0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set32_fx( bufChanR_fx, 0, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + set32_fx( input_mem_loc_fx[0], 0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + set32_fx( input_mem_loc_fx[1], 0, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); +#endif + /* Buffers at internal sampling rate, i.e., CORR_INTER_FS */ + float bufChanL_DS[L_FRAME_DS + ADDED_MEM_DS]; + float bufChanR_DS[L_FRAME_DS + ADDED_MEM_DS]; + float *ptrChanL_DS, *ptrChanR_DS; +#ifdef IVAS_FLOAT_FIXED + Word32 bufChanL_DS_fx[L_FRAME_DS + ADDED_MEM_DS]; + Word32 bufChanR_DS_fx[L_FRAME_DS + ADDED_MEM_DS]; + Word32 *ptrChanL_DS_fx, *ptrChanR_DS_fx; +#endif + float *target; +#ifdef IVAS_FLOAT_FIXED + Word32 *target_fx; +#endif + int16_t target_idx; + + int16_t prevNCShift, currentNCShift; + int16_t tempLag[2]; + float corrEstStage2[N_MAX_SHIFT_CHANGE + 1]; +#ifdef IVAS_FLOAT_FIXED + Word32 corrEstStage2_fx[N_MAX_SHIFT_CHANGE + 1]; + Word16 corrEstStage2_exp; +#endif + /* temp variables */ + float tempF, tempF1; +#ifdef IVAS_FLOAT_FIXED + Word32 tempF1_fx; + Word16 tempF1_exp; +#endif + int16_t tempS, tempS_buff[3]; + int16_t maxCorrStatsDev, L_shift_adapt; + int16_t musicMode = 0, neighborLimit; + int32_t input_Fs; + int16_t prev_ICA_flag; + + /* initialization */ + sts = hCPE->hCoreCoder; + hStereoTCA = hCPE->hStereoTCA; + + input_Fs = sts[0]->input_Fs; + + lMemRecalc = NS2SA( input_Fs, L_MEM_RECALC_NS ); + lMemRecalc_SCh = NS2SA( input_Fs, L_MEM_RECALC_SCH_NS ); + + if ( hCPE->element_mode == IVAS_CPE_MDCT ) + { + return; + } + + /* populate L/R memories into current buffers */ + mvr2r( hStereoTCA->memChanL, bufChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( hStereoTCA->memChanR, bufChanR, lMemRecalc + lMemRecalc_SCh ); + + /* pointers to the current frame */ + ptrChanL = bufChanL + lMemRecalc + lMemRecalc_SCh; + ptrChanR = bufChanR + lMemRecalc + lMemRecalc_SCh; +#ifdef IVAS_FLOAT_FIXED + ptrChanL_fx = bufChanL_fx + lMemRecalc + lMemRecalc_SCh; + ptrChanR_fx = bufChanR_fx + lMemRecalc + lMemRecalc_SCh; +#endif + /* copy interleaved stereo data to two channels, e.g., L, R */ + mvr2r( sts[0]->input, ptrChanL, input_frame ); + mvr2r( sts[1]->input, ptrChanR, input_frame ); + + /* UNCLR classifier update */ + if ( hCPE->hStereoClassif->lrtd_mode == 0 ) /* Normal TD mode, no attenuation */ + { + hStereoTCA->LRTD_G_ATT_cnt = 1; + } + else if ( hCPE->hStereoTD != NULL ) + { + if ( hCPE->hStereoTD->tdm_LRTD_flag == 0 ) /* lrtd_mode == 1, but in td section */ + { + hStereoTCA->LRTD_G_ATT_cnt++; + hStereoTCA->LRTD_G_ATT_cnt = min( 1000, hStereoTCA->LRTD_G_ATT_cnt ); + } + } + + if ( hCPE->element_mode != IVAS_CPE_TD ) + { + hStereoTCA->refChanIndx = L_CH_INDX; + hStereoTCA->corrStatsSmoothFac = 0.7f; + estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, 0, input_frame, hCPE->element_mode, NULL, 0 ); + hStereoTCA->prevTargetGain = hStereoTCA->targetGain; +#ifdef DEBUG_MODE_INFO + hStereoTCA->indx_ica_NCShift = 0; +#endif + + /* back up the L/R missing target */ + mvr2r( bufChanL + input_frame, hStereoTCA->memChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( bufChanR + input_frame, hStereoTCA->memChanR, lMemRecalc + lMemRecalc_SCh ); + + hStereoTCA->lMemRecalc = 0; + hStereoTCA->lMemRecalc_12k8 = 0; + hStereoTCA->lMemRecalc_16k = 0; + + return; + } + else if ( hCPE->last_element_mode != IVAS_CPE_TD ) + { + tempF = hStereoTCA->targetGain; + tempF1 = hStereoTCA->prevTargetGain; + tempS = hStereoTCA->prevRefChanIndx; + mvs2s( hStereoTCA->prevCorrLagStats, tempS_buff, 3 ); + stereo_tca_init_enc( hStereoTCA, input_Fs ); +#ifdef IVAS_FLOAT_FIXED + stereo_tca_init_enc_fx( hStereoTCA, input_Fs ); +#endif + hStereoTCA->targetGain = tempF; + hStereoTCA->prevTargetGain = tempF1; + + if ( hCPE->hStereoClassif->lrtd_mode == 1 ) + { + hStereoTCA->targetGain = min( hStereoTCA->targetGain, 1.0f ); + hStereoTCA->prevTargetGain = min( hStereoTCA->prevTargetGain, 1.0f ); + + hStereoTCA->prevTargetGain = 1; + } + + hStereoTCA->prevRefChanIndx = tempS; + mvs2s( tempS_buff, hStereoTCA->prevCorrLagStats, 3 ); + + /* populate memory */ + if ( hCPE->last_element_mode == IVAS_CPE_MDCT ) + { + mvr2r( sts[0]->input - lMemRecalc - lMemRecalc_SCh, bufChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( sts[1]->input - lMemRecalc - lMemRecalc_SCh, bufChanR, lMemRecalc + lMemRecalc_SCh ); + } + } + + /* populate L/R DS memories into current buffers */ + mvr2r( hStereoTCA->memChanL_DS, bufChanL_DS, ADDED_MEM_DS ); + mvr2r( hStereoTCA->memChanR_DS, bufChanR_DS, ADDED_MEM_DS ); + + /* pointers to the current frame of DS */ + ptrChanL_DS = bufChanL_DS + ADDED_MEM_DS; + ptrChanR_DS = bufChanR_DS + ADDED_MEM_DS; +#ifdef IVAS_FLOAT_FIXED + ptrChanL_DS_fx = bufChanL_DS_fx + ADDED_MEM_DS; + ptrChanR_DS_fx = bufChanR_DS_fx + ADDED_MEM_DS; +#endif + /* resample factor */ + dsFactor = (int16_t) ( input_Fs / CORR_INTER_FS ); + + /* resample the stereo channels */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_com; + q_com = L_get_q_buf1( ptrChanL, input_frame ); + q_com = min( q_com, L_get_q_buf1( ptrChanR, input_frame ) ); + q_com = min( q_com, L_get_q_buf1( hStereoTCA->memdecim, 12 ) ) - 4; + + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame ); + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame ); + floatToFixed_arrL32( hStereoTCA->memdecim, hStereoTCA->memdecim_fx, q_com, 12 ); +#endif + + deEmphResample( hStereoTCA, ptrChanL_fx, ptrChanR_fx, ptrChanL_DS_fx, ptrChanR_DS_fx, input_frame, dsFactor ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( ptrChanL_DS_fx, ptrChanL_DS, q_com, input_frame / dsFactor ); + fixedToFloat_arrL32( ptrChanR_DS_fx, ptrChanR_DS, q_com, input_frame / dsFactor ); + fixedToFloat_arrL32( hStereoTCA->memdecim_fx, hStereoTCA->memdecim, q_com, 12 ); +#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + +#endif +#else + deEmphResample( hStereoTCA, ptrChanL, ptrChanR, ptrChanL_DS, ptrChanR_DS, input_frame, dsFactor ); +#endif + /**********************NEED to Allign first 40 index in each channel ************************************/ + /* inter-channel corrStats estimation */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( bufChanL_DS, L_FRAME_DS + ADDED_MEM_DS ); + q_com = min( q_com, L_get_q_buf1( bufChanR_DS, L_FRAME_DS + ADDED_MEM_DS ) ) - 4; + + floatToFixed_arrL32( bufChanL_DS, bufChanL_DS_fx, q_com, L_FRAME_DS + ADDED_MEM_DS ); + floatToFixed_arrL32( bufChanR_DS, bufChanR_DS_fx, q_com, L_FRAME_DS + ADDED_MEM_DS ); + floatToFixed_arrL32( hCPE->hStereoClassif->xtalk_fv, hCPE->hStereoClassif->xtalk_fv_fx, Q15, SSC_MAX_NFEA ); + floatToFixed_arrL32( hCPE->hStereoClassif->unclr_fv, hCPE->hStereoClassif->unclr_fv_fx, Q15, SSC_MAX_NFEA ); + hStereoTCA->prevTargetGain_fx = floatToFixed_32( hStereoTCA->prevTargetGain, Q29 ); +#endif + + corrStatsEst_fx( hStereoTCA, bufChanL_DS_fx + ADDED_MEM_DS, bufChanR_DS_fx + ADDED_MEM_DS, q_com, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( hCPE->hStereoClassif->xtalk_fv_fx, hCPE->hStereoClassif->xtalk_fv, Q15, SSC_MAX_NFEA ); + fixedToFloat_arrL32( hCPE->hStereoClassif->unclr_fv_fx, hCPE->hStereoClassif->unclr_fv, Q15, SSC_MAX_NFEA ); + hCPE->hStereoClassif->ave_ener_L = me2f( hCPE->hStereoClassif->ave_ener_L_fx, hCPE->hStereoClassif->ave_ener_L_fx_e ); + hCPE->hStereoClassif->ave_ener_R = me2f( hCPE->hStereoClassif->ave_ener_R_fx, hCPE->hStereoClassif->ave_ener_R_fx_e ); + hStereoTCA->corrStatsSmoothFac = me2f_16( hStereoTCA->corrStatsSmoothFac_fx, 0 ); +#endif +#else + corrStatsEst( hStereoTCA, bufChanL_DS + ADDED_MEM_DS, bufChanR_DS + ADDED_MEM_DS, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); +#endif + /*-----------------------------------------------------------------* + * refine the ICA stats + *-----------------------------------------------------------------*/ + + prev_ICA_flag = 0; + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec && abs( hStereoTCA->prevCorrLagStats[2] ) != 0 ) + { + prev_ICA_flag = 1; + } + + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || prev_ICA_flag == 1 ) + { + /* initialize the refinement search for NC-shift */ + hStereoTCA->corrLagStats[2] = hStereoTCA->corrLagStats[1]; + + maxCorrStatsDev = N_MAX_SHIFT_CHANGE; + if ( hStereoTCA->corrStatsSmoothFac <= 0.7f ) + { + maxCorrStatsDev = 160; /* L_NCSHIFT_MAX @ 32kHz */ + } + + if ( input_Fs < 32000 ) + { + maxCorrStatsDev = (int16_t) ( maxCorrStatsDev * input_Fs / 32000.0f ); + } + + musicMode = ( hCPE->hCoreCoder[0]->sp_aud_decision0 == 1 || sts[0]->last_core > ACELP_CORE ); + if ( musicMode ) + { + maxCorrStatsDev = 1; + set_s( hStereoTCA->corrLagStats + 1, 0, 2 ); + } + + tempS = ( hStereoTCA->corrLagStats[1] - hStereoTCA->prevCorrLagStats[2] ); + if ( abs( tempS ) > maxCorrStatsDev ) + { + hStereoTCA->corrLagStats[2] = hStereoTCA->prevCorrLagStats[2] + ( ( tempS > 0 ) ? maxCorrStatsDev : -maxCorrStatsDev ); + } + + neighborLimit = maxCorrStatsDev; + + /* refine and search based on the corrlag stats */ + if ( tempS != 0 && dsFactor != 1 && prev_ICA_flag == 0 ) + { + tempF = 0; + if ( !musicMode ) + { + tempLag[0] = min( hStereoTCA->corrLagStats[2], hStereoTCA->prevCorrLagStats[2] ); + tempLag[1] = max( hStereoTCA->corrLagStats[2], hStereoTCA->prevCorrLagStats[2] ); + + neighborLimit = min( 3, maxCorrStatsDev ); + if ( hStereoTCA->prevCorrLagStats[2] < hStereoTCA->corrLagStats[2] ) + { + tempLag[1] = min( tempLag[1], tempLag[0] + neighborLimit ); + } + else + { + tempLag[0] = max( tempLag[0], tempLag[1] - neighborLimit ); + } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 ptrChanL_q = Q_factor_arrL( ptrChanL, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + Word16 ptrChanR_q = Q_factor_arrL( ptrChanR, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanL, ptrChanL_fx, ptrChanL_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanR, ptrChanR_fx, ptrChanR_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); +#endif + utilCrossCorr_fx( ptrChanL_fx, ptrChanL_q, ptrChanR_fx, ptrChanR_q, NULL, corrEstStage2_fx, &corrEstStage2_exp, tempLag, input_frame, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( corrEstStage2_fx, corrEstStage2, ( Q31 - corrEstStage2_exp ), N_MAX_SHIFT_CHANGE + 1 ); +#endif +#else + utilCrossCorr( ptrChanL, ptrChanR, NULL, corrEstStage2, tempLag, input_frame, 0 ); +#endif + hStereoTCA->corrLagStats[2] = maximum( corrEstStage2, ( tempLag[1] - tempLag[0] + 1 ), &tempF ); + hStereoTCA->corrLagStats[2] += tempLag[0]; + } + + if ( abs( tempS ) > neighborLimit ) + { + tempLag[0] = hStereoTCA->corrLagStats[1]; + tempLag[1] = hStereoTCA->corrLagStats[1]; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 ptrChanL_q = Q_factor_arrL( ptrChanL, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + Word16 ptrChanR_q = Q_factor_arrL( ptrChanR, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanL, ptrChanL_fx, ptrChanL_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); + floatToFixed_arrL( ptrChanR, ptrChanR_fx, ptrChanR_q, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX - ( lMemRecalc + lMemRecalc_SCh ) ); +#endif + utilCrossCorr_fx( ptrChanL_fx, ptrChanL_q, ptrChanR_fx, ptrChanR_q, NULL, &tempF1_fx, &tempF1_exp, tempLag, input_frame, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + tempF1 = fixedToFloat_32( tempF1_fx, Q31 - tempF1_exp ); +#endif +#else + utilCrossCorr( ptrChanL, ptrChanR, NULL, &tempF1, tempLag, input_frame, 0 ); +#endif + if ( tempF1 > tempF || musicMode ) + { + hStereoTCA->corrLagStats[2] = hStereoTCA->prevCorrLagStats[2] + ( ( tempS > 0 ) ? min( (int16_t) abs( tempS ), maxCorrStatsDev ) : max( (int16_t) -abs( tempS ), -maxCorrStatsDev ) ); + } + } + + /* restrict the reference channel for +/- variation */ + if ( ( hStereoTCA->corrLagStats[2] < 0 && hStereoTCA->prevCorrLagStats[2] > 0 ) || ( hStereoTCA->corrLagStats[2] > 0 && hStereoTCA->prevCorrLagStats[2] < 0 ) ) + { + hStereoTCA->corrLagStats[2] = 0; + } + } + + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec /*hCPE->hStereoClassif->lrtd_mode*/ == 1 ) /* Content is considered as uncorrelated -> ICA shift is turned off */ + { + hStereoTCA->corrLagStats[2] = 0; + + if ( hCPE->hStereoTD->tdm_LRTD_flag == 1 && prev_ICA_flag == 0 ) + { + hStereoTCA->prevCorrLagStats[2] = 0; + } + } + + /* Perform the following: + 1. adjust samples, + 2. interp shift variation, + 3. gain estimation */ + prevNCShift = (int16_t) abs( hStereoTCA->prevCorrLagStats[2] ); + currentNCShift = (int16_t) abs( hStereoTCA->corrLagStats[2] ); + + if ( hStereoTCA->prevRefChanIndx == L_CH_INDX ) + { + mvr2r( ptrChanL - lMemRecalc - lMemRecalc_SCh, input_mem_loc[0], lMemRecalc + lMemRecalc_SCh ); + v_multc( ptrChanR + prevNCShift - lMemRecalc - lMemRecalc_SCh, hStereoTCA->prevTargetGain, input_mem_loc[1], lMemRecalc + lMemRecalc_SCh ); + } + else + { + mvr2r( ptrChanL + prevNCShift - lMemRecalc - lMemRecalc_SCh, input_mem_loc[0], lMemRecalc + lMemRecalc_SCh ); + v_multc( ptrChanR - lMemRecalc - lMemRecalc_SCh, hStereoTCA->prevTargetGain, input_mem_loc[1], lMemRecalc + lMemRecalc_SCh ); + } + + target = ptrChanR; +#ifdef IVAS_FLOAT_FIXED + target_fx = ptrChanR_fx; +#endif + target_idx = R_CH_INDX; + /* identify target signal to correct for shift variations */ + if ( ( prevNCShift == 0 && hStereoTCA->corrLagStats[2] < 0 ) || ( hStereoTCA->prevRefChanIndx == R_CH_INDX ) ) + { + target = ptrChanL; +#ifdef IVAS_FLOAT_FIXED + target_fx = ptrChanL_fx; +#endif + target_idx = L_CH_INDX; + } + + /* target signal adjustment for temporal shift variations */ + if ( ( prevNCShift - currentNCShift ) != 0 ) + { + L_shift_adapt = L_SHIFT_ADAPT_16k; + if ( input_Fs > INT_FS_16k ) + { + L_shift_adapt = L_SHIFT_ADAPT_MAX; + } + + /* Note!! : Always keep the assert (prevNCShift>>1) below according to the equation used here to get tempS */ + tempS = ( currentNCShift >> 1 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 q_com1 = L_get_q_buf1( bufChanR, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ) - 4; + Word16 q_com2 = L_get_q_buf1( bufChanL, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ) - 4; + floatToFixed_arrL32( bufChanR, bufChanR_fx, q_com1, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + floatToFixed_arrL32( bufChanL, bufChanL_fx, q_com2, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); +#endif + if ( abs( currentNCShift - prevNCShift ) <= min( N_MAX_SHIFT_CHANGE, N_MAX_SHIFT_CHANGE * input_Fs / 32000.0f ) ) + { +#ifdef IVAS_FLOAT_FIXED + adjustTargetSignal_fx( ( target_fx - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 0 ); +#else + adjustTargetSignal( ( target - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 0 ); +#endif + } + else + { + tempS = min( max( tempS, prevNCShift - currentNCShift + L_shift_adapt - input_frame ), prevNCShift - currentNCShift + lMemRecalc ); +#ifdef IVAS_FLOAT_FIXED + adjustTargetSignal_fx( ( target_fx - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 ); +#else + adjustTargetSignal( ( target - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 ); +#endif + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( bufChanR_fx, bufChanR, q_com1, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); + fixedToFloat_arrL32( bufChanL_fx, bufChanL, q_com2, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX ); +#endif + if ( target_idx == L_CH_INDX ) + { + mvr2r( target - tempS, &( input_mem_loc[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), currentNCShift + tempS ); + } + else + { + v_multc( target - tempS, hStereoTCA->prevTargetGain, &( input_mem_loc[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), currentNCShift + tempS ); + } + } + + /* reference channel index */ + if ( hStereoTCA->corrLagStats[2] >= 0 ) + { + hStereoTCA->refChanIndx = L_CH_INDX; + } + else + { + hStereoTCA->refChanIndx = R_CH_INDX; + } + + /* Estimate and quantize the gain for scaling */ + estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, currentNCShift, ( input_frame - currentNCShift ), hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag ); + + /* quantize the corrStats */ + hStereoTCA->indx_ica_NCShift = (int16_t) usquant( ( (float) currentNCShift ) / dsFactor, &tempF, 0, 1.0f, 1 << STEREO_BITS_TCA_CORRSTATS ); + } + else + { + hStereoTCA->refChanIndx = L_CH_INDX; + hStereoTCA->corrLagStats[2] = 0; + hStereoTCA->prevCorrLagStats[2] = 0; + hStereoTCA->indx_ica_NCShift = 0; + + currentNCShift = 0; /* only to avoid compilation warning */ + target = ptrChanL; /* only to avoid compilation warning */ + target_idx = L_CH_INDX; /* only to avoid compilation warning */ + + mvr2r( ptrChanL - lMemRecalc - lMemRecalc_SCh, input_mem_loc[0], lMemRecalc + lMemRecalc_SCh ); + v_multc( ptrChanR - lMemRecalc - lMemRecalc_SCh, hStereoTCA->prevTargetGain, input_mem_loc[1], lMemRecalc + lMemRecalc_SCh ); + + /* Estimate and quantize the gain for scaling */ + estDownmixGain( hStereoTCA, ptrChanL, ptrChanR, 0, input_frame, hCPE->element_mode, hCPE->hStereoClassif, hCPE->hStereoTD->tdm_LRTD_flag ); + } + + /*-----------------------------------------------------------------* + * updates and memory backups + *-----------------------------------------------------------------*/ - ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; - /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ - ptr2[i] = tmp2; + /* back up the L/R missing target */ + mvr2r( bufChanL + input_frame, hStereoTCA->memChanL, lMemRecalc + lMemRecalc_SCh ); + mvr2r( bufChanR + input_frame, hStereoTCA->memChanR, lMemRecalc + lMemRecalc_SCh ); - fac += incr; - } - } - else - { - /* reconstruction of the Secondary channel past segment */ - for ( i = 0; i < lMemRecalc_SCh; i++ ) - { - ptr2[i] = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; - } + IF( currentNCShift != 0 ) + { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( ptrChanL, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); + q_com = s_min( q_com, L_get_q_buf1( ptrChanR, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ) ) - 4; + floatToFixed_arrL32( ptrChanL, ptrChanL_fx, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); + floatToFixed_arrL32( ptrChanR, ptrChanR_fx, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); +#endif + /* Temporal channel adjustment of the LA samples based on the NC shift */ + tcaTargetCh_LA_fx( hStereoTCA, ptrChanL_fx, ptrChanR_fx, &q_com, currentNCShift, input_frame ); - /* overlap-add smoothing to equalize for different DMX signal energy between DFT and TD stereo */ - fac = 1.0f / (float) lMemRecalc; - incr = fac; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( ptrChanL_fx, ptrChanL, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); + fixedToFloat_arrL32( ptrChanR_fx, ptrChanR, q_com, input_frame + NS2SA( L_mult0( input_frame, FRAMES_PER_SEC ), L_SAMPLES_LA_NS ) ); +#endif + } +#else + if ( currentNCShift != 0 ) + { + /* Temporal channel adjustment of the LA samples based on the NC shift */ + tcaTargetCh_LA( hStereoTCA, ptrChanL, ptrChanR, currentNCShift, input_frame ); + } +#endif + /* Update of changed samples corresponding to the memory */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + q_com = L_get_q_buf1( input_mem_loc[0], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + q_com = s_min( q_com, L_get_q_buf1( input_mem_loc[1], NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ) ) - 4; + floatToFixed_arrL32( input_mem_loc[0], input_mem_loc_fx[0], q_com, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); + floatToFixed_arrL32( input_mem_loc[1], input_mem_loc_fx[1], q_com, NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS ) ); - for ( i = lMemRecalc_SCh; i < lMemRecalc + lMemRecalc_SCh; i++ ) - { - tmp1 = bufChanR[i] * One_m_Ratio + bufChanL[i] * ratio_L; - tmp2 = bufChanL[i] * One_m_Ratio - bufChanR[i] * ratio_L; + floatToFixed_arrL32( sts[0]->input_buff, sts[0]->input_buff32_fx, q_com, 1965 ); + floatToFixed_arrL32( sts[1]->input_buff, sts[1]->input_buff32_fx, q_com, 1965 ); - ptr1[i] = ( 1.0f - fac ) * ptr1[i] + fac * tmp1; - /*ptr2[i] = (1.0f - fac) * ptr2[i] + fac * tmp2;*/ /* the secondary channel (downmixed) buffer of DFT stereo is empty ! */ - ptr2[i] = tmp2; + hCPE->hStereoTD->tdm_last_ratio_SM_fx = floatToFixed_32( hCPE->hStereoTD->tdm_last_ratio_SM, Q31 ); + hCPE->hStereoTD->tdm_last_ratio_fx = floatToFixed_32( hCPE->hStereoTD->tdm_last_ratio, Q31 ); +#endif + icaMemUpdate_fx( sts, hCPE, input_mem_loc_fx[0], input_mem_loc_fx[1], q_com, lMemRecalc, lMemRecalc_SCh, input_frame ); - fac += incr; - } - } - } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( sts[0]->input_buff32_fx, sts[0]->input_buff, q_com, 1965 ); + fixedToFloat_arrL32( sts[1]->input_buff32_fx, sts[1]->input_buff, q_com, 1965 ); + if ( hCPE->hStereoICBWE != NULL ) + { + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[0], hCPE->hStereoICBWE->icbwe_inp_mem[0], hCPE->hStereoICBWE->q_dataChan_fx, NS2SA( 48000, L_MEM_RECALC_TBE_NS ) ); + fixedToFloat_arr( hCPE->hStereoICBWE->icbwe_inp_mem_fx[1], hCPE->hStereoICBWE->icbwe_inp_mem[1], hCPE->hStereoICBWE->q_dataChan_fx, NS2SA( 48000, L_MEM_RECALC_TBE_NS ) ); + } +#endif +#else + icaMemUpdate( sts, hCPE, input_mem_loc[0], input_mem_loc[1], lMemRecalc, lMemRecalc_SCh, input_frame ); +#endif + /* populate the st->input target buffer */ + if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || prev_ICA_flag == 1 ) + { + mvr2r( target + currentNCShift, sts[target_idx]->input, input_frame ); } - if ( hCPE->hStereoICBWE != NULL ) + if ( hCPE->element_mode != IVAS_CPE_DFT ) { - assert( L_MEM_RECALC_TBE_NS <= L_MEM_RECALC_NS ); - i = NS2SA( sts[0]->input_Fs, L_MEM_RECALC_TBE_NS ); - mvr2r( bufChanL + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[0], i ); - mvr2r( bufChanR + lMemRecalc + lMemRecalc_SCh - i, hCPE->hStereoICBWE->icbwe_inp_mem[1], i ); + /* Scale the Right channel with the gain */ + int16_t j; + int16_t l_ica_ovl = NS2SA( input_Fs, STEREO_L_TCA_OVLP_NS ); + float winSlope = 1.0f / (float) l_ica_ovl; + + tempF1 = hStereoTCA->targetGain; + tempF = hStereoTCA->prevTargetGain; + + for ( i = 0, j = 0; i < l_ica_ovl; i++, j++ ) + { + sts[1]->input[i] = ( 1.0f - j * winSlope ) * tempF * sts[1]->input[i] + ( j * winSlope ) * tempF1 * sts[1]->input[i]; + } + for ( ; i < input_frame; i++ ) + { + sts[1]->input[i] *= tempF1; + } } - return; -} + /* update L/R DS memories */ + mvr2r( bufChanL_DS + L_FRAME_DS, hStereoTCA->memChanL_DS, ADDED_MEM_DS ); + mvr2r( bufChanR_DS + L_FRAME_DS, hStereoTCA->memChanR_DS, ADDED_MEM_DS ); -/*--------------------------------------------------------------- - * stereo_tca_enc() - * - * Stereo temporal inter-channel adjustment/allocation processing module; - * Downmix, convert L/R to M/S. - * ---------------------------------------------------------------*/ + /* save the reference channel index for next frame */ + hStereoTCA->prevRefChanIndx = hStereoTCA->refChanIndx; + /* save the corr lag stats for next frame */ + mvs2s( hStereoTCA->corrLagStats, hStereoTCA->prevCorrLagStats, 3 ); + + /* save the target gain for next frame */ + hStereoTCA->prevTargetGain = hStereoTCA->targetGain; + + return; +} +#else void stereo_tca_enc( CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ const int16_t input_frame /* i : length of a frame per channel */ @@ -1251,7 +2677,6 @@ void stereo_tca_enc( float bufChanR[L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH + L_FRAME48k + L_NCSHIFTMAX]; float input_mem_loc[2][NS2SA( 48000, L_MEM_RECALC_NS + L_MEM_RECALC_SCH_NS )]; float *ptrChanL, *ptrChanR; - /* Buffers at internal sampling rate, i.e., CORR_INTER_FS */ float bufChanL_DS[L_FRAME_DS + ADDED_MEM_DS]; float bufChanR_DS[L_FRAME_DS + ADDED_MEM_DS]; @@ -1292,7 +2717,6 @@ void stereo_tca_enc( /* pointers to the current frame */ ptrChanL = bufChanL + lMemRecalc + lMemRecalc_SCh; ptrChanR = bufChanR + lMemRecalc + lMemRecalc_SCh; - /* copy interleaved stereo data to two channels, e.g., L, R */ mvr2r( sts[0]->input, ptrChanL, input_frame ); mvr2r( sts[1]->input, ptrChanR, input_frame ); @@ -1367,17 +2791,17 @@ void stereo_tca_enc( /* pointers to the current frame of DS */ ptrChanL_DS = bufChanL_DS + ADDED_MEM_DS; ptrChanR_DS = bufChanR_DS + ADDED_MEM_DS; - /* resample factor */ dsFactor = (int16_t) ( input_Fs / CORR_INTER_FS ); /* resample the stereo channels */ - deEmphResample( hStereoTCA, ptrChanL, ptrChanR, ptrChanL_DS, ptrChanR_DS, input_frame, dsFactor ); + deEmphResample( hStereoTCA, ptrChanL, ptrChanR, ptrChanL_DS, ptrChanR_DS, input_frame, dsFactor ); + /**********************NEED to Allign first 40 index in each channel ************************************/ /* inter-channel corrStats estimation */ - corrStatsEst( hStereoTCA, bufChanL_DS + ADDED_MEM_DS, bufChanR_DS + ADDED_MEM_DS, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); + corrStatsEst( hStereoTCA, bufChanL_DS + ADDED_MEM_DS, bufChanR_DS + ADDED_MEM_DS, ( L_FRAME_DS + L_XCORRMEM_DS ), dsFactor, hCPE->hCoreCoder[0]->vad_flag, hCPE->hCoreCoder[1]->vad_flag, hCPE->hStereoClassif ); /*-----------------------------------------------------------------* * refine the ICA stats *-----------------------------------------------------------------*/ @@ -1520,7 +2944,6 @@ void stereo_tca_enc( tempS = min( max( tempS, prevNCShift - currentNCShift + L_shift_adapt - input_frame ), prevNCShift - currentNCShift + lMemRecalc ); adjustTargetSignal( ( target - tempS ), prevNCShift, currentNCShift, L_shift_adapt, 1 ); } - if ( target_idx == L_CH_INDX ) { mvr2r( target - tempS, &( input_mem_loc[target_idx][lMemRecalc + lMemRecalc_SCh - tempS - currentNCShift] ), currentNCShift + tempS ); @@ -1578,10 +3001,9 @@ void stereo_tca_enc( /* Temporal channel adjustment of the LA samples based on the NC shift */ tcaTargetCh_LA( hStereoTCA, ptrChanL, ptrChanR, currentNCShift, input_frame ); } - /* Update of changed samples corresponding to the memory */ - icaMemUpdate( sts, hCPE, input_mem_loc[0], input_mem_loc[1], lMemRecalc, lMemRecalc_SCh, input_frame ); + icaMemUpdate( sts, hCPE, input_mem_loc[0], input_mem_loc[1], lMemRecalc, lMemRecalc_SCh, input_frame ); /* populate the st->input target buffer */ if ( hCPE->hStereoTD->prev_fr_LRTD_TD_dec == 0 || prev_ICA_flag == 1 ) { @@ -1623,7 +3045,7 @@ void stereo_tca_enc( return; } - +#endif /*-------------------------------------------------------------------* * stereo_tca_init_enc() * @@ -1654,22 +3076,29 @@ void stereo_tca_init_enc( set_f( hStereoTCA->memChanR, 0.0f, L_MEM_RECALC_48K + L_MEM_RECALC_48k_SCH ); set_f( hStereoTCA->memChanL_DS, 0.0f, ADDED_MEM_DS ); set_f( hStereoTCA->memChanR_DS, 0.0f, ADDED_MEM_DS ); + set_f( hStereoTCA->memdecim, 0.0f, 12 ); +#ifndef IVAS_FLOAT_FIXED hStereoTCA->mem_tempF = 0.; set_f( hStereoTCA->corrEstPrev[0], 0.0f, 2 * L_NCSHIFT_DS + 1 ); set_f( hStereoTCA->corrEstPrev[1], 0.0f, 2 * L_NCSHIFT_DS + 1 ); set_f( hStereoTCA->corrEstPrev[2], 0.0f, 2 * L_NCSHIFT_DS + 1 ); - set_f( hStereoTCA->corrEstLT, 0.0f, 2 * L_NCSHIFT_DS + 1 ); - set_f( hStereoTCA->memdecim, 0.0f, 12 ); hStereoTCA->ica_envVarLT = 2000.0f; - set_f( hStereoTCA->C_mem, 0.0f, 2 * L_NCSHIFT_DS + 1 ); hStereoTCA->E1_mem = 0.0f; hStereoTCA->E2_mem = 0.0f; set_f( hStereoTCA->delay_0_mem, 0.0f, MAX_DELAYREGLEN ); hStereoTCA->smooth_dist_reg_prv_corr = 1.0f; +#endif hStereoTCA->LRTD_G_ATT_cnt = 1; - + set32_fx( hStereoTCA->C_mem_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + set16_fx( hStereoTCA->C_mem_exp, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + hStereoTCA->E1_mem_fx = 0; + move32(); + hStereoTCA->E2_mem_fx = 0; + move32(); + hStereoTCA->E1_E2_mem_exp = 0; + move16(); return; } @@ -1683,11 +3112,11 @@ void stereo_tca_init_enc_fx( hStereoTCA->lMemRecalc = NS2SA_FX2( input_Fs, L_MEM_RECALC_NS ); move16(); div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_12k8 ), input_Fs, &div_e ); - hStereoTCA->lMemRecalc_12k8 = shr( div1, sub( 15, div_e ) ); + hStereoTCA->lMemRecalc_12k8 = shr( div1, 1 + sub( 15, div_e ) ); move16(); div1 = BASOP_Util_Divide3232_Scale( L_mult( hStereoTCA->lMemRecalc, INT_FS_16k ), input_Fs, &div_e ); - hStereoTCA->lMemRecalc_16k = shr( div1, sub( 15, div_e ) ); + hStereoTCA->lMemRecalc_16k = shr( div1, 1 + sub( 15, div_e ) ); move16(); hStereoTCA->refChanIndx = L_CH_INDX; @@ -1714,22 +3143,35 @@ void stereo_tca_init_enc_fx( set32_fx( hStereoTCA->memChanR_DS_fx, 0, ADDED_MEM_DS ); hStereoTCA->mem_tempF_fx = 0; move32(); + hStereoTCA->mem_tempF_exp = 0; + move16(); set32_fx( hStereoTCA->corrEstPrev_fx[0], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->corrEstPrev_fx[1], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); set32_fx( hStereoTCA->corrEstPrev_fx[2], 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); - + hStereoTCA->corrEstPrev_exp = 0; + move16(); set32_fx( hStereoTCA->corrEstLT_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + hStereoTCA->corrEstLT_exp = 0; + move16(); set32_fx( hStereoTCA->memdecim_fx, 0, 12 ); hStereoTCA->ica_envVarLT_fx = 2097152000; // 2000 in Q20 move32(); + hStereoTCA->ica_envVarLT_exp = 11; // 2000 in Q20 + move16(); set32_fx( hStereoTCA->C_mem_fx, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); + set16_fx( hStereoTCA->C_mem_exp, 0, add( shl( L_NCSHIFT_DS, 1 ), 1 ) ); hStereoTCA->E1_mem_fx = 0; - hStereoTCA->E2_mem_fx = 0; move32(); + hStereoTCA->E2_mem_fx = 0; move32(); + hStereoTCA->E1_E2_mem_exp = 0; + move16(); set32_fx( hStereoTCA->delay_0_mem_fx, 0, MAX_DELAYREGLEN ); - hStereoTCA->smooth_dist_reg_prv_corr_fx = MAX16B; // Q15 + hStereoTCA->delay_0_mem_exp = 0; + move16(); + hStereoTCA->smooth_dist_reg_prv_corr_fx = MAX_32; // Q15 + hStereoTCA->smooth_dist_reg_prv_corr_exp = 0; // Q15 hStereoTCA->LRTD_G_ATT_cnt = 1; move16(); move16(); @@ -1740,7 +3182,219 @@ void stereo_tca_init_enc_fx( * Function unclr_calc_corr_features() * *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +static void unclr_calc_corr_features_fx( + STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ + STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ + Word32 buf1[], /* i : left channel q_com*/ + Word32 buf2[], /* i : right channel q_com*/ + Word16 q_com, + const Word16 length, /* i : length of input signal buffers */ + Word32 corrEst[], /* i : buffer containing inter-channel correlation values corrEst_exp*/ + Word16 corrEst_exp, + const Word16 lagSearchRange[], /* i : minimum and maximum lags for corrEst[] */ + Word32 *corrEst_ncorr, /* o : norm. x-correlation btw. current and previous correlation buffers corrEst_ncorr_exp*/ + Word16 *corrEst_ncorr_exp ) +{ + Word16 i, corrLagMax, d_corrLagMax, tempLen, k; + Word32 num, den; + Word32 corrL, corrR, ener, ener_side, mono_i, side_i, ic_Lm, ic_Rm, tdm_es_em, m_corrL_corrR, d_corrL_corrR; + Word32 sum_prod, corrEstMax; + Word16 corrL_exp, corrR_exp, ener_exp, ener_side_exp, sum_prod_exp, exp, exp1, exp2, num_exp, den_exp; + + corrL = ONE_IN_Q31; + move32(); + corrL_exp = 0; + move16(); + corrR = ONE_IN_Q31; + move32(); + corrR_exp = 0; + move16(); + ener = ONE_IN_Q31; + move32(); + ener_exp = 0; + move16(); + ener_side = ONE_IN_Q31; + move32(); + ener_side_exp = 0; + move16(); + sum_prod = 0; + move32(); + sum_prod_exp = 0; + move16(); + + FOR( i = 0; i < length; i++ ) + { + mono_i = BASOP_Util_Add_Mant32Exp( L_shr( buf1[i], 1 ), sub( 31, q_com ), L_shr( buf2[i], 1 ), sub( 31, q_com ), &exp ); + corrL = BASOP_Util_Add_Mant32Exp( corrL, corrL_exp, Mpy_32_32( buf1[i], mono_i ), add( sub( 31, q_com ), exp ), &corrL_exp ); + corrR = BASOP_Util_Add_Mant32Exp( corrR, corrR_exp, Mpy_32_32( buf2[i], mono_i ), add( sub( 31, q_com ), exp ), &corrR_exp ); + ener = BASOP_Util_Add_Mant32Exp( ener, ener_exp, Mpy_32_32( mono_i, mono_i ), shl( exp, 1 ), &ener_exp ); + + side_i = BASOP_Util_Add_Mant32Exp( L_shr( buf1[i], 1 ), sub( 31, q_com ), L_negate( L_shr( buf2[i], 1 ) ), sub( 31, q_com ), &exp ); + ener_side = BASOP_Util_Add_Mant32Exp( ener_side, ener_side_exp, Mpy_32_32( side_i, side_i ), shl( exp, 1 ), &ener_side_exp ); + sum_prod = BASOP_Util_Add_Mant32Exp( sum_prod, sum_prod_exp, Mpy_32_32( buf1[i], buf2[i] ), sub( 62, shl( q_com, 1 ) ), &sum_prod_exp ); + } + + /* average energy of L and R channels */ + hStereoClassif->ave_ener_L_fx = Mpy_32_32( hStereoTCA->E1_mem_fx, 13421772 /* 1/length in Q31*/ ); + move32(); + hStereoClassif->ave_ener_L_fx_e = hStereoTCA->E1_E2_mem_exp; + move16(); + hStereoClassif->ave_ener_R_fx = Mpy_32_32( hStereoTCA->E2_mem_fx, 13421772 /* 1/length in Q31*/ ); + move32(); + hStereoClassif->ave_ener_R_fx_e = hStereoTCA->E1_E2_mem_exp; + move16(); + + /* unnormalized L/R correlation */ + IF( sum_prod ) + { + sum_prod = BASOP_Util_Log10( L_abs( sum_prod ), sum_prod_exp ); + sum_prod_exp = 6; + move16(); + } + ELSE + { + sum_prod = 0; + move32(); + sum_prod_exp = 0; + move16(); + } + + hStereoClassif->unclr_fv_fx[E_sum_prod] = L_shr( sum_prod, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_sum_prod] = L_shr( sum_prod, 10 ); // Q15 + move32(); + /* S/M energy ratio */ + Word32 inp1 = Sqrt32( Mpy_32_32( ener_side, 13421773 /* 1/L_FRAME_DS in Q31*/ ), &ener_side_exp ); + inp1 = BASOP_Util_Log10( inp1, ener_side_exp ); + Word16 temp = ener_exp; + move16(); + Word32 inp2 = Sqrt32( Mpy_32_32( ener, 13421773 /* 1/L_FRAME_DS in Q31*/ ), &ener_exp ); + inp2 = BASOP_Util_Log10( inp2, ener_exp ); + ener_exp = temp; + move16(); + + tdm_es_em = L_abs( Mpy_32_32( L_sub( inp1, inp2 ), 1342177280 ) ); /* Q25 + Q27 - Q31 = 21*/ + + hStereoClassif->unclr_fv_fx[E_tdm_es_em] = L_shr( tdm_es_em, 6 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_tdm_es_em] = L_shr( tdm_es_em, 6 ); // Q15 + move32(); + + /* L/R correlation values (zero lag, maximum) */ + corrLagMax = maximum_l( corrEst, sub( lagSearchRange[1], add( lagSearchRange[0], 1 ) ), &corrEstMax ); + d_corrLagMax = sub( corrLagMax, hStereoClassif->unclr_corrLagMax_prev ); + + hStereoClassif->unclr_fv_fx[E_d_corrLagMax] = L_shl( d_corrLagMax, 15 ); + move32(); + hStereoClassif->unclr_corrLagMax_prev = corrLagMax; + move32(); + hStereoClassif->xtalk_fv_fx[E_d_corrLagMax] = L_shl( d_corrLagMax, 15 ); + move32(); + + if ( corrEstMax < 0 ) + { + corrEstMax = 0; + move32(); + } + + hStereoClassif->unclr_fv_fx[E_corrEst0] = L_shl( corrEst[abs_s( lagSearchRange[0] )], sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->unclr_fv_fx[E_corrEstMax] = L_shl( corrEstMax, sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->unclr_fv_fx[E_corrLagMax] = L_shl( corrLagMax, 15 ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrEst0] = L_shl( corrEst[abs_s( lagSearchRange[0] )], sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrEstMax] = L_shl( corrEstMax, sub( corrEst_exp, 16 ) ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrLagMax] = L_shl( corrLagMax, 15 ); + move32(); + + /* L/M and R/M correlation */ + if ( corrL < 0 ) + { + corrL = 0; + move32(); + } + + if ( corrR < 0 ) + { + corrR = 0; + move32(); + } + + ic_Lm = BASOP_Util_Divide3232_Scale_cadence( corrL, ener, &exp1 ); + exp1 = add( exp1, sub( corrL_exp, ener_exp ) ); + ic_Rm = BASOP_Util_Divide3232_Scale_cadence( corrR, ener, &exp2 ); + exp2 = add( exp2, sub( corrR_exp, ener_exp ) ); + + m_corrL_corrR = L_sub( L_max( L_abs( L_shl( ic_Lm, sub( exp1, s_max( exp1, exp2 ) ) ) ), L_abs( L_shl( ic_Rm, sub( exp2, s_max( exp1, exp2 ) ) ) ) ), L_min( L_abs( L_shl( ic_Lm, sub( exp1, s_max( exp1, exp2 ) ) ) ), L_abs( L_shl( ic_Rm, sub( exp2, s_max( exp1, exp2 ) ) ) ) ) ); // s_max(exp1, exp2) + + inp1 = BASOP_Util_Add_Mant32Exp( corrL, corrL_exp, corrR, corrR_exp, &exp ); + IF( inp1 ) + { + d_corrL_corrR = BASOP_Util_Log10( L_abs( inp1 ), exp ); // Q25 + } + ELSE + { + d_corrL_corrR = 0; + move32(); + } + + hStereoClassif->unclr_fv_fx[E_m_corrL_corrR] = L_shl( m_corrL_corrR, sub( s_max( exp1, exp2 ), 16 ) ); // Q15 + move32(); + hStereoClassif->unclr_fv_fx[E_d_corrL_corrR] = L_shr( d_corrL_corrR, 10 ); // Q15 + move32(); + hStereoClassif->xtalk_fv_fx[E_m_corrL_corrR] = L_shl( m_corrL_corrR, sub( s_max( exp1, exp2 ), 16 ) ); // Q15 + move32(); + + /* norm. x-correlation btw. current and previous correlation buffers */ + tempLen = ( 2 * L_NCSHIFT_DS + 1 ); + + Word64 L64_sum = 0; + move64(); + FOR( k = 0; k < tempLen; k++ ) + { + L64_sum = W_mac_32_32( L64_sum, corrEst[k], hStereoTCA->corrEstPrev_fx[2][k] ); + } + k = W_norm( L64_sum ); + L64_sum = W_shl( L64_sum, k ); + num = W_extract_h( L64_sum ); // ener_side_q + num_exp = sub( 31, sub( add( add( add( sub( 31, corrEst_exp ), sub( 31, hStereoTCA->corrEstPrev_exp ) ), 1 ), k ), 32 ) ); + + exp1 = corrEst_exp; + move16(); + inp1 = sum2_32_exp_fx( corrEst, tempLen, &exp1, 3 ); + + exp2 = hStereoTCA->corrEstPrev_exp; + move16(); + inp2 = sum2_32_exp_fx( hStereoTCA->corrEstPrev_fx[2], tempLen, &exp2, 3 ); + den_exp = add( exp1, exp2 ); + den = Sqrt32( Mpy_32_32( inp1, inp2 ), &den_exp ); + + IF( den == 0 ) + { + *corrEst_ncorr = 0; + move16(); + *corrEst_ncorr_exp = 0; + move32(); + } + ELSE + { + *corrEst_ncorr = BASOP_Util_Divide3232_Scale_cadence( num, den, &exp ); + *corrEst_ncorr_exp = add( exp, sub( num_exp, den_exp ) ); + } + + hStereoClassif->unclr_fv_fx[E_corrEst_ncorr] = L_shl( *corrEst_ncorr, sub( *corrEst_ncorr_exp, 16 ) ); + move32(); + hStereoClassif->xtalk_fv_fx[E_corrEst_ncorr] = L_shl( *corrEst_ncorr, sub( *corrEst_ncorr_exp, 16 ) ); + move32(); + + return; +} +#else static void unclr_calc_corr_features( STEREO_CLASSIF_HANDLE hStereoClassif, /* i/o: stereo classifier handle */ STEREO_TCA_ENC_HANDLE hStereoTCA, /* i/o: ICA Stereo Encoder handle */ @@ -1839,3 +3493,4 @@ static void unclr_calc_corr_features( return; } +#endif diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 2eccc298d..8b9d4e4d5 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -1318,7 +1318,148 @@ void stereo_mdct_core_enc( { st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[ch][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[ch][n], orig_spectrum_fx[ch][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + q_powerSpec = L_get_q_buf1( &powerSpec[ch][n * L_subframeTCX], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( &powerSpec[ch][n * L_subframeTCX], &powerSpec_fx[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + floatToFixed_arr16( &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold_flt[0][0], &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + fixedToFloat_arrL32( &powerSpec_fx[ch][n * L_subframeTCX], &powerSpec[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + 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, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - 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, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#endif } } } @@ -1340,7 +1481,148 @@ void stereo_mdct_core_enc( { for ( n = 0; n < nSubframes; n++ ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + 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 ); + } + } + + int igfGridIdx; + if ( st->last_core == ACELP_CORE && st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_TRAN; + } + else if ( st->core == TCX_20_CORE ) + { + igfGridIdx = IGF_GRID_LB_NORM; + } + else + { + /* It is short block */ + igfGridIdx = IGF_GRID_LB_SHORT; + } + + L_subframeTCX = st->hTcxEnc->L_frameTCX / nSubframes; + Word16 q_spectrum; + q_spectrum = L_get_q_buf1( orig_spectrum[ch][n], hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + q_spectrum = min( q_spectrum, L_get_q_buf1( st->hIGFEnc->spec_be_igf_flt, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ) ); + } + floatToFixed_arrL32( orig_spectrum[ch][n], orig_spectrum_fx[ch][n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine ); + if ( st->hIGFEnc ) + { + floatToFixed_arrL32( st->hIGFEnc->spec_be_igf_flt, st->hIGFEnc->spec_be_igf, q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - IGF_START_MN ); + st->hIGFEnc->spec_be_igf_e = 31 - q_spectrum; + } + + q_spectrum = L_get_q_buf1( st->hTcxEnc->spectrum[n], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( st->hTcxEnc->spectrum[n], st->hTcxEnc->spectrum_fx[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + q_powerSpec = L_get_q_buf1( &powerSpec[ch][n * L_subframeTCX], hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + floatToFixed_arrL32( &powerSpec[ch][n * L_subframeTCX], &powerSpec_fx[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + st->hIGFEnc->tns_predictionGain = float_to_fix16( st->hIGFEnc->tns_predictionGain_flt, Q23 ); + } + floatToFixed_arr16( &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold_flt[0][0], &hPrivateData->igfInfo.grid[igfGridIdx].whiteningThreshold[0][0], Q13, 2 * IGF_MAX_TILES ); +#endif + ProcessIGF_ivas_fx( st, st->hTcxEnc->spectrum_fx[n], orig_spectrum_fx[ch][n], &q_spectrum, &powerSpec_fx[ch][n * L_subframeTCX], &q_powerSpec, st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL32( st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum[n], q_spectrum, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + fixedToFloat_arrL32( &powerSpec_fx[ch][n * L_subframeTCX], &powerSpec[ch][n * L_subframeTCX], q_powerSpec, hPrivateData->igfInfo.grid[igfGridIdx].infoGranuleLen ); + + if ( st->hIGFEnc ) + { + 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, hPrivateData->igfInfo.grid[igfGridIdx].stopLine - 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, st->hTcxEnc->spectrum[n], orig_spectrum[ch][n], &powerSpec[ch][n * L_subframeTCX], st->core == TCX_20_CORE, n, hCPE->hCoreCoder[0]->sp_aud_decision0, 0 ); +#endif } } } diff --git a/lib_enc/ivas_stereo_td_analysis.c b/lib_enc/ivas_stereo_td_analysis.c index 299f5e837..8a3be7590 100644 --- a/lib_enc/ivas_stereo_td_analysis.c +++ b/lib_enc/ivas_stereo_td_analysis.c @@ -2448,7 +2448,7 @@ int16_t tdm_lp_comparison( return LP_mode; } - +#ifndef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* * tdm_ol_pitch_comparison() * @@ -2528,7 +2528,108 @@ void tdm_ol_pitch_comparison( return; } +#else +/*-------------------------------------------------------------------* + * tdm_ol_pitch_comparison() + * + * Perform the comparison of the 2 sets of OL pitch + *-------------------------------------------------------------------*/ +/*! r: replication decision; 1 = Use old LP */ +void tdm_ol_pitch_comparison_fx( + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + Word16 pitch_fr[CPE_CHANNELS][NB_SUBFR], /* i/o: fractional pitch values, Q6 */ + Word16 voicing_fr[CPE_CHANNELS][NB_SUBFR] /* i/o: fractional pitch gains, Q15 */ +) +{ + Word16 tmp_diff; + Word16 diff_thr = 6; + Encoder_State *st0, *st1; + move16(); + + st0 = hCPE->hCoreCoder[0]; /* Encoder structure - primary channel */ + st1 = hCPE->hCoreCoder[1]; /* Encoder structure - secondary channel */ + + if ( GT_32( hCPE->element_brate, IVAS_13k2 ) ) + { + diff_thr = 3; + move16(); + } + + test(); + if ( GE_32( hCPE->element_brate, IVAS_48k ) || EQ_16( hCPE->hStereoTD->tdm_LRTD_flag, 1 ) ) + { + diff_thr = 1; + move16(); + } + + hCPE->hStereoTD->tdm_Pitch_reuse_flag = 0; + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( st0->sp_aud_decision1 == 0 && st0->sp_aud_decision2 == 0 ) && /* Pitch is not recycled in case of music coding*/ + ( LE_32( hCPE->element_brate, IVAS_16k4 ) || ( LE_32( hCPE->element_brate, IVAS_24k4 ) && EQ_16( st0->coder_type, VOICED ) && EQ_16( st1->coder_type, VOICED ) ) ) ) || + LT_32( hCPE->element_brate, IVAS_13k2 ) ) + { + IF( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + Word16 voicmin[4]; + + minimum_fx( st0->voicing_fx, 3, voicmin ); + minimum_fx( st1->voicing_fx, 3, voicmin + 1 ); + minimum_fx( voicing_fr[0], 4, voicmin + 2 ); + minimum_fx( voicing_fr[1], 4, voicmin + 3 ); + + tmp_diff = 10; + move16(); + + test(); + test(); + test(); + IF( GE_16( voicmin[0], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[1], 29491 /* 0.9f in Q15 */ ) && GE_16( voicmin[2], 27853 /* 0.85f in Q15 */ ) && GE_16( voicmin[3], 27853 /* 0.85f in Q15 */ ) ) + { + tmp_diff = add( abs_s( sub( st0->pitch[0], st1->pitch[0] ) ), add( abs_s( sub( st0->pitch[1], st1->pitch[1] ) ), abs_s( sub( st0->pitch[2], st1->pitch[2] ) ) ) ); + } + } + ELSE + { + tmp_diff = abs_s( sub( add( st0->pitch[0], add( st0->pitch[1], st0->pitch[2] ) ), add( st1->pitch[0], add( st1->pitch[1], st1->pitch[2] ) ) ) ); + } + + IF( LE_16( tmp_diff, diff_thr ) ) + { + hCPE->hStereoTD->tdm_Pitch_reuse_flag = 1; + move16(); + + /* 1/4 pitch precision update*/ + Copy( st0->pitch, st1->pitch, 3 ); + Copy( st0->voicing_fx, st1->voicing_fx, 3 ); + + /* Update some parameters accordingly */ + st1->old_corr_fx = st0->old_corr_fx; + st1->old_thres_fx = st0->old_thres_fx; + st1->delta_pit = st0->delta_pit; + move16(); + move16(); + move16(); + + /* Updates for adaptive lag window memory */ + st1->old_pitch_la = st0->old_pitch_la; + move16(); + /* 1/4 pitch precision update*/ + Copy( pitch_fr[0], pitch_fr[1], NB_SUBFR ); + Copy( voicing_fr[0], voicing_fr[1], NB_SUBFR ); + } + } + + return; +} +#endif #ifdef IVAS_FLOAT_FIXED /*-------------------------------------------------------------------* diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index b1ba9d559..22f387acd 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -44,6 +44,7 @@ #endif #ifdef IVAS_FLOAT_FIXED #include "prot_fx_enc.h" +#include "ivas_prot_fx.h" #endif @@ -392,7 +393,353 @@ ivas_error stereo_set_tdm( * * Configure TD stereo encoder *-------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void tdm_configure_enc_fx( + const Word16 ivas_format, /* i : IVAS format */ + const Word16 ism_mode, /* i : ISM mode in combined format */ + CPE_ENC_HANDLE hCPE, /* i : CPE encoder structure */ + const Word16 Etot_last_fx[CPE_CHANNELS], /* i/o: Energy of last frame Q8*/ + const Word16 tdm_SM_or_LRTD_Pri, /* i : channel combination scheme flag in TD stereo OR LRTD primary channel */ + const Word16 tdm_ratio_idx, /* i : ratio index */ + const Word16 tdm_ratio_idx_SM, /* i : ratio index in SM mode */ + const Word16 attack_flag, /* i : Primary channel attack flag */ + const Word16 nb_bits_metadata /* i : number of metadata bits */ +) +{ + Word16 tdm_ratio_bit_alloc_idx, mod_ct; + STEREO_TD_ENC_DATA_HANDLE hStereoTD; + Encoder_State **sts; + Word16 loc_coder_tyape_raw0; + hStereoTD = hCPE->hStereoTD; + sts = hCPE->hCoreCoder; + loc_coder_tyape_raw0 = sts[0]->coder_type_raw; + move16(); + + /*----------------------------------------------------------------* + * Overwrite certain decisions depending on the input + *----------------------------------------------------------------*/ + + hStereoTD->tdm_use_IAWB_Ave_lpc = 0; /* Flag initialisation */ + move16(); + sts[0]->hSpMusClas->tdm_lt_Etot_fx = add( mult( 3277 /*0.1f in Q15*/, Etot_last_fx[0] ), mult( 29491 /* 0.9f*/, sts[0]->hSpMusClas->tdm_lt_Etot_fx ) ); + move16(); + sts[1]->hSpMusClas->tdm_lt_Etot_fx = add( mult( 3277 /*0.1f in Q15*/, Etot_last_fx[1] ), mult( 29491 /* 0.9f*/, sts[1]->hSpMusClas->tdm_lt_Etot_fx ) ); + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( hCPE->hStereoClassif->lrtd_mode == 0 && ( ( sts[1]->hSpMusClas->tdm_lt_Etot < 0 && hCPE->hCoreCoder[1]->vad_flag == 0 ) /* very clean signal */ + || ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( LT_16( Etot_last_fx[1], 7680 /*30.0f*/ ) && GT_16( sub( sts[0]->hSpMusClas->tdm_lt_Etot_fx, sts[1]->hSpMusClas->tdm_lt_Etot_fx ), 6656 /*26.0f*/ ) ) ) ) ) + { + sts[1]->coder_type = INACTIVE; + move16(); + + test(); + if ( hStereoTD->tdm_lp_reuse_flag == 0 && hCPE->hCoreCoder[0]->vad_flag != 0 ) + { + hStereoTD->tdm_use_IAWB_Ave_lpc = 1; + move16(); + } + hStereoTD->tdm_lp_reuse_flag = 1; + move16(); + } + ELSE IF( ( ( hCPE->hCoreCoder[1]->vad_flag == 0 ) || ( hCPE->hCoreCoder[0]->vad_flag == 0 && LT_16( Etot_last_fx[1], 7680 /*30.0f*/ ) && GT_16( sub( sts[0]->hSpMusClas->tdm_lt_Etot_fx, sts[1]->hSpMusClas->tdm_lt_Etot_fx ), 6656 /*26.0f*/ ) ) ) && ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) /* && NO_DTX */ ) /* boths channels are inactive but not DTX used*/ + { + sts[1]->coder_type = INACTIVE; + move16(); + IF( GT_16( tdm_ratio_idx, 1 ) && LT_16( tdm_ratio_idx, 29 ) ) + { + if ( hStereoTD->tdm_lp_reuse_flag == 0 && hCPE->hCoreCoder[0]->vad_flag != 0 ) + { + hStereoTD->tdm_use_IAWB_Ave_lpc = 1; + move16(); + } + hStereoTD->tdm_lp_reuse_flag = 1; + move16(); + } + } + ELSE IF( !( sts[1]->sp_aud_decision0 ) && sts[1]->tc_cnt <= 0 && ( EQ_16( sts[1]->coder_type_raw, UNVOICED ) || ( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && hStereoTD->tdm_lp_reuse_flag == 0 && ( hCPE->hCoreCoder[1]->vad_flag == 0 || ( LT_16( Etot_last_fx[1], 7680 /*30.0f*/ ) && GT_16( sub( sts[0]->hSpMusClas->tdm_lt_Etot_fx, sts[1]->hSpMusClas->tdm_lt_Etot_fx ), 6656 /*26.0f*/ ) ) ) ) ) ) + { + sts[1]->coder_type = UNVOICED; + move16(); + if ( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) + { + hStereoTD->tdm_lp_reuse_flag = 0; + move16(); + } + } + ELSE IF( ( LT_16( sts[1]->coder_type, AUDIO ) && NE_16( sts[1]->coder_type, UNVOICED ) ) || /* TC and VC are not supported in secondary channel */ + ( ( EQ_16( sts[1]->coder_type, AUDIO ) && LE_32( hCPE->element_brate, IVAS_24k4 ) ) || ( EQ_16( sts[0]->sp_aud_decision1, 1 ) && GE_32( hCPE->element_brate, IVAS_16k4 ) ) || ( EQ_16( sts[1]->sp_aud_decision0, 1 ) && GE_32( hCPE->element_brate, IVAS_13k2 ) ) ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + ELSE IF( EQ_16( sts[1]->coder_type, GENERIC ) && EQ_16( sts[1]->coder_type_raw, UNVOICED ) ) + { + hStereoTD->tdm_lp_reuse_flag = 0; + move16(); + } + + test(); + IF( GE_32( hCPE->element_brate, IVAS_24k4 ) && EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) ) + { + if ( EQ_16( sts[1]->coder_type, UNVOICED ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + + IF( EQ_16( sts[0]->coder_type, UNVOICED ) ) + { + sts[0]->coder_type = GENERIC; + move16(); + loc_coder_tyape_raw0 = GENERIC; + move16(); + } + } + test(); + test(); + IF( GE_32( hCPE->element_brate, IVAS_24k4 ) && hCPE->hStereoClassif->lrtd_mode == 0 && EQ_16( sts[0]->coder_type, UNVOICED ) ) + { + sts[0]->coder_type = GENERIC; + move16(); + loc_coder_tyape_raw0 = GENERIC; + move16(); + } + + if ( NE_16( sts[1]->coder_type, GENERIC ) ) + { + hStereoTD->tdm_Pitch_reuse_flag = 0; + move16(); + } + + IF( attack_flag != 0 ) + { + if ( sts[1]->coder_type != INACTIVE ) + { + hStereoTD->tdm_lp_reuse_flag = 0; /* Do not allow the LP filter reusing on TC or attack in the primary channel */ + move16(); + } + } + test(); + IF( tdm_SM_or_LRTD_Pri && hStereoTD->tdm_LRTD_flag == 0 ) + { + tdm_ratio_bit_alloc_idx = tdm_ratio_idx_SM; + move16(); + } + ELSE + { + tdm_ratio_bit_alloc_idx = tdm_ratio_idx; + move16(); + } + test(); + test(); + test(); + test(); + if ( ( EQ_16( hCPE->hStereoClassif->lrtd_mode, 1 ) && GE_16( sts[1]->coder_type, UNVOICED ) && GT_16( abs_s( sub( hStereoTD->tdm_last_ratio_idx, tdm_ratio_bit_alloc_idx ) ), 15 ) ) /* channel inversion in lrtd */ + || ( LT_16( hStereoTD->tdm_FD2LRTD_SW_cnt, 4 ) && LT_16( hStereoTD->tdm_last_LRTD_frame_cnt, 4 ) ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + + IF( LT_32( L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), 12000 ) ) + { + if ( EQ_16( sts[1]->coder_type, UNVOICED ) ) + { + sts[1]->coder_type = GENERIC; + move16(); + } + hStereoTD->tdm_lp_reuse_flag = 1; + move16(); + + if ( LT_32( L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), 11000 ) ) + { + sts[1]->coder_type = INACTIVE; + move16(); + } + } + + IF( LT_32( L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), 14700 ) ) + { + if ( EQ_16( sts[0]->coder_type, TRANSITION ) ) + { + sts[0]->coder_type = GENERIC; + move16(); + } + } + + mod_ct = AUDIO; + move16(); + IF( LT_32( hCPE->element_brate, IVAS_24k4 ) ) + { + mod_ct = sts[0]->coder_type; + move16(); + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + /* Only sure TRANSITION coding modes are important for bit allocation, otherwise mod_ct is set to AUDIO only to easy debugging if needed */ + IF( ( ( GE_16( sts[0]->last_L_frame, L_FRAME16k ) && EQ_16( sts[0]->flag_ACELP16k, 0 ) ) || ( EQ_16( sts[0]->last_L_frame, L_FRAME ) && EQ_16( sts[0]->flag_ACELP16k, 1 ) ) ) && NE_32( sts[0]->last_core_brate, FRAME_NO_DATA ) && NE_32( sts[0]->last_core_brate, SID_2k40 ) && NE_32( sts[0]->coder_type_raw, VOICED ) /*in case of CNG, this code is not reached sts[0]->core_brate != FRAME_NO_DATA && sts[0]->core_brate != SID_2k40 &&*/ ) + { + mod_ct = TRANSITION; + move16(); + } + ELSE IF( EQ_16( sts[0]->sp_aud_decision1, 1 ) || EQ_16( sts[0]->sp_aud_decision2, 1 ) || NE_16( mod_ct, TRANSITION ) ) + { + mod_ct = AUDIO; + move16(); + } + } + + /* Correction of tdm_inst_ratio_idx in case of TC in the seecondary channel */ + test(); + test(); + IF( hStereoTD->flag_skip_DMX == 0 && EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) && GT_16( sts[1]->tc_cnt, 1 ) /*&& abs(hStereoTD->tdm_inst_ratio_idx-LRTD_STEREO_MID_IS_PRIM) > 5*/ ) + { + IF( tdm_SM_or_LRTD_Pri == 0 ) /* Primary is right */ + { + hStereoTD->tdm_inst_ratio_idx = add( hStereoTD->tdm_inst_ratio_idx, LRTD_STEREO_QUARTER_RANGE ); + move16(); + } + ELSE IF( EQ_16( tdm_SM_or_LRTD_Pri, 1 ) ) /* Primary is left */ + { + hStereoTD->tdm_inst_ratio_idx = sub( hStereoTD->tdm_inst_ratio_idx, LRTD_STEREO_QUARTER_RANGE ); + move16(); + } + hStereoTD->tdm_inst_ratio_idx = check_bounds_s_fx( hStereoTD->tdm_inst_ratio_idx, 8, 22 ); + move16(); + } + + /*----------------------------------------------------------------* + * bitbudget distribution between channels (taking into account also metadata bitbudget) + *----------------------------------------------------------------*/ + + tdm_bit_alloc( ivas_format, ism_mode, L_sub( L_add( hCPE->element_brate, hCPE->brate_surplus ), L_mult0( nb_bits_metadata, FRAMES_PER_SEC ) ), + hStereoTD->tdm_lp_reuse_flag, &( sts[0]->total_brate ), &( sts[1]->total_brate ), + &( hStereoTD->tdm_low_rate_mode ), sts[1]->coder_type, tdm_ratio_bit_alloc_idx, hStereoTD->tdm_Pitch_reuse_flag, + sts[0]->bwidth, sts[1]->bwidth, sts[0]->flag_ACELP16k, hStereoTD->tdm_LRTD_flag, mod_ct, hStereoTD->tdm_inst_ratio_idx ); + test(); + if ( sts[0]->GSC_IVAS_mode > 0 && LE_32( sts[0]->total_brate, STEREO_GSC_BIT_RATE_ALLOC ) ) + { + sts[0]->GSC_IVAS_mode = 0; + move16(); + } + test(); + test(); + if ( sts[1]->GSC_IVAS_mode > 0 && ( LE_32( sts[1]->total_brate, STEREO_GSC_BIT_RATE_ALLOC ) || EQ_16( hStereoTD->tdm_low_rate_mode, 1 ) ) ) + { + sts[1]->GSC_IVAS_mode = 0; + move16(); + } + test(); + IF( EQ_16( sts[0]->coder_type, GENERIC ) && EQ_16( loc_coder_tyape_raw0, UNVOICED ) ) + { + if ( LT_32( sts[0]->total_brate, MAX_UNVOICED_BRATE ) ) + { + sts[0]->coder_type = UNVOICED; + move16(); + } + } + + /*----------------------------------------------------------------* + * Bitstream writing + *----------------------------------------------------------------*/ + /* transmit the ratio index */ + test(); + IF( tdm_SM_or_LRTD_Pri && hStereoTD->tdm_LRTD_flag == 0 ) + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_TD_ALPHA, tdm_ratio_idx_SM, TDM_RATIO_BITS ); + } + ELSE + { + IF( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_TD_ALPHA, hStereoTD->tdm_inst_ratio_idx, TDM_RATIO_BITS ); + } + ELSE + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_TD_ALPHA, tdm_ratio_idx, TDM_RATIO_BITS ); + } + } + + /* LPC reuse flag */ + test(); + test(); + IF( sts[1]->coder_type == INACTIVE && LT_16( tdm_ratio_idx, 29 ) && GT_16( tdm_ratio_idx, 1 ) ) + { + /* normal TD, tdm_lp_reuse_flag always on, tdm_use_IAWB_Ave_lpc varies tdm_ratio_idx<29 && tdm_ratio_idx> 1*/ + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_LPC_REUSE, hStereoTD->tdm_use_IAWB_Ave_lpc, TDM_LP_REUSE_BITS ); + } + ELSE + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_LPC_REUSE, hStereoTD->tdm_lp_reuse_flag, TDM_LP_REUSE_BITS ); + } + + /* LRTD flag */ + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_LRTD_FLAG, hStereoTD->tdm_LRTD_flag, TDM_LR_CONTENT_BITS ); + + /* Stereo ICA parameters */ + IF( hStereoTD->tdm_LRTD_flag == 0 ) + { + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_REFCHAN, hCPE->hStereoTCA->refChanIndx, STEREO_BITS_TCA_CHAN ); + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_CORRSTATS, hCPE->hStereoTCA->indx_ica_NCShift, STEREO_BITS_TCA_CORRSTATS ); + push_indice( &hStereoTD->tdm_hBstr_tmp, IND_STEREO_GD, hCPE->hStereoTCA->indx_ica_gD, STEREO_BITS_TCA_GD ); + } + + + /*----------------------------------------------------------------* + * Updates + *----------------------------------------------------------------*/ + + hStereoTD->tdm_last_ratio_idx = tdm_ratio_idx; + move16(); + hStereoTD->tdm_last_ratio_idx_SM = tdm_ratio_idx_SM; + move16(); + hStereoTD->tdm_last_SM_flag = tdm_SM_or_LRTD_Pri; + move16(); + + if ( EQ_16( hStereoTD->tdm_LRTD_flag, 1 ) ) + { + hStereoTD->tdm_last_SM_flag = 0; + move16(); + } + + hStereoTD->tdm_last_inst_ratio_idx = hStereoTD->tdm_inst_ratio_idx; + move16(); + + return; +} +#else void tdm_configure_enc( const int16_t ivas_format, /* i : IVAS format */ const int16_t ism_mode, /* i : ISM mode in combined format */ @@ -649,7 +996,7 @@ void tdm_configure_enc( return; } - +#endif /*-------------------------------------------------------------------* * signaling_enc_secondary() diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index 721241fc3..16e14a312 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -531,7 +531,10 @@ void stereo_tcx_core_enc( floatToFixed_arr( st->synth_flt, st->synth, Q_new, st->L_frame ); floatToFixed_arr( st->hLPDmem->syn_flt, st->hLPDmem->syn, Q_new, M + 1 ); - st->wspeech_enc[st->L_frame - 1] = (Word16) floatToFixed( st->wspeech_enc_flt[st->L_frame - 1], Q_new ); + if ( st->tcxonly == 0 ) + { + st->wspeech_enc[st->L_frame - 1] = (Word16) floatToFixed( st->wspeech_enc_flt[st->L_frame - 1], Q_new ); + } #endif // IVAS_FLOAT_FIXED_CONVERSIONS IF( !st->enableTcxLpc ) @@ -673,10 +676,13 @@ void stereo_tcx_core_enc( s = sub( getScaleFactor16( st->synth, st->L_frame ), 2 ); s = s_min( s, getScaleFactor16( st->hLPDmem->syn, M ) ); - s = s_min( s, norm_s( st->wspeech_enc[st->L_frame - 1] ) ); + IF( st->tcxonly == 0 ) + { + s = s_min( s, norm_s( st->wspeech_enc[st->L_frame - 1] ) ); + st->wspeech_enc[st->L_frame - 1] = shl( st->wspeech_enc[st->L_frame - 1], s ); + } Scale_sig( st->synth, st->L_frame, s ); Scale_sig( st->hLPDmem->syn, M + 1, s ); - st->wspeech_enc[st->L_frame - 1] = shl( st->wspeech_enc[st->L_frame - 1], s ); Q_new = add( Q_new, s ); move16(); move16(); diff --git a/lib_enc/nois_est.c b/lib_enc/nois_est.c index 792ecd2f0..ac674a34a 100644 --- a/lib_enc/nois_est.c +++ b/lib_enc/nois_est.c @@ -104,6 +104,10 @@ void noise_est_init( } hNoiseEst->totalNoise = 0.0f; + +#ifdef IVAS_FLOAT_FIXED + hNoiseEst->totalNoise_fx = 0; +#endif hNoiseEst->first_noise_updt = 0; hNoiseEst->first_noise_updt_cnt = 0; diff --git a/lib_enc/pre_proc.c b/lib_enc/pre_proc.c index 524956f7f..f8f232b89 100644 --- a/lib_enc/pre_proc.c +++ b/lib_enc/pre_proc.c @@ -251,8 +251,52 @@ void pre_proc( /*----------------------------------------------------------------* * FD-CNG Noise Estimator *----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->last_totalNoise_fx = float_to_fix16( st->last_totalNoise, Q8 ); + st->hNoiseEst->totalNoise_fx = float_to_fix16( st->hNoiseEst->totalNoise, Q8 ); + + FOR( Word16 n = 0; n < TOTALNOISE_HIST_SIZE; n++ ) + { + st->totalNoise_increase_hist_fx[n] = float_to_fix16( st->totalNoise_increase_hist[n], Q8 ); + move16(); + } +#endif + resetFdCngEnc_fx( st ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + + Word16 totalNoiseIncrease_fx = st->hNoiseEst->totalNoise_fx - st->last_totalNoise_fx; + st->last_totalNoise = fix16_to_float( st->last_totalNoise_fx, Q8 ); + IF( + ( totalNoiseIncrease_fx > 5 * 256 && st->totalNoise_increase_len == TOTALNOISE_HIST_SIZE && st->ini_frame > 150 ) || + ( st->input_bwidth > st->last_input_bwidth ) || + ( st->last_core == AMR_WB_CORE ) ) + { + st->hFdCngEnc->hFdCngCom->init_old_flt = fix16_to_float( st->hFdCngEnc->hFdCngCom->init_old, Q15 ); + move16(); + } + IF( totalNoiseIncrease_fx > 0 ) + { + IF( EQ_16( st->totalNoise_increase_len, TOTALNOISE_HIST_SIZE ) ) + { + FOR( Word16 n = 0; n < TOTALNOISE_HIST_SIZE; n++ ) + { + st->totalNoise_increase_hist[n] = fix16_to_float( st->totalNoise_increase_hist_fx[n + 1], Q8 ); + move16(); + } + } + ELSE + { + st->totalNoise_increase_hist[st->totalNoise_increase_len] = fix16_to_float( st->totalNoise_increase_hist_fx[st->totalNoise_increase_len], Q8 ); + move16(); + } + } +#endif +#else resetFdCngEnc( st ); +#endif perform_noise_estimation_enc( band_energies, enerBuffer, st->hFdCngEnc, 1, NULL ); diff --git a/lib_enc/prot_fx_enc.h b/lib_enc/prot_fx_enc.h index d78ab652d..0e64a12c1 100644 --- a/lib_enc/prot_fx_enc.h +++ b/lib_enc/prot_fx_enc.h @@ -183,6 +183,12 @@ void fb_tbe_enc_fx( const Word16 fb_exc[], /* i : FB excitation from the SWB part */ Word16 Q_fb_exc ); +void fb_tbe_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : i speech at 48 kHz sample rate Q0*/ + const Word16 fb_exc[], /* i : FB excitation from the SWB part Q_fb_exc*/ + Word16 Q_fb_exc ); + void fb_tbe_reset_enc_fx( Word32 elliptic_bpf_2_48k_mem_fx[][4], Word32 *prev_fb_energy_fx, @@ -1784,13 +1790,14 @@ void perform_noise_estimation_enc_fx( Word16 enerBuffer_exp, HANDLE_FD_CNG_ENC st ); /* i/o: FD_CNG structure containing all buffers and variables */ -void perform_noise_estimation_enc_ivas_fx( Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ - Word16 band_energies_exp, /* i: exponent for energy in critical bands without minimum noise floor MODE2_E_MIN */ - Word32 *enerBuffer, - Word16 enerBuffer_exp, - HANDLE_FD_CNG_ENC st, /* i/o: FD_CNG structure containing all buffers and variables */ - const int32_t input_Fs, /* i : input sampling rate */ - CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ +void perform_noise_estimation_enc_ivas_fx( + Word32 *band_energies, /* i: energy in critical bands without minimum noise floor MODE2_E_MIN */ + Word16 band_energies_exp, + Word32 *enerBuffer, + Word16 enerBuffer_exp, + HANDLE_FD_CNG_ENC hFdCngEnc, /* i/o: CNG structure containing all buffers and variables */ + const Word32 input_Fs, /* i : input sampling rate */ + CPE_ENC_HANDLE hCPE /* i : CPE encoder structure */ ); /* Adjust the noise estimator at the beginning of each CNG phase (encoder-side) */ diff --git a/lib_enc/speech_music_classif.c b/lib_enc/speech_music_classif.c index 7d605217a..24beb8445 100644 --- a/lib_enc/speech_music_classif.c +++ b/lib_enc/speech_music_classif.c @@ -84,9 +84,9 @@ static int16_t mode_decision( Encoder_State *st, int16_t len, float *dec_mov, fl static void var_cor_calc( const float old_corr, float *mold_corr, float var_cor_t[], int16_t *high_stable_cor ); static int16_t attack_det( const float *inp, const int16_t last_clas, const int16_t localVAD, const int16_t coder_type, const int32_t total_brate, const int16_t element_mode, const int16_t clas, float finc_prev[], float *lt_finc, int16_t *last_strong_attack ); - +#ifndef IVAS_FLOAT_FIXED static float tonal_det( const float S[], int16_t vad_flag, float tod_S_map_lt[], float *tod_thr_lt, float *tod_weight, float *tod_S_mass_prev, float *tod_S_mass_lt ); - +#endif static void tonal_context_improv( Encoder_State *st, const float PS[], const float voi_fv, const float cor_map_sum_fv, const float LPCErr ); static void order_spectrum( float *vec, const int16_t len ); @@ -217,7 +217,11 @@ void speech_music_clas_init( set_f( hSpMusClas->finc_prev, 0.0f, ATT_NSEG ); hSpMusClas->lt_finc = 0.0f; hSpMusClas->last_strong_attack = 0; +#ifdef IVAS_FLOAT_FIXED + hSpMusClas->tdm_lt_Etot_fx = 328 /* 0.01 in Q15*/; +#else hSpMusClas->tdm_lt_Etot = 0.01f; +#endif set_f( hSpMusClas->tod_lt_Bin_E, 0.0f, TOD_NSPEC ); set_f( hSpMusClas->tod_S_map_lt, 0.0f, TOD_NSPEC ); hSpMusClas->tod_thr_lt = TOD_THR_MASS; @@ -900,7 +904,7 @@ static void sp_mus_classif_2nd( return; } - +#ifndef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * tonal_det() * @@ -974,7 +978,7 @@ static float tonal_det( return S_mass; } - +#endif /*---------------------------------------------------------------------* * var_cor_calc() * @@ -2568,7 +2572,7 @@ int16_t ivas_smc_gmm( * 1 - 0 -> GSC * 1 - 1 -> TCX *---------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void ivas_smc_mode_selection( Encoder_State *st, /* i/o: encoder state structure */ const int32_t element_brate, /* i : element bitrate */ @@ -2768,7 +2772,7 @@ void ivas_smc_mode_selection( return; } - +#endif /*------------------------------------------------------------------------* * music_mixed_classif_improv() diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 3018245e2..a8ae5ecac 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -505,8 +505,8 @@ typedef struct td_cng_enc_structure typedef struct fd_cng_enc_structure { HANDLE_FD_CNG_COM hFdCngCom; - float msPeriodog[NPART]; /* Periodogram */ +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled float msBminWin[NPART]; float msBminSubWin[NPART]; float msPsd[NPART]; /* Power Spectral Density estimate (i.e., smoothed periodogram) */ @@ -515,7 +515,7 @@ typedef struct fd_cng_enc_structure float msCurrentMinOut[NPART]; float msCurrentMin[NPART]; float msCurrentMinSubWindow[NPART]; - +#endif Word32 msPeriodog_fx[NPART]; /* Periodogram */ Word16 msPeriodog_fx_exp; /* Common exponent for fft and cldfb energies */ Word16 msPeriodog_fx_exp_fft; @@ -531,16 +531,18 @@ typedef struct fd_cng_enc_structure int16_t msLocalMinFlag[NPART]; int16_t msNewMinFlag[NPART]; - +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled float msPsdFirstMoment[NPART]; float msPsdSecondMoment[NPART]; float msNoiseFloor[NPART]; /* Estimated noise floor */ - float msNoiseEst[NPART]; /* Estimated noise level */ +#endif + float msNoiseEst[NPART]; /* Estimated noise level */ float energy_ho[NPART]; float msNoiseEst_old[NPART]; +#if 1 // ndef IVAS_FLOAT_FIXED to be disabled float msLogPeriodog[NPART]; /* Periodogram */ float msLogNoiseEst[NPART]; /* Estimated noise level */ - +#endif Word16 msPsdFirstMoment_fx[NPART]; Word32 msPsdSecondMoment_fx[NPART]; Word16 msNoiseFloor_fx[NPART]; /* Estimated noise floor */ @@ -550,7 +552,6 @@ typedef struct fd_cng_enc_structure Word16 energy_ho_fx_exp; Word32 msNoiseEst_old_fx[NPART]; Word16 msNoiseEst_old_fx_exp; - float msPeriodogBuf[MSBUFLEN * NPART]; Word16 msPeriodogBuf_fx[MSBUFLEN * NPART]; int16_t msPeriodogBufPtr; @@ -563,10 +564,15 @@ typedef struct fd_cng_enc_structure int16_t nFFTpartDec; int16_t partDec[NPART]; + Word16 msLogPeriodog_fx[NPART]; Word16 msLogNoiseEst_fx[NPART]; - +#ifndef IVAS_FLOAT_FIXED float mem_coherence[4]; +#else + Word32 mem_coherence_fx[4]; +#endif + Word16 mem_coherence_exp[4]; } FD_CNG_ENC, *HANDLE_FD_CNG_ENC; // typedef struct @@ -1014,6 +1020,7 @@ typedef struct sp_mus_clas_structure Word16 lowrate_pitchGain; float tdm_lt_Etot; + Word16 tdm_lt_Etot_fx; // Q8 float var_cor_t[VAR_COR_LEN]; Word16 var_cor_t_fx[VAR_COR_LEN]; int16_t high_stable_cor; @@ -1400,9 +1407,9 @@ typedef struct td_bwe_enc_structure float shb_inv_filt_mem[LPC_SHB_ORDER]; float lsp_shb_spacing[3]; float prev_swb_GainShape; - Word32 elliptic_bpf_2_48k_mem_fx[4][4]; + Word32 elliptic_bpf_2_48k_mem_fx[4][4]; /*elliptic_bpf_2_48k_mem_fx_Q[4]*/ Word16 elliptic_bpf_2_48k_mem_fx_Q[4]; - Word32 prev_fb_energy_fx; + Word32 prev_fb_energy_fx; /*prev_fb_energy_fx_Q*/ Word16 prev_fb_energy_fx_Q; Word32 prev_gainFr_SHB_fx; /* Q18 */ Word16 lsp_shb_slow_interpl_fx[LPC_SHB_ORDER]; /* Q15 */ @@ -1856,6 +1863,7 @@ typedef struct enc_core_structure float voicing[3]; /* open-loop normalized correlation values for three half-frames */ // Word16 pitch_fx[3]; Word16 voicing_fx[3]; + Word16 voicing_e; LPD_state_HANDLE hLPDmem; /* ACELP LPDmem memories */ diff --git a/lib_enc/swb_tbe_enc_fx.c b/lib_enc/swb_tbe_enc_fx.c index c52458790..dc8b08704 100644 --- a/lib_enc/swb_tbe_enc_fx.c +++ b/lib_enc/swb_tbe_enc_fx.c @@ -7035,6 +7035,168 @@ void fb_tbe_enc_fx( return; } + +void fb_tbe_enc_ivas_fx( + Encoder_State *st, /* i/o: encoder state structure */ + const Word16 new_input[], /* i : input speech at 48 kHz sample rate Q0 */ + const Word16 fb_exc[], /* i : FB excitation from the SWB part Q_fb_exc */ + Word16 Q_fb_exc ) +{ + Word16 ratio; + Word16 tmp_vec[L_FRAME48k]; + Word16 idxGain; + Word16 input_fhb_new[L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS )]; + Word16 input_fhb[L_FRAME48k]; + Word16 Sample_Delay_HP; + Word32 fb_exc_energy, temp2; + Word32 L_tmp; + Word16 tmp, tmp1, tmp2, exp, exp2, exp_norm; + Word16 s_max_value, exp_temp, i; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + s_max_value = 0; + move16(); + FOR( i = 0; i < L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ); i++ ) + { + s_max_value = s_max( s_max_value, abs_s( new_input[i - NS2SA( 48000, DELAY_FIR_RESAMPL_NS )] ) ); + } + exp_temp = norm_s( s_max_value ); + if ( s_max_value == 0 ) + { + exp_temp = 15; + move16(); + } + + Copy_Scale_sig( new_input - NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), input_fhb_new, L_FRAME48k + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), exp_temp ); + + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + elliptic_bpf_48k_generic_fx( input_fhb_new, &exp_temp, tmp_vec, hBWE_TD->elliptic_bpf_2_48k_mem_fx, hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q, full_band_bpf_2_fx ); + } + ELSE + { + elliptic_bpf_48k_generic_fx( input_fhb_new + NS2SA( 48000, DELAY_FIR_RESAMPL_NS ), &exp_temp, tmp_vec, hBWE_TD->elliptic_bpf_2_48k_mem_fx, hBWE_TD->elliptic_bpf_2_48k_mem_fx_Q, full_band_bpf_2_fx ); + } + + test(); + IF( GT_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_SCE ) ) + { + + IF( EQ_16( st->L_frame, L_FRAME ) ) + { + Sample_Delay_HP = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ) - L_FRAME48k / 2; + move16(); + } + ELSE + { + Sample_Delay_HP = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ) - L_FRAME48k / 2; + move16(); + } + } + ELSE + { + Sample_Delay_HP = NS2SA( 48000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) - L_FRAME48k / 2; + move16(); + } + + IF( NE_16( st->last_extl, FB_TBE ) ) + { + set16_fx( hBWE_TD->old_input_fhb_fx, 0, Sample_Delay_HP ); + hBWE_TD->old_input_fhb_fx_Q = 0; + move16(); + set16_fx( tmp_vec, 0, L_FRAME16k ); + } + Copy_Scale_sig( hBWE_TD->old_input_fhb_fx, hBWE_TD->old_input_fhb_fx, Sample_Delay_HP, sub( exp_temp, hBWE_TD->old_input_fhb_fx_Q ) ); + hBWE_TD->old_input_fhb_fx_Q = exp_temp; + move16(); + Copy( hBWE_TD->old_input_fhb_fx, input_fhb, Sample_Delay_HP ); + Copy( tmp_vec, input_fhb + Sample_Delay_HP, sub( L_FRAME48k, Sample_Delay_HP ) ); + Copy( tmp_vec + L_FRAME48k - Sample_Delay_HP, hBWE_TD->old_input_fhb_fx, Sample_Delay_HP ); + temp2 = sum2_fx_mod( input_fhb, L_FRAME48k / 2 ); /* Q(2*Q_input_fhb-8) */ +#ifdef BASOP_NOGLOB + temp2 = L_add_o( temp2, L_shl_o( hBWE_TD->prev_fb_energy_fx, sub( sub( add( exp_temp, exp_temp ), 8 ), hBWE_TD->prev_fb_energy_fx_Q ), &Overflow ), &Overflow ); /* Q(2*(exp_temp)-8) */ +#else + temp2 = L_add( temp2, L_shl( hBWE_TD->prev_fb_energy_fx, sub( sub( add( exp_temp, exp_temp ), 8 ), hBWE_TD->prev_fb_energy_fx_Q ) ) ); /* Q(2*(exp_temp)-8) */ +#endif + hBWE_TD->prev_fb_energy_fx = sum2_fx_mod( input_fhb + L_FRAME48k / 2, L_FRAME48k / 2 ); /*Q(2*(Q_input_fhb)-8) */ + move32(); + hBWE_TD->prev_fb_energy_fx_Q = sub( add( exp_temp, exp_temp ), 8 ); + move16(); + fb_exc_energy = sum2_fx_mod( fb_exc, L_FRAME16k ); /* Q(2*Q_fb_exc-8) */ + + /*ratio = (float) sqrt( temp2 / fb_exc_energy );*/ + L_tmp = L_max( 1, temp2 ); /*Q(2*(exp_temp)-8)*/ + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 31, sub( add( exp_temp, exp_temp ), 8 ) ), exp ); /* (L_tmp in Q(2*(exp_temp)-8))*/ + + exp2 = norm_l( fb_exc_energy ); + tmp2 = extract_h( L_shl( fb_exc_energy, exp2 ) ); + tmp1 = sub( add( Q_fb_exc, Q_fb_exc ), 8 ); /*1 - 9*/ + exp2 = sub( sub( 31, tmp1 ), exp2 ); /* (L_tmp in Q(2*(exp_temp)-8))*/ + + exp = sub( exp2, exp ); /* Denormalize and substract */ + IF( GT_16( tmp2, tmp ) ) + { + tmp2 = shr( tmp2, 1 ); + exp = add( exp, 1 ); + } + IF( 0 != tmp ) + { + tmp = div_s( tmp2, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp)*/ +#ifdef BASOP_NOGLOB + L_tmp = L_max( L_shr_o( L_tmp, sub( 31, exp ), &Overflow ), 0x1 ); /* Q0 */ +#else + L_tmp = L_max( L_shr( L_tmp, sub( 31, exp ) ), 0x1 ); /* Q0 */ +#endif + } + ELSE + { + L_tmp = 0; + move32(); + } + + /* idxGain = (short)( log2_f ((float)ratio) + 0.5f ); + idxGain = max( 0, min(15,idxGain) ); */ + ratio = 0; + move16(); + IF( GE_32( L_tmp, 32768 ) ) + { + idxGain = 15; + move16(); + } + ELSE + { + ratio = extract_l( L_tmp ); + exp_norm = norm_s( ratio ); + idxGain = sub( 14, exp_norm ); + idxGain = s_max( 0, idxGain ); + } + test(); + test(); + IF( GT_16( idxGain, 2 ) && LT_16( idxGain, 15 ) && GT_16( ratio, add( shl( 2, sub( idxGain, 1 ) ), shl( 2, sub( idxGain, 2 ) ) ) ) ) + { + idxGain = add( idxGain, 1 ); + } + + /* ratio = (float)(1 << idxGain);*/ + IF( EQ_16( st->codec_mode, MODE2 ) ) + { + hBWE_TD->idxGain = idxGain; + move16(); + } + ELSE + { + push_indice( st->hBstr, IND_FB_SLOPE, idxGain, 4 ); + } + + return; +} void tbe_write_bitstream_fx( Encoder_State *st_fx /* i/o: encoder state structure */ ) diff --git a/lib_enc/tcx_utils_enc.c b/lib_enc/tcx_utils_enc.c index 15379f73a..9e52923e8 100644 --- a/lib_enc/tcx_utils_enc.c +++ b/lib_enc/tcx_utils_enc.c @@ -1506,127 +1506,6 @@ int16_t tcx_res_Q_spec( } -/*---------------------------------------------------------------------* - * ProcessIGF() - * - * - *---------------------------------------------------------------------*/ -#if 0 // Not Tested: Some dependency -void ProcessIGF_ivas_fx( - IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ - Encoder_State *st, /**< in: Encoder state */ - Word32 pMDCTSpectrum[], /**< in: MDCT spectrum */ - Word16 *pMDCTSpectrum_e, - Word32 pPowerSpectrum[], /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ - Word16 *pPowerSpectrum_e, - Word16 isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - Word16 isTNSActive, /**< in: flag indicating if the TNS is active */ - Word16 isTransition, /**< in: flag indicating if the input is the transition from from ACELP to TCX20/TCX10 */ - Word16 frameno /**< in: flag indicating index of current subframe */ -) -{ - Word16 igfGridIdx; - Word16 isIndepFlag; - Word16 bsBits; - Word16 bsStart; - BSTR_ENC_HANDLE hBstr = st->hBstr; - - - isIndepFlag = 1; - move16(); - test(); - IF( isTransition && isTCX20 ) - { - igfGridIdx = IGF_GRID_LB_TRAN; - move16(); - } - ELSE - { - IF( isTCX20 ) - { - igfGridIdx = IGF_GRID_LB_NORM; - move16(); - } - ELSE - { - /* It is short block */ - igfGridIdx = IGF_GRID_LB_SHORT; - move16(); - if ( EQ_16( frameno, 1 ) ) - { - isIndepFlag = 0; - move16(); - } - } - } - - - IGFEncApplyMono_fx( hInstance, /**< in: instance handle of IGF Encoder */ - igfGridIdx, /**< in: IGF grid index */ - st, /**< in: Encoder state */ - pMDCTSpectrum, /**< in: MDCT spectrum */ - *pMDCTSpectrum_e, - pPowerSpectrum, /**< in: MDCT^2 + MDST^2 spectrum, or estimate */ - *pPowerSpectrum_e, - isTCX20, /**< in: flag indicating if the input is TCX20 or TCX10/2xTCX5 */ - isTNSActive, /**< in: flag indicating if the TNS is active */ - ( st->last_core == ACELP_CORE ) ); - { - const Word32 tns_predictionGain = st->hIGFEnc->tns_predictionGain; - const Word16 startLine = st->hIGFEnc->infoStartLine; - const Word16 endLine = st->hIGFEnc->infoStopLine; - const Word16 maxOrder = 8; - const Word32 *spec_before = st->hIGFEnc->spec_be_igf; - Word16 curr_order = 0; - Word16 A[ITF_MAX_FILTER_ORDER + 1]; - Word16 Q_A; - Word16 predictionGain = 0; - Word16 *flatteningTrigger = &( st->hIGFEnc->flatteningTrigger ); - - ITF_Detect_fx( spec_before, startLine, endLine, maxOrder, A, &Q_A, &predictionGain, &curr_order, shl( st->hIGFEnc->spec_be_igf_e, 1 ) ); - *flatteningTrigger = 0; - test(); - IF( LT_32( tns_predictionGain, 9646899l /*1.15 Q23*/ ) && - LT_16( predictionGain, 147 /*1.15 Q7*/ ) ) - { - *flatteningTrigger = 1; - } - } - - // IVAS_CODE_BITSTREAM - bsStart = hBstr->next_ind_fx; - - move16(); - hInstance->infoTotalBitsPerFrameWritten = 0; - move16(); - IF( isTCX20 ) - { - IGFEncWriteBitstream_fx( hInstance, NULL, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); - } - ELSE - { - IGFEncWriteBitstream_fx( hInstance, st->hBstr, &hInstance->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); - } - -#ifndef IVAS_CODE_BITSTREAM - bsBits = sub( hBstr->next_ind_fx, bsStart ); - IF( !isTCX20 ) - { - IGFEncConcatenateBitstream_fx( hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot, hBstr->ind_list ); - } -#else - PMT( "New bit stream implementation to be checked" ) - bsBits = sub( hBstr->next_ind_fx, bsStart ); - IF( !isTCX20 ) - { - IGFEncConcatenateBitstream_fx( hInstance, bsBits, &hBstr->next_ind_fx, &hBstr->nb_bits_tot_fx, hBstr->ind_list_fx ); - } - -#endif -} -#endif - - #ifdef IVAS_FLOAT_FIXED /*---------------------------------------------------------------------* * ProcessIGF_ivas_fx() @@ -1687,6 +1566,8 @@ void ProcessIGF_ivas_fx( move16(); predictionGain = 0; move16(); + q_A = 0; + move16(); ITF_Detect_ivas_fx( hIGFEnc->spec_be_igf, hIGFEnc->infoStartLine, hIGFEnc->infoStopLine, 8 /*maxOrder*/, A, &q_A, &predictionGain, &curr_order, sub( 31, hIGFEnc->spec_be_igf_e ) ); @@ -1717,7 +1598,7 @@ void ProcessIGF_ivas_fx( IGFEncWriteBitstream_ivas_fx( hIGFEnc, hBstr, &hIGFEnc->infoTotalBitsPerFrameWritten, igfGridIdx, isIndepFlag ); bsBits = sub( hBstr->nb_ind_tot, pBsStart ); - IGFEncConcatenateBitstream_ivas_fx( hIGFEnc, bsBits, hBstr ); + IGFEncConcatenateBitstream( hIGFEnc, bsBits, hBstr ); } return; @@ -1725,6 +1606,11 @@ void ProcessIGF_ivas_fx( #endif +/*---------------------------------------------------------------------* + * ProcessIGF() + * + * + *---------------------------------------------------------------------*/ void ProcessIGF( Encoder_State *st, /* i : Encoder state */ float *pMDCTSpectrum, /* i : MDCT spectrum */ diff --git a/lib_enc/transient_detection_fx.c b/lib_enc/transient_detection_fx.c index 1a47751fa..559255b42 100644 --- a/lib_enc/transient_detection_fx.c +++ b/lib_enc/transient_detection_fx.c @@ -327,6 +327,7 @@ Word16 GetTCXAvgTemporalFlatnessMeasure_ivas_fx( TRAN_DET_HANDLE pTransientDetec pTransientDetector = &pTransientDetection->transientDetector; pSubblockEnergies = pTransientDetector->pSubblockEnergies; nDelay = pTransientDetector->nDelay; + move16(); nRelativeDelay = sub( pSubblockEnergies->nDelay, nDelay ); pSubblockNrgChange = NULL; nTotBlocks = add( nCurrentSubblocks, nPrevSubblocks ); -- GitLab