diff --git a/lib_com/cnst.h b/lib_com/cnst.h index bbedf69d6b3e9d3b0843e58a72e33b81c079604b..9a9b3417f2e0e8d73cbc388a8a1158a53604d072 100644 --- a/lib_com/cnst.h +++ b/lib_com/cnst.h @@ -1549,6 +1549,7 @@ enum #define SHB_GAIN_QDELTA_1k75 0.08f /* SHB gain scalar quantizer stepsize */ #define SHB_GAIN_QLOW_1k75_FX 0 /* SHB gain lowest scalar quantizer value */ #define SHB_GAIN_QDELTA_1k75_FX 10486 /* SHB gain scalar quantizer stepsize Q17 */ +#define SHB_GAIN_QDELTA_1k75_FX_15 2622 /* SHB gain scalar quantizer stepsize */ #define SHB_GAIN_QLOW_FX -262144 /* Q18*/ /* SHB gain lowest scalar quantizer value */ #define SHB_GAIN_QLOW_FX_16 -65536 /* SHB gain lowest scalar quantizer value */ #define SHB_GAIN_QDELTA_FX_15 4915 /* SHB gain scalar quantizer step size */ diff --git a/lib_com/float_to_fix_ops.c b/lib_com/float_to_fix_ops.c index 7a081f35137dabf9796d96f7fcb8f07e9e3b1018..432bc2d2e2b168fcee1d4a5e45a0830cda7d5c6e 100644 --- a/lib_com/float_to_fix_ops.c +++ b/lib_com/float_to_fix_ops.c @@ -78,6 +78,13 @@ void floatToFixed_arr32( float *f, Word32 *i, Word16 Q, Word16 l ) } } +float fixedToFloat_16( Word16 i, Word16 Q ) +{ + if ( Q < 0 ) + return ( i * (float) ( ( (unsigned) 1 ) << ( -Q ) ) ); + else + return (float) ( i ) / (float) ( (unsigned int) 1 << Q ); +} float fixedToFloat_32( Word32 number, Word16 Q ) { float val = 0.0f; diff --git a/lib_com/int_lsp.c b/lib_com/int_lsp.c index b6528030e17949b4ff1af298ed0996668d5d87ae..522f62fe0568f9c1a16c907938055edd0a7e15b9 100644 --- a/lib_com/int_lsp.c +++ b/lib_com/int_lsp.c @@ -314,3 +314,82 @@ void int_lsp4_fx( return; } + +void int_lsp4_ivas_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame Q15*/ + const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/ + const Word16 lsp_new[], /* i : LSPs from present frame Q15*/ + Word16 *Aq, /* o : LP coefficients in both subframes Q12*/ + const Word16 m, /* i : order of LP filter */ + Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +) +{ + Word16 lsp[M16k]; + Word16 i, j, k; + Word32 L_tmp; + const Word16 *pt_int_coeffs; + + IF( EQ_16( L_frame, L_FRAME ) ) + { + IF( EQ_16( relax_prev_lsf_interp, 1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_12k8_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, 2 ) ) + { + pt_int_coeffs = interpol_frac_mid_FEC_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, -1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_pred_12k8_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, -2 ) ) + { + pt_int_coeffs = interpol_frac2_mid_fx; + } + ELSE + { + pt_int_coeffs = interpol_frac_mid_fx; + } + } + ELSE /* L_frame == L_FRAME16k */ + { + IF( EQ_16( relax_prev_lsf_interp, 1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_16k_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, 2 ) ) + { + pt_int_coeffs = interpol_frac_mid_16k_FEC_fx; + } + ELSE IF( EQ_16( relax_prev_lsf_interp, -1 ) ) + { + pt_int_coeffs = interpol_frac_mid_relaxprev_pred_16k_fx; + } + ELSE + { + pt_int_coeffs = interpol_frac_mid_16k_fx; + } + } + k = sub( shr( L_frame, 6 ), 1 ); + FOR( j = 0; j < k; j++ ) + { + FOR( i = 0; i < m; i++ ) + { + L_tmp = L_mult( lsp_old[i], *pt_int_coeffs ); /*Q31 */ + L_tmp = L_mac( L_tmp, lsp_mid[i], *( pt_int_coeffs + 1 ) ); /*Q31 */ + lsp[i] = mac_r( L_tmp, lsp_new[i], *( pt_int_coeffs + 2 ) ); + move16(); + } + pt_int_coeffs += 3; + + E_LPC_f_lsp_a_conversion( lsp, Aq, m ); + Aq += add( m, 1 ); + } + + /* Last subframe */ + E_LPC_f_lsp_a_conversion( lsp_new, Aq, m ); + + return; +} diff --git a/lib_com/ivas_prot.h b/lib_com/ivas_prot.h index 51a7644727c618f5439f4d63475712ccc155d725..8d847926986ba33c4b22c5f9e902be4bf851faa6 100644 --- a/lib_com/ivas_prot.h +++ b/lib_com/ivas_prot.h @@ -4122,14 +4122,6 @@ void ivas_mdct_quant_coder( const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ); -void ivas_mdct_quant_coder_fx( - CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ - const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ -); - void apply_MCT_enc( MCT_ENC_HANDLE hMCT, /* i/o: MCT encoder structure */ Encoder_State **sts, /* i/o: encoder state structure */ diff --git a/lib_com/ivas_prot_fx.h b/lib_com/ivas_prot_fx.h index 866c42a6695b252fc2c623923ea0f321a90db9ec..d74647545f9b085d3ca1ada04c6dc3de2903efa5 100644 --- a/lib_com/ivas_prot_fx.h +++ b/lib_com/ivas_prot_fx.h @@ -835,14 +835,14 @@ void ivas_lfe_dec_close_fx( void td_stereo_param_updt_fx( - const Word16 lsp_old_PCh[], /* i : primary channel old LSPs */ - const Word16 lsf_old_PCh[], /* i : primary channel old LSFs */ - const Word16 pitch_buf_PCh[], /* i : primary channel pitch buffer */ - Word16 tdm_lspQ_PCh[], /* o : Q LSPs for primary channel */ - Word16 tdm_lsfQ_PCh[], /* o : Q LSFs for primary channel */ - Word16 tdm_Pri_pitch_buf[], /* o : pitch values for primary channel */ - const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ - const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ + const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15 */ + const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qlog2(2.56) */ + const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q6 */ + Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15 */ + Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qlog2(2.56) */ + Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q6 */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ #ifndef FIX_798_WRONG_CPY_OF_PITCH , Word16 Q_var @@ -2725,6 +2725,20 @@ void core_switching_pre_enc_ivas_fx( ); #endif +void ivas_mdct_quant_coder_fx( + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ + Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + Word16 p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ +); + +void ivas_mdct_tcx10_bit_distribution_fx( + Word16 target_bitsTCX10[NB_DIV], /* o : target bit distribution */ + const Word16 nbits_tcx, /* i : TCX bits */ + const Word16 nTnsBitsTCX10[NB_DIV] /* i : TNS bits */ +); + void QuantizeSpectrum_ivas_fx( Encoder_State *st, /* i/o: encoder state structure */ const float A[], /* i : quantized coefficients NxAz_q[M+1] */ diff --git a/lib_com/ivas_rom_com_fx.c b/lib_com/ivas_rom_com_fx.c index affd420b94eb44e1325d8fb7fdcd7c3bad5380f4..84b0e906dad697cca1a6fef7e6ae498fdd01e005 100644 --- a/lib_com/ivas_rom_com_fx.c +++ b/lib_com/ivas_rom_com_fx.c @@ -519,25 +519,40 @@ const UWord16 cum_n_for_id_th[122] = { * Multi-channel LS setups *----------------------------------------------------------------------------------*/ /*Azimuth and elevation LS Tables in Q22*/ + +/* Q22 */ const Word32 ls_azimuth_CICP1_fx[1] = { 0 }; +/* Q22 */ const Word32 ls_elevation_CICP1_fx[1] = { 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP2_fx[2] = { 125829120, -125829120 }; +/* Q22 */ const Word32 ls_elevation_CICP2_fx[2] = { 0, 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP6_fx[5] = { 125829120, -125829120, 0, 461373440, -461373440 }; +/* Q22 */ const Word32 ls_elevation_CICP6_fx[5] = { 0, 0, 0, 0, 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP12_fx[7] = { 125829120, -125829120, 0, 461373440, -461373440, 566231040, -566231040 }; +/* Q22 */ const Word32 ls_elevation_CICP12_fx[7] = { 0, 0, 0, 0, 0, 0, 0 }; +/* Q22 */ const Word32 ls_azimuth_CICP14_fx[7] = { 125829120, -125829120, 0, 461373440, -461373440, 125829120, -125829120 }; +/* Q22 */ const Word32 ls_elevation_CICP14_fx[7] = { 0, 0, 0, 0, 0, 146800640, 146800640 }; +/* Q22 */ const Word32 ls_azimuth_CICP16_fx[9] = { 125829120, -125829120, 0, 461373440, -461373440, 125829120, -125829120, 461373440, -461373440 }; +/* Q22 */ const Word32 ls_elevation_CICP16_fx[9] = { 0, 0, 0, 0, 0, 146800640, 146800640, 146800640, 146800640 }; +/* Q22 */ const Word32 ls_azimuth_CICP19_fx[11] = { 125829120, -125829120, 0, 566231040, -566231040, 377487360, -377487360, 125829120, -125829120, 566231040, -566231040 }; +/* Q22 */ const Word32 ls_elevation_CICP19_fx[11] = { 0, 0, 0, 0, 0, 0, 0, 146800640, 146800640, 146800640, 146800640 }; const Word16 pow_10_q11[128] = { diff --git a/lib_com/ivas_stereo_td_bit_alloc.c b/lib_com/ivas_stereo_td_bit_alloc.c index d16f7b320360777799a331a18a6924ef4f725712..995c70ed2148105d11b944643f60ccd837e5c482 100644 --- a/lib_com/ivas_stereo_td_bit_alloc.c +++ b/lib_com/ivas_stereo_td_bit_alloc.c @@ -968,16 +968,15 @@ void td_stereo_param_updt( } #ifdef IVAS_FLOAT_FIXED - void td_stereo_param_updt_fx( - const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15*/ - const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qx2.56*/ - const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q_var*/ - Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15*/ - Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qx2.56*/ - Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q_var */ - const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ - const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ + const Word16 lsp_old_PCh_fx[], /* i : primary channel old LSPs Q15 */ + const Word16 lsf_old_PCh_fx[], /* i : primary channel old LSFs Qlog2(2.56) */ + const Word16 pitch_buf_PCh_fx[], /* i : primary channel pitch buffer Q6 */ + Word16 tdm_lspQ_PCh_fx[], /* o : Q LSPs for primary channel Q15 */ + Word16 tdm_lsfQ_PCh_fx[], /* o : Q LSFs for primary channel Qlog2(2.56) */ + Word16 tdm_Pri_pitch_buf_fx[], /* o : pitch values for primary channel Q6 */ + const Word16 flag_ACELP16k, /* i : ACELP@16kHz flag */ + const Word16 tdm_use_IAWB_Ave_lpc /* i : flag to indicate the usage of mean inactive LP coefficients */ #ifndef FIX_798_WRONG_CPY_OF_PITCH , Word16 Q_var diff --git a/lib_com/lsf_tools_fx.c b/lib_com/lsf_tools_fx.c index 3a84633af2e48acbabf532b9a707a22512981fa7..dd395cba7a1e50d901218a83ad5a71205fa04d13 100644 --- a/lib_com/lsf_tools_fx.c +++ b/lib_com/lsf_tools_fx.c @@ -555,8 +555,6 @@ Word16 lpc2lsp_fx( move16(); move16(); move16(); - move16(); - move16(); low = 0; high = 8; prev_rt = 0; @@ -1454,7 +1452,7 @@ void lsp_weights_fx( move16(); } - *Qout = 9 - n_max; + *Qout = sub( 9, n_max ); move16(); } @@ -2895,7 +2893,7 @@ void lsf_syn_mem_backup_fx( *gc_threshold_fx = hLPDmem->gc_threshold; move16(); Copy( st_fx->clip_var_fx, clip_var_bck_fx, 6 ); - *next_force_sf_bck_fx = st_fx->next_force_safety_net_fx; + *next_force_sf_bck_fx = st_fx->next_force_safety_net; move16(); @@ -2975,7 +2973,7 @@ void lsf_syn_mem_backup_ivas_fx( *gc_threshold_fx = hLPDmem->gc_threshold; move16(); Copy( st_fx->clip_var_fx, clip_var_bck_fx, 6 ); - *next_force_sf_bck_fx = st_fx->next_force_safety_net_fx; + *next_force_sf_bck_fx = st_fx->next_force_safety_net; move16(); @@ -3116,7 +3114,7 @@ void lsf_syn_mem_restore_fx( hLPDmem->tilt_code = btilt_code_fx; hLPDmem->gc_threshold = gc_threshold_fx; Copy( clip_var_bck_fx, st_fx->clip_var_fx, 6 ); - st_fx->next_force_safety_net_fx = next_force_sf_bck_fx; + st_fx->next_force_safety_net = next_force_sf_bck_fx; return; } diff --git a/lib_com/prot.h b/lib_com/prot.h index df837c21f38acea83410e4bb488316923234f0ed..7a0bbfbc9642fdf48bf636247ac73de4911c9d13 100644 --- a/lib_com/prot.h +++ b/lib_com/prot.h @@ -6173,10 +6173,12 @@ void Next_good_after_burst_erasures( const int16_t ol_size /* i : overlap size */ ); +#ifndef IVAS_FLOAT_FIXED void update_average_rate( SC_VBR_ENC_HANDLE hSC_VBR, /* i/o: SC-VBR state structure */ const int32_t core_brate /* i : core bitrate */ ); +#endif void reset_preecho_dec( HQ_DEC_HANDLE hHQ_core /* i/o: HQ decoder handle */ diff --git a/lib_com/prot_fx.h b/lib_com/prot_fx.h index 9c6706c11a1c7ff49b454ed46e60187c943f08b4..7654c22a8fac05604b6e1fb19d8cab001e41ab3b 100644 --- a/lib_com/prot_fx.h +++ b/lib_com/prot_fx.h @@ -88,6 +88,7 @@ Word32 floatToFixed( float f, Word16 Q ); float fixedToFloat( Word32 i, Word16 Q ); Word32 floatToFixed_32( float f, Word16 Q ); float fixedToFloat_32( Word32 i, Word16 Q ); +float fixedToFloat_16( Word16 i, Word16 Q ); void floatToFixed_arr16( float *f, Word16 *i, Word16 Q, Word16 l ); void floatToFixed_arr32( float *f, Word32 *i, Word16 Q, Word16 l ); @@ -1575,6 +1576,16 @@ void int_lsp4_fx( Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ ); +void int_lsp4_ivas_fx( + const Word16 L_frame, /* i : length of the frame */ + const Word16 lsp_old[], /* i : LSPs from past frame Q15*/ + const Word16 lsp_mid[], /* i : LSPs from mid-frame Q15*/ + const Word16 lsp_new[], /* i : LSPs from present frame Q15*/ + Word16 *Aq, /* o : LP coefficients in both subframes Q12*/ + const Word16 m, /* i : order of LP filter */ + Word16 relax_prev_lsf_interp /* i : relax prev frame lsf interp after erasure */ +); + // interleave_spectrum.c void de_interleave_spectrum_fx( Word32 *coefs, /* i/o: i and output coefficients Q? */ @@ -8188,6 +8199,29 @@ void stat_noise_uv_mod_fx( Word16 *Q_stat_noise_ge /* i/o: noise scaling */ ); +void stat_noise_uv_mod_ivas_fx( + const Word16 coder_type, /* i : Coder type */ + Word16 noisiness, /* i : noisiness parameter Q=0 */ + const Word16 *lsp_old, /* i : old LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_new, /* i : LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr Q=15*/ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes Q=12*/ + Word16 *exc2, /* i/o: excitation buffer Q=Q_exc*/ + Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */ + const Word16 bfi, /* i : Bad frame indicator */ + Word32 *ge_sm, /* i/o: smoothed excitation gain Q=Q_stat_noise_ge (6) */ + Word16 *uv_count, /* i/o: unvoiced counter */ + Word16 *act_count, /* i/o: activation counter */ + Word16 lspold_s[], /* i/o: old LSP Q=15*/ + Word16 *noimix_seed, /* i/o: mixture seed */ + Word16 *st_min_alpha, /* i/o: minimum alpha Q=15*/ + Word16 *exc_pe, /* i/o: scale Q_stat_noise Q=Q_stat_noise*/ + const Word32 bitrate, /* i : core bitrate */ + const Word16 bwidth_fx, /* i : i bandwidth */ + Word16 *Q_stat_noise, /* i/o: noise scaling */ + Word16 *Q_stat_noise_ge /* i/o: noise scaling */ +); + // FEC_adao_codebook_fx.c Word16 FEC_SinOnset_fx( Word16 *exc, /* i/o : exc vector to modify */ @@ -9915,9 +9949,9 @@ Word32 root_a_fx( Word16 *exp_out ); Word32 root_a_over_b_fx( - Word32 a, + Word32 a, /* Q(Q_a) */ Word16 Q_a, - Word32 b, + Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *exp_out ); @@ -10163,6 +10197,24 @@ Word32 imax_pos_fx( const Word32 *y /* i : Input vector for peak interpolation */ ); +void msvq_enc_ivas_fx( + const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) Q_cb */ + const Word16 Q_cb, /* i : Codebook Q */ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word32 u_fx[], /* i : Vector to be encoded (prediction and mean removed) (exp : u_e) */ + const Word16 u_e, /* i : Exponent for Vector to be encoded */ + const Word16 *levels, /* i : Number of levels in each stage */ + const Word16 maxC, /* i : Tree search size (number of candidates kept from from one stage to the next == M-best) */ + const Word16 stages, /* i : Number of stages */ + const Word16 w[], /* i : Weights Q8 */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + const Word16 applyDCT_flag, /* i : applyDCT flag */ + Word32 *invTrfMatrix_fx, /* i/o: synthesis matrix Q31 */ + Word16 Idx[] /* o : Indices */ +); + void msvq_dec_fx( const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) */ const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ @@ -10674,4 +10726,39 @@ void init_tcx_cfg_ivas_fx( const Word16 ini_frame, const Word16 MCT_flag ); +Word16 msvq_stage1_dct_search_fx( + const Word32 *u_fx, /* i : target exp : u_e */ + const Word16 u_e, /* i : exp for target Q0 */ + const Word16 N, /* i : target length and IDCT synthesis length */ + const Word16 maxC_st1, /* i : number of final stage 1 candidates to provide */ + const DCTTYPE dcttype, /* e.g. DCT_T2_16_XX, DCT_T2_24_XX; */ + const Word16 max_dct_trunc, /* i : maximum of truncation lenghts */ + Word32 *invTrfMatrix_fx, /* i : IDCT synthesis matrix for dim N Q31 */ + const Word16 *midQ_truncQ_fx, /* i : midQ vector */ + const Word32 *dct_scaleF_fx, /* i : global scale factors Q10 */ + const Word16 n_segm, /* i : number of segments */ + const Word16 *cols_per_segment, /* i : remaining length per segment */ + const Word16 *trunc_dct_cols_per_segment, /* i : trunc length per segment */ + const Word16 *entries_per_segment, /* i : number of rows per segment */ + const Word16 *cum_entries_per_segment, /* i : number of cumulative entries */ + const Word8 *const W8Qx_dct_sections[], /* i : Word8(byte) segment table ptrs */ + const Word16 *col_syn_shift[], /* i : columnwise syn shift tables */ + const Word8 *segm_neighbour_fwd, /* i : circular neighbour list fwd */ + const Word8 *segm_neighbour_rev, /* i : circular neighbour list reverse */ + const Word16 npost_check, /* i : number of neigbours to check , should be even */ + Word32 *st1_mse_ptr_fx, /* i : dynRAM buffer for MSEs exp : u_e */ + Word16 *indices_st1_local, /* o : selected cand indices */ + Word32 *st1_syn_vec_ptr_fx, /* i/o: buffer for IDCT24 synthesis i :exp : u_e */ + Word32 *dist1_ptr_fx, /* o : resulting stage 1 MSEs in DCT-N domain */ + Word16 *dist1_ptr_e ); + +Word16 msvq_stage1_dct_recalc_candidates_fdcng_wb_fx( + const Word32 *st1_syn_vec_ptr_fx, /* i : IDCT24 synthesis vectors */ + const Word16 st1_syn_vec_e, /* i : exp for IDCT24 synthesis vectors */ + const Word32 *u_fx, /* i : target signal */ + const Word16 u_e, /* i : exp for target signal */ + const int16_t maxC_st1, /* i : number of candidates in stage1 */ + Word32 *dist_ptr_fx, /* i/o: updated MSE vector for stage1 */ + Word16 *dist_ptr_e /* i/o: exp for updated MSE vector for stage1 */ +); #endif diff --git a/lib_com/rom_com.c b/lib_com/rom_com.c index a442ebd84e0bc2582b8d111024f9484deb20761e..8a73dc6bf7d75e75af492789fb601910be5e4c77 100644 --- a/lib_com/rom_com.c +++ b/lib_com/rom_com.c @@ -11803,6 +11803,7 @@ const Word8* const cdk_37bits_ivas_stage1_W8Qx_dct_sections[] = { cdk1_ivas_dct_ /* scaling constants */ const float fdcng_dct_scaleF[3] = { 0.420288085937500f , (0.420288085937500f / 16.0f) , (0.420288085937500f * 0.420288085937500f) / (16.0f*16.0f) }; const float fdcng_dct_invScaleF[2] = { 2.379272460937500f ,2.379272460937500f*16.0f }; +const Word32 fdcng_dct_scaleF_fx[3] = { 902561792, 56410112,1481781 }; const Word16 stage1_col_syn_shift_segm0[8] = { 4, 4, 4, 3, 2, 2, 2, 1 diff --git a/lib_com/rom_com.h b/lib_com/rom_com.h index 3eb6bdf92c2f83894f6272a5be64c5fde271bfc1..1f8155cbc85dfec0f08b9acb68f61a1a9b15d90e 100644 --- a/lib_com/rom_com.h +++ b/lib_com/rom_com.h @@ -1770,6 +1770,7 @@ extern const Word16 cdk1r_tr_midQ_truncQ_fx[]; #endif extern const float fdcng_dct_invScaleF[]; extern const float fdcng_dct_scaleF[]; +extern const Word32 fdcng_dct_scaleF_fx[]; extern const Word16 unique_idctT2_24coeffsQ16[]; diff --git a/lib_com/stat_noise_uv_mod_fx.c b/lib_com/stat_noise_uv_mod_fx.c index e91ea907e3085529012cd2d9b505d6a8ec7f1242..c022ab04f7eca5102b75236fd166f48a4517bb6e 100644 --- a/lib_com/stat_noise_uv_mod_fx.c +++ b/lib_com/stat_noise_uv_mod_fx.c @@ -358,6 +358,339 @@ void stat_noise_uv_mod_fx( } } } + +/*--------------------------------------------------------------------* + * stat_noise_uv_mod() + * + * Modifies excitation signal in stationary noise segments + *--------------------------------------------------------------------*/ + +void stat_noise_uv_mod_ivas_fx( + const Word16 coder_type, /* i : Coder type */ + Word16 noisiness, /* i : noisiness parameter Q=0 */ + const Word16 *lsp_old, /* i : old LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_new, /* i : LSP vector at 4th sfr Q=15*/ + const Word16 *lsp_mid, /* i : LSP vector at 2nd sfr Q=15*/ + Word16 *Aq, /* o : A(z) quantized for the 4 subframes Q=12*/ + Word16 *exc2, /* i/o: excitation buffer Q=Q_exc*/ + Word16 Q_exc, /* i : Q of exc2 excitation buffer [11..-1] expected */ + const Word16 bfi, /* i : Bad frame indicator */ + Word32 *ge_sm, /* i/o: smoothed excitation gain Q=Q_stat_noise_ge (6)*/ + Word16 *uv_count, /* i/o: unvoiced counter */ + Word16 *act_count, /* i/o: activation counter */ + Word16 lspold_s[], /* i/o: old LSP Q=15*/ + Word16 *noimix_seed, /* i/o: mixture seed */ + Word16 *st_min_alpha, /* i/o: minimum alpha Q=15*/ + Word16 *exc_pe, /* i/o: scale Q_stat_noise Q=Q_stat_noise*/ + const Word32 bitrate, /* i : core bitrate */ + const Word16 bwidth_fx, /* i : i bandwidth */ + Word16 *Q_stat_noise, /* i/o: noise scaling */ + Word16 *Q_stat_noise_ge /* i/o: noise scaling */ +) +{ + Word16 exctilt; /* Q15 */ + Word32 vare; /* Q31 */ + Word16 randval; /* Q?? */ + Word16 alpha; /* Q15 */ + Word16 alpha_m1; /* (1-alpha) Q15 */ + Word16 min_alpha; /* Q15 */ + Word16 lspnew_s[M]; /* Same for all LSP (Q15) */ + Word16 oldlsp_mix[M]; + Word16 midlsp_mix[M]; + Word16 newlsp_mix[M]; + Word16 beta; /* Q15 */ + Word16 Noimix_fract; /* (noimix_fac - 1.0) in Q15 */ + /* noimix_fax * x <-> x + Noimix_fract * x */ + Word16 i_subfr; + Word16 i, k; + + /* Work variables for div and sqrt */ + Word16 tmp_nom, tmp_den, tmp_shift, tmp_res; + Word16 Qdiff, Q_local; /* new Q to be used for states Exc_pe and Ge_sm, and Exc2_local */ + Word32 L_tmp_res, L_tmp, L_tmp3, L_Ge; + + Word16 En_shift, Tmp; + Word16 Exc2_local[L_FRAME]; /* local_copy in scaled Q_local*/ +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + /*---------------------------------------------------------* + * Init local variables + *---------------------------------------------------------*/ + alpha = 32767; + move16(); + min_alpha = 16384; + move16(); + + test(); + test(); + test(); + IF( EQ_16( coder_type, INACTIVE ) && ( EQ_32( bitrate, ACELP_9k60 ) || ( LT_32( bitrate, ACELP_9k60 ) && GT_16( bwidth_fx, NB ) ) ) ) + { + min_alpha = *st_min_alpha; + move16(); + /*---------------------------------------------------------* + * decode noisiness parameter + *---------------------------------------------------------*/ + IF( bfi == 0 ) + { + tmp_den = 31; + move16(); + tmp_shift = norm_s( tmp_den ); + L_tmp_res = L_deposit_h( noisiness ); + L_tmp_res = L_shl( L_tmp_res, sub( tmp_shift, 1 ) ); + tmp_den = shl( tmp_den, tmp_shift ); + tmp_res = div_l( L_tmp_res, tmp_den ); +#ifdef BASOP_NOGLOB + min_alpha = add_o( tmp_res, 16384, &Overflow ); +#else /* BASOP_NOGLOB */ + min_alpha = add( tmp_res, 16384 ); +#endif /* BASOP_NOGLOB */ + + /**st_min_alpha = sub(*st_min_alpha, 1638); move16();*/ + min_alpha = s_max( min_alpha, sub( *st_min_alpha, 1638 ) ); + + *st_min_alpha = min_alpha; + move16(); + } + } + + /*---------------------------------------------------------* + * Mix excitation signal with random noise + *---------------------------------------------------------*/ + test(); + test(); + test(); + IF( EQ_16( coder_type, INACTIVE ) && ( EQ_32( bitrate, ACELP_9k60 ) || ( LT_32( bitrate, ACELP_9k60 ) && GT_16( bwidth_fx, NB ) ) ) ) + { + /* use a local working copy for scaling and filtering, not needed if input Q-range is fixed */ + Copy( exc2, Exc2_local, L_FRAME ); + + /* bound Q for internal use, optimization possible */ + Q_local = s_min( 11, s_max( -1, Q_exc ) ); + /* local excitation Q and incoming excitation Q*/ + Qdiff = sub( Q_local, Q_exc ); + /* only shift if incoming Q is outside [11..-1] shift is done in energy calculations aswell */ + Scale_sig( Exc2_local, L_FRAME, Qdiff ); + /* current excitation Q and previous stat_noise states Q */ + Qdiff = sub( Q_local, *Q_stat_noise ); + + *Q_stat_noise_ge = GE_SHIFT; + move16(); /* assign the fixed Q for Ge_sm */ + + IF( Qdiff != 0 ) + { + Scale_sig( exc_pe, 1, Qdiff ); + } + + En_shift = 0; + move16(); + if ( GT_16( Q_local, 3 ) ) + { + /* increase margin for energy accumulation in calc_tilt and vare accumulation */ + En_shift = sub( Q_local, 3 ); + } + + IF( LT_16( min_alpha, TILT_COMP_LIM_FX ) ) + { + FOR( i_subfr = 0; i_subfr < L_FRAME; i_subfr += L_SUBFR ) + { + exctilt = calc_tilt_fx( &Exc2_local[i_subfr], En_shift, L_SUBFR ); /*Q15 */ +#ifdef BASOP_NOGLOB + exctilt = mult( shl_o( sub( TILT_COMP_LIM_FX, min_alpha ), 2, &Overflow ), exctilt ); /*Q15 */ +#else /* BASOP_NOGLOB */ + exctilt = mult( shl( sub( TILT_COMP_LIM_FX, min_alpha ), 2 ), exctilt ); /*Q15 */ +#endif /* BASOP_NOGLOB */ + + PREEMPH_FX( &Exc2_local[i_subfr], exctilt, L_SUBFR, exc_pe ); + } + } + + ( *uv_count )++; + + IF( LE_16( *uv_count, START_NG ) ) + { + alpha = 32767; + move16(); + *act_count = 3; + move16(); + Copy( lsp_new, lspold_s, M ); + } + ELSE + { + *uv_count = s_min( *uv_count, FULL_NG ); + move16(); + tmp_nom = sub( *uv_count, START_NG ); + tmp_den = sub( FULL_NG, START_NG ); + tmp_shift = norm_s( tmp_den ); + tmp_den = shl( tmp_den, tmp_shift ); + tmp_res = div_s( tmp_nom, tmp_den ); +#ifdef BASOP_NOGLOB + tmp_res = shl_o( tmp_res, tmp_shift, &Overflow ); +#else /* BASOP_NOGLOB */ + tmp_res = shl( tmp_res, tmp_shift ); +#endif + alpha = add( 32767, mult( tmp_res, sub( min_alpha, 32767 ) ) ); + + *act_count = 0; + move16(); + } + + /*---------------------------------------------------------* + * calculate lowpass filtered excitation gain + *---------------------------------------------------------*/ + Tmp = shr( Exc2_local[0], En_shift ); + vare = L_mult( Tmp, Tmp ); /* positive accumulation only */ + FOR( i = 1; i < L_FRAME; i++ ) + { + Tmp = shr( Exc2_local[i], En_shift ); +#ifdef BASOP_NOGLOB + vare = L_mac_sat( vare, Tmp, Tmp ); /* positive accumulation only */ +#else + vare = L_mac( vare, Tmp, Tmp ); /* positive accumulation only */ +#endif + } + + /* obtain Ge in Q_local with safety saturation */ + L_Ge = L_shl( L_Sqrt_Q0( L_shr( vare, 1 ) ), add( sub( *Q_stat_noise_ge, 4 ), En_shift ) ); /* L_Ge in Q_local*/ + + /* st->ge_sm = ISP_SMOOTHING_QUANT_A1 * st->ge_sm + (1.0f-ISP_SMOOTHING_QUANT_A1) * ge */ + + IF( EQ_16( *uv_count, 1 ) ) + { + *ge_sm = L_shr( L_Ge, Q_local ); + move32(); + } + ELSE + { + L_tmp = Mult_32_16( L_Ge, P1 ); /* 0.1*ge still in Q local */ + L_tmp3 = Mult_32_16( *ge_sm, P9 ); /* 0.9*ge_sm still in Q_ge */ + + *ge_sm = L_add( L_shr( L_tmp, Q_local ), L_tmp3 ); + move32(); /* addition in Q_ge domain*/ + } + + /*--------------------------------------------------------------------* + * generate mixture of excitation and noise + * float: + * noimix_fac = 1.0f/(float)sqrt(alpha*alpha + (1-alpha)*(1-alpha)) + *--------------------------------------------------------------------*/ + + beta = shl( sub( alpha, 16384 ), 1 ); + alpha_m1 = sub( 32767, alpha ); + L_tmp_res = L_mac( 0, alpha, alpha ); + L_tmp_res = L_mac( L_tmp_res, alpha_m1, alpha_m1 ); + tmp_den = round_fx( L_Frac_sqrtQ31( L_tmp_res ) ); + + tmp_nom = sub( 32767, tmp_den ); + tmp_shift = norm_s( tmp_den ); + tmp_den = shl( tmp_den, tmp_shift ); + tmp_res = div_s( tmp_nom, tmp_den ); + + Noimix_fract = shr( tmp_res, tmp_shift ); /* float value is in range 0.0 to 0.42 */ + + /* L_Ge might be 0 in unvoiced WB */ + L_Ge = L_max( L_Ge, 1 ); + tmp_shift = norm_l( L_Ge ); + tmp_den = extract_h( L_shl( L_Ge, tmp_shift ) ); /* Q_local+Q_ge+tmp_shift-16 */ + tmp_res = div_s( 1 << 14, tmp_den ); /* 15+14-Q_local-tmp_shift-Q_ge+16 */ + L_tmp_res = Mult_32_16( *ge_sm, tmp_res ); /* Q_stat_noise_ge+45-Q_local-Q_ge-tmp_shift-15 */ + L_tmp_res = Mult_32_16( L_tmp_res, sub( 32767, beta ) ); /*30-Q_local-tmp_shift+15-15 */ +#ifdef BASOP_NOGLOB + L_tmp_res = L_add_sat( L_shl_sat( L_tmp_res, sub( add( Q_local, tmp_shift ), 15 ) ), beta ); /* Q15 */ +#else + L_tmp_res = L_add( L_shl( L_tmp_res, sub( add( Q_local, tmp_shift ), 15 ) ), beta ); /* Q15 */ +#endif +#ifdef BASOP_NOGLOB + tmp_res = extract_h( L_shl_o( L_tmp_res, 15, &Overflow ) ); /* 15+15-16=14 */ +#else + tmp_res = extract_h( L_shl( L_tmp_res, 15 ) ); /* 15+15-16=14 */ +#endif + + Noimix_fract = extract_l( Mult_32_16( L_tmp_res, Noimix_fract ) ); /*15+15-15 */ + + FOR( i = 0; i < L_FRAME; i++ ) + { + /*--------------------------------------------------------------------* + * flt: exc2[i] = noimix_fac*exc2[i] * alpha + st->ge_sm*Rnd*((1.0f)-alpha) + * flt: exc2[i] = (noimix_fract*exc2[i]+exc2 )* alpha + st->ge_sm*Rnd*((1.0f)-alpha) + * NB: currently uses 32bit accumulation for best low level performance, + * possibly overkill if input is always up-scaled + *--------------------------------------------------------------------*/ + + /* (1-alpha)*(float)sqrt(12.0f) * ((float)own_random(&(st->noimix_seed))/65536.0f) */ + randval = Random( noimix_seed ); /* +/-32767 */ + randval = mult_r( 28378, randval ); /* Q downscaled by 2 bits ends up in Q14 */ /*sqrt(12.0f) in Q13*/ + randval = extract_l( L_shl( Mult_32_16( L_Ge, randval ), sub( 1, *Q_stat_noise_ge ) ) ); /*Q_local+Q_ge+14-15+1-Q_ge=Q_local */ + + L_tmp = L_mult( Exc2_local[i], alpha ); /* Q_local + 16 */ + L_tmp = L_mac( L_tmp, randval, alpha_m1 ); /* Q_local + 16 */ + L_tmp3 = Mult_32_16( L_tmp, Noimix_fract ); /* Q_local+16+15-15 */ +#ifdef BASOP_NOGLOB + L_tmp = L_add_sat( L_tmp3, L_shl_sat( Mult_32_16( L_tmp, tmp_res ), 1 ) ); /* Q_local+16+14-15+1 */ +#else + L_tmp = L_add( L_tmp3, L_shl( Mult_32_16( L_tmp, tmp_res ), 1 ) ); /* Q_local+16+14-15+1 */ +#endif + Exc2_local[i] = extract_h( L_tmp ); /*Q_local */ + move16(); + } + *Q_stat_noise = Q_local; /* update for next call, routine can only be called once every frame */ + move16(); + Qdiff = sub( Q_exc, Q_local ); /* local excitation and incoming excitation */ + Scale_sig( Exc2_local, L_FRAME, Qdiff ); + Copy( Exc2_local, exc2, L_FRAME ); + + /*--------------------------------------------------------------------* + * Generate low-pass filtered version of ISP coefficients + *--------------------------------------------------------------------*/ + FOR( k = 0; k < M; k++ ) + { + move16(); + lspnew_s[k] = add( + mult( ISP_SMOOTHING_QUANT_A1_FX, lspold_s[k] ), + mult( 32767 - ISP_SMOOTHING_QUANT_A1_FX, lsp_new[k] ) ); + } + + /*--------------------------------------------------------------------* + * replace LPC coefficients + *--------------------------------------------------------------------*/ + + /*--------------------------------------------------------------------* + * pre-calculation of (1-beta) + *--------------------------------------------------------------------*/ + FOR( i = 0; i < M; i++ ) + { + move16(); + move16(); + move16(); + oldlsp_mix[i] = add( mult( beta, lsp_old[i] ), + mult( sub( 32767, beta ), lspold_s[i] ) ); + + midlsp_mix[i] = add( mult( beta, lsp_mid[i] ), + mult( sub( 32767, beta ), add( shr( lspold_s[i], 1 ), + shr( lspnew_s[i], 1 ) ) ) ); + + newlsp_mix[i] = add( mult( beta, lsp_new[i] ), + mult( sub( 32767, beta ), lspnew_s[i] ) ); + } + + int_lsp4_ivas_fx( L_FRAME, oldlsp_mix, midlsp_mix, newlsp_mix, Aq, M, 0 ); + Copy( lspnew_s, lspold_s, M ); + } + ELSE /* (unvoiced_vad != 0) */ + { + ( *act_count )++; + IF( GT_16( *act_count, 3 ) ) + { + *act_count = 3; + move16(); + *uv_count = 0; + move16(); + } + } +} /*---------------------------------------------------------------------------* * calc_tilt() * diff --git a/lib_com/swb_bwe_com_fx.c b/lib_com/swb_bwe_com_fx.c index a308d15596b74e9168d564093a36dab1b17518ff..29662510a85b4570b55c38547ac7c36abf903739 100644 --- a/lib_com/swb_bwe_com_fx.c +++ b/lib_com/swb_bwe_com_fx.c @@ -528,7 +528,6 @@ void calc_normal_length_fx( n_band = 0; move16(); pit = sp; - move16(); /*Q_syn */ FOR( i = 0; i < N; i++ ) { peak = 0; @@ -544,14 +543,14 @@ void calc_normal_length_fx( pit++; } - L_tmp = L_mult0( peak, 15 + THRES ); /*Q_syn */ + L_tmp = L_mult0( peak, add( 15, THRES ) ); /*Q_syn */ IF( EQ_16( THRES, 8 ) ) { - L_tmp1 = L_shl( Mult_32_16( L_mean, 32767 ), 3 ); + L_tmp1 = L_shl( Mpy_32_16_1( L_mean, 32767 ), 3 ); } ELSE { - L_tmp1 = L_shl( Mult_32_16( L_mean, 32767 ), 2 ); + L_tmp1 = L_shl( Mpy_32_16_1( L_mean, 32767 ), 2 ); } test(); @@ -605,6 +604,7 @@ void calc_normal_length_fx( /**L_swb_norm = add(mult_r(L_swb_norm_cur, 3277), mult_r(*prev_L_swb_norm, 29491)); */ *L_swb_norm = round_fx( L_mac( L_mult( L_swb_norm_cur, 3277 ), *prev_L_swb_norm, 29491 ) ); + move16(); *prev_L_swb_norm = L_swb_norm_cur; move16(); } @@ -877,7 +877,7 @@ void calc_norm_envelop_fx( } envelope[env_index] = L_tmp; move32(); - env_index++; + env_index = add( env_index, 1 ); } i = 0; @@ -896,8 +896,8 @@ void calc_norm_envelop_fx( } envelope[env_index] = L_tmp; move32(); - env_index++; - i++; + env_index = add( env_index, 1 ); + i = add( i, 1 ); } return; diff --git a/lib_com/swb_tbe_com_fx.c b/lib_com/swb_tbe_com_fx.c index 891e2524c0e9b19d3c980863c97c43cfa12108da..456ab2bc3a8bf5b0114a86da52715c6af5c45e93 100644 --- a/lib_com/swb_tbe_com_fx.c +++ b/lib_com/swb_tbe_com_fx.c @@ -1158,6 +1158,7 @@ void flip_spectrum_and_decimby4_fx( /*--------------------------------------------------------------------------*/ /* CALLED FROM : */ /*==========================================================================*/ + #ifdef IVAS_FLOAT_FIXED void ivas_GenShapedWBExcitation_fx( Word16 *excSHB, /* o : synthesized shaped shb exctiation Q_bwe_exc*/ @@ -1455,20 +1456,20 @@ void ivas_GenShapedWBExcitation_fx( #endif void GenShapedWBExcitation_fx( - Word16 *excSHB, /* o : synthesized shaped shb exctiation Q_bwe_exc*/ - const Word16 *lpc_shb, /* i : lpc coefficients Q12*/ - Word16 *exc4kWhtnd, /* o : whitened synthesized shb excitation Q_bwe_exc*/ - Word32 *mem_csfilt, /* i/o : memory Q_bwe_exc+16*/ - Word16 *mem_genSHBexc_filt_down1, /* i/o : memory Q_bwe_exc*/ - Word16 *mem_genSHBexc_filt_down2, /* i/o : memory Q_bwe_exc*/ - Word16 *mem_genSHBexc_filt_down3, /* i/o : memory Q_bwe_exc*/ - Word16 *state_lpc_syn, /* i/o : memory Q_bwe_exc*/ - const Word16 coder_type, /* i : coding type */ - const Word16 *bwe_exc_extended, /* i : bwidth extended exciatation Q_bwe_exc*/ - const Word16 Q_bwe_exc, - Word16 bwe_seed[], /* i/o : random number generator seed */ - const Word16 voice_factors[], /* i : voicing factor Q15*/ - const Word16 uv_flag, /* i : unvoiced flag */ + Word16 *excSHB, /* o : synthesized shaped shb exctiation Q(Q_bwe_exc) */ + const Word16 *lpc_shb, /* i : lpc coefficients Q12 */ + Word16 *exc4kWhtnd, /* o : whitened synthesized shb excitation Q(Q_bwe_exc) */ + Word32 *mem_csfilt, /* i/o : memory Q(Q_bwe_exc+16) */ + Word16 *mem_genSHBexc_filt_down1, /* i/o : memory Q(Q_bwe_exc) */ + Word16 *mem_genSHBexc_filt_down2, /* i/o : memory Q(Q_bwe_exc) */ + Word16 *mem_genSHBexc_filt_down3, /* i/o : memory Q(Q_bwe_exc) */ + Word16 *state_lpc_syn, /* i/o : memory Q(Q_bwe_exc) */ + const Word16 coder_type, /* i : coding type */ + const Word16 *bwe_exc_extended, /* i : bwidth extended exciatation Q(Q_bwe_exc) */ + const Word16 Q_bwe_exc, /* i : Q for memories */ + Word16 bwe_seed[], /* i/o : random number generator seed */ + const Word16 voice_factors[], /* i : voicing factor Q15 */ + const Word16 uv_flag, /* i : unvoiced flag */ const Word16 igf_flag ) { Word16 i, j, k; @@ -1498,6 +1499,9 @@ void GenShapedWBExcitation_fx( Flag Overflow = 0; move32(); #endif + move16(); + move16(); + move16(); /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ L_tmp = L_mult( voice_factors[0], 8192 ); @@ -1534,7 +1538,6 @@ void GenShapedWBExcitation_fx( create_random_vector_fx( exc4kWhtnd, L_FRAME16k / 4, bwe_seed ); IF( LT_16( Q_bwe_exc, 5 ) ) { - FOR( i = 0; i < L_FRAME16k / 4; i++ ) { exc4kWhtnd[i] = shl_r( exc4kWhtnd[i], sub( Q_bwe_exc, 5 ) ); /*Q(Q_bwe_exc)/Q5(if Q_bwe_exc > 5) */ @@ -1565,6 +1568,7 @@ void GenShapedWBExcitation_fx( /* Ensure pow1 is greater than zero when computing normalization */ max_val = 0; + move16(); FOR( i = 0; i < L_FRAME16k / 4; i++ ) { excTmp2[i] = abs_s( exc4kWhtnd[i] ); @@ -1615,7 +1619,7 @@ void GenShapedWBExcitation_fx( excNoisyEnv[i] = L_add( *mem_csfilt, L_mult( csfilt_num2[0], excTmp2[i] ) ); #endif move32(); /* Q_bwe_exc+16 */ - *mem_csfilt = Mult_32_16( excNoisyEnv[i], neg_csfilt_den2[1] ); + *mem_csfilt = Mpy_32_16_1( excNoisyEnv[i], neg_csfilt_den2[1] ); move32(); /* Q_bwe_exc+16 */ } @@ -1623,9 +1627,10 @@ void GenShapedWBExcitation_fx( /* Ensure pow22 is greater than zero when computing normalization */ Lmax = 0; + move32(); FOR( i = 0; i < L_FRAME16k / 4; i++ ) { - exc4k_32[i] = Mult_32_16( excNoisyEnv[i], exc4k[i] ); + exc4k_32[i] = Mpy_32_16_1( excNoisyEnv[i], exc4k[i] ); move32(); /* Q_bwe_exc+6 */ Lmax = L_max( Lmax, L_abs( exc4k_32[i] ) ); } @@ -1650,7 +1655,7 @@ void GenShapedWBExcitation_fx( #endif move16(); } - n2 = 30 - n2 - ( Q_bwe_exc + 6 ); + n2 = sub( sub( 30, n2 ), add( Q_bwe_exc, 6 ) ); pow22 = 1; move32(); FOR( i = 0; i < L_FRAME16k / 4; i++ ) @@ -1719,7 +1724,7 @@ void GenShapedWBExcitation_fx( #else temp1 = round_fx( L_shl( Ltemp1, exp ) ); /* Q15 */ #endif - L_tmp = Mult_32_16( pow1, sub( 32767, tmp_vfac ) ); /* Q22*/ + L_tmp = Mpy_32_16_1( pow1, sub( 32767, tmp_vfac ) ); /* Q22*/ Ltemp2 = root_a_over_b_fx( L_tmp, sub( 22, shl( n1, 1 ) ), pow22, sub( 22, shl( n2, 1 ) ), &exp ); #ifdef BASOP_NOGLOB temp2 = round_fx_o( L_shl_o( Ltemp2, exp, &Overflow ), &Overflow ); /* Q15 */ @@ -1738,7 +1743,7 @@ void GenShapedWBExcitation_fx( exc4kWhtnd[k] = round_fx( L_tmp ); /* Q_bwe_exc */ #endif move16(); - k++; + k = add( k, 1 ); } } } @@ -3815,18 +3820,16 @@ void GenSHBSynth_fx( /* CALLED FROM : RX */ /*==============================================================================*/ - void ScaleShapedSHB_fx( - const Word16 length, /* i : SHB overlap length */ - Word16 *synSHB, /* i/o : synthesized shb signal Q_bwe_exc/Qx */ - Word16 *overlap, /* i/o : buffer for overlap-add Q_bwe_exc/Qx */ - const Word16 *subgain, /* i : subframe gain Q15*/ - const Word32 frame_gain, /* i : frame gain Q18 */ - const Word16 *win, /* i : window Q15*/ - const Word16 *subwin, /* i : subframes window Q15*/ + const Word16 length, /* i : SHB overlap length */ + Word16 *synSHB, /* i/o : synthesized shb signal Q(Q_bwe_exc)/Q(Qx) */ + Word16 *overlap, /* i/o : buffer for overlap-add Q(Q_bwe_exc)/Q(Qx) */ + const Word16 *subgain, /* i : subframe gain Q15 */ + const Word32 frame_gain, /* i : frame gain Q18 */ + const Word16 *win, /* i : window Q15 */ + const Word16 *subwin, /* i : subframes window Q15 */ Word16 *Q_bwe_exc, - Word16 *Qx /* o : newly computed Q factor for synSHB */ - , + Word16 *Qx, /* o : newly computed Q factor for synSHB */ Word16 n_mem3, Word16 prev_Q_bwe_syn2 ) { @@ -3845,11 +3848,10 @@ void ScaleShapedSHB_fx( set32_fx( mod_syn, 0, L_FRAME16k + L_SHB_LAHEAD ); /* apply gain for each subframe, and store noise output signal using overlap-add */ - IF( length == SHB_OVERLAP_LEN / 2 ) + IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { /* WB Gain shape and gain frame application with overlap */ skip = skip_bands_WB_TBE; - move16(); l_frame = L_FRAME16k / 4; move16(); l_shb_lahead = L_SHB_LAHEAD / 4; @@ -3892,18 +3894,18 @@ void ScaleShapedSHB_fx( l_shb_lahead = L_SHB_LAHEAD; move16(); skip = skip_bands_SWB_TBE; - move16(); num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; move16(); join_length = i_mult2( num_join, length ); j = 0; + move16(); FOR( k = 0; k < length; k++ ) { sum_gain = mult_r( subwin[k + 1], subgain[0] ); /* Q15 */ mod_syn[j] = L_mult( synSHB[j], sum_gain ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } FOR( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) @@ -3912,7 +3914,7 @@ void ScaleShapedSHB_fx( { mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) @@ -3923,21 +3925,21 @@ void ScaleShapedSHB_fx( sum_gain = round_fx( L_mac0( L_tmp, subwin[length - k - 1], subgain[i * num_join] ) ); /*Q14 */ mod_syn[j] = L_shl( L_mult( sum_gain, synSHB[j] ), 1 ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } } FOR( k = 0; k < join_length - length; k++ ) { mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) { sum_gain = mult_r( subwin[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); /* Q15 */ mod_syn[j] = L_mult( synSHB[j], sum_gain ); move32(); /* Q_bwe_exc + 16 */ - j++; + j = add( j, 1 ); } } @@ -3954,7 +3956,9 @@ void ScaleShapedSHB_fx( = (Q_gFr_norm + 2) */ *Q_bwe_exc = add( *Q_bwe_exc, Q_gFr_norm ); /* compensate for the exp shift */ - *Q_bwe_exc = sub( *Q_bwe_exc, 13 ); /* Keep Q-fac at => (Q_bwe_exc + Q_gFr_norm - 13) */ + move16(); + *Q_bwe_exc = sub( *Q_bwe_exc, 13 ); /* Keep Q-fac at => (Q_bwe_exc + Q_gFr_norm - 13) */ + move16(); /* check for headroom of previous buff memories: overlap, Hilbert, and interp all-pass mem */ tmpQ15 = add( prev_Q_bwe_syn2, n_mem3 ); @@ -3977,15 +3981,15 @@ void ScaleShapedSHB_fx( move16(); } temp1 = abs_s( overlap[i] ); - temp1 = shl( temp1, ( *Q_bwe_exc - prev_Q_bwe_syn2 ) ); - move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ + temp1 = shl( temp1, sub( *Q_bwe_exc, prev_Q_bwe_syn2 ) ); overlap[i] = i_mult( temp1, temp2 ); + move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ } FOR( i = 0; i < l_shb_lahead; i++ ) { - L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ - L_tmp2 = Mult_32_16( L_tmp, win[i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ + L_tmp = Mpy_32_16_1( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + L_tmp2 = Mpy_32_16_1( L_tmp, win[i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ synSHB[i] = mac_r( L_tmp2, overlap[i], MAX_16 ); move16(); /* Q_bwe_exc + Q_gFr_norm - 13 */ synSHB[i + l_shb_lahead] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ @@ -3994,21 +3998,23 @@ void ScaleShapedSHB_fx( FOR( ; i < l_frame; i++ ) { - L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ - synSHB[i] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + L_tmp = Mpy_32_16_1( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + synSHB[i] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ move16(); } l_frame_tmp = add( l_frame, l_shb_lahead ); FOR( ; i < l_frame_tmp; i++ ) { - L_tmp = Mult_32_16( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ - L_tmp = Mult_32_16( L_tmp, win[l_frame + l_shb_lahead - 1 - i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ - overlap[i - l_frame] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + L_tmp = Mpy_32_16_1( mod_syn[i], gain_frame_Q16 ); /* Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15 */ + L_tmp = Mpy_32_16_1( L_tmp, win[l_frame + l_shb_lahead - 1 - i] ); /* (Q_bwe_exc + 16 + Q_gFr_norm + 2 - 15) + 15 + (1-16) */ + overlap[i - l_frame] = round_fx( L_tmp ); /* Q_bwe_exc + Q_gFr_norm - 13 */ + move16(); } return; } + /*-------------------------------------------------------------------* * ScaleShapedWB() * diff --git a/lib_com/tools_fx.c b/lib_com/tools_fx.c index d0b3dd0dda542f06c4a4f11ffb945bf1a6e0998c..088a6037ef22886b8bcc41314c43dc0b8d80ad56 100644 --- a/lib_com/tools_fx.c +++ b/lib_com/tools_fx.c @@ -1197,8 +1197,10 @@ Word16 minimum_32_fx( /* o : index of the minimum value i } tmp = L_min( tmp, vec_fx[j] ); } - - *min_fx = tmp; + if ( min_fx != NULL ) + { + *min_fx = tmp; + } move32(); return ind; @@ -1232,7 +1234,10 @@ Word16 maximum_32_fx( /* o : index of the maximum value in t } tmp = L_max( tmp, vec[j] ); } - *max_val = tmp; + if ( max_val != NULL ) + { + *max_val = tmp; + } move32(); return ind; @@ -1633,13 +1638,14 @@ void Vr_subt( * Searches a given codebook to find the nearest neighbour in Euclidean space. * Index of the winning codevector and the winning vector itself are returned. *-------------------------------------------------------------------*/ -Word16 vquant_fx( /* o: index of the winning codevector */ - Word16 x[], /* i: vector to quantize Q13 */ - const Word16 x_mean[], /* i: vector mean to subtract (0 if none)Q13*/ - Word16 xq[], /* o: quantized vector Q13 */ - const Word16 cb[], /* i: codebook Q13 */ - const Word16 dim, /* i: dimension of codebook vectors */ - const Word16 cbsize /* i: codebook size */ + +Word16 vquant_fx( /* o: index of the winning codevector */ + Word16 x[], /* i: vector to quantize Q13 */ + const Word16 x_mean[], /* i: vector mean to subtract (0 if none) Q13 */ + Word16 xq[], /* o: quantized vector Q13 */ + const Word16 cb[], /* i: codebook Q13 */ + const Word16 dim, /* i: dimension of codebook vectors */ + const Word16 cbsize /* i: codebook size */ ) { Word16 tmp; @@ -1649,7 +1655,7 @@ Word16 vquant_fx( /* o: index of the winning codevector idx = 0; move16(); L_mindist = MAX_32; - move16(); + move32(); IF( x_mean != 0 ) { FOR( d = 0; d < dim; d++ ) @@ -1679,7 +1685,7 @@ Word16 vquant_fx( /* o: index of the winning codevector } L_mindist = L_min( L_mindist, L_dist ); } - if ( xq == 0 ) + IF( xq == 0 ) { return idx; } @@ -2351,9 +2357,9 @@ Word32 root_a_fx( Word32 root_a_over_b_fx( - Word32 a, + Word32 a, /* Q(Q_a) */ Word16 Q_a, - Word32 b, + Word32 b, /* Q(Q_b) */ Word16 Q_b, Word16 *exp_out ) { diff --git a/lib_dec/stat_dec.h b/lib_dec/stat_dec.h index 212183213f564146772e06d2862e5f9c7b8c914d..b6d153746284057284761583ac8f194e9f65fd4d 100644 --- a/lib_dec/stat_dec.h +++ b/lib_dec/stat_dec.h @@ -2279,7 +2279,7 @@ typedef struct Decoder_State int16_t bfi_pitch_frame; /* FEC - frame length when pitch for FEC is saved */ - Word16 old_pitch_buf_16_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values 15Q16 */ + Word16 old_pitch_buf_16_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values Q6 */ Word32 old_pitch_buf_fx[2 * NB_SUBFR16k + 2]; /* FEC - buffer of old subframe pitch values 15Q16 */ int16_t upd_cnt; /* FEC - counter of frames since last update */ diff --git a/lib_enc/acelp_core_enc.c b/lib_enc/acelp_core_enc.c index b573bc5a9b82d8f698efc54fcf88938d2dc9983a..64caa1e9930ea484127145df472a8c152ea87966 100644 --- a/lib_enc/acelp_core_enc.c +++ b/lib_enc/acelp_core_enc.c @@ -49,6 +49,11 @@ #include "wmc_auto.h" #include "options_warnings.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#endif + /*-------------------------------------------------------------------* * acelp_core_enc() * @@ -663,17 +668,11 @@ ivas_error acelp_core_enc( *-----------------------------------------------------------------*/ /* SC-VBR & channel-aware mode - back-up memories for LSF quantizer and synthesis filter */ - st->next_force_safety_net_fx = st->next_force_safety_net; - move16(); lsf_syn_mem_backup_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 ); IF( !tdm_lp_reuse_flag ) { - st->next_force_safety_net_fx = st->next_force_safety_net; - move16(); lsf_enc_ivas_fx( st, lsf_new_fx, lsp_new_fx, lsp_mid_fx, Aq_fx, tdm_low_rate_mode, st->GSC_IVAS_mode, tdm_lsfQ_PCh_fx, Q_new ); - st->next_force_safety_net = st->next_force_safety_net_fx; - move16(); } ELSE { @@ -955,7 +954,42 @@ ivas_error acelp_core_enc( { /* exc2 buffer is needed only for updating of Aq[] which is needed for core switching */ mvr2r( exc, exc2, st->L_frame ); +#ifndef IVAS_FLOAT_FIXED stat_noise_uv_enc( st, epsP, lsp_new, lsp_mid, Aq, exc2, uc_two_stage_flag ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from float to fix + Word16 Q_exc2 = Q_factor_arr( exc2, L_FRAME ); + Word16 exc2_fx[L_FRAME16k]; + floatToFixed_arr( exc2, exc2_fx, Q_exc2, L_FRAME16k ); + floatToFixed_arr( Aq, Aq_fx, 12, NB_SUBFR16k * ( M + 1 ) ); + floatToFixed_arr( st->lspold_s, st->lspold_s_fx, 15, 16 ); + st->min_alpha_fx = float_to_fix16( st->min_alpha, 15 ); + Word32 LepsP[2]; + Word32 epsP_fx[M + 1]; + Word16 e_epsP; + f2me_buf( epsP, epsP_fx, &e_epsP, M + 1 ); + st->ge_sm_fx = float_to_fix( st->ge_sm, 6 ); + st->exc_pe_fx = float_to_fix16( st->exc_pe, st->Q_stat_noise ); + floatToFixed_arr( lsp_new, lsp_new_fx, 15, 16 ); + floatToFixed_arr( lsp_mid, lsp_mid_fx, 15, 16 ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, 15, 16 ); +#endif + LepsP[0] = epsP_fx[2]; + move32(); + LepsP[1] = epsP_fx[16]; + move32(); + stat_noise_uv_enc_ivas_fx( st, LepsP, lsp_new_fx, lsp_mid_fx, Aq_fx, exc2_fx, uc_two_stage_flag, Q_exc2 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // conv params from fix to float + fixedToFloat_arr( exc2_fx, exc2, Q_exc2, L_FRAME16k ); + fixedToFloat_arr( Aq_fx, Aq, 12, NB_SUBFR16k * ( M + 1 ) ); + fixedToFloat_arr( st->lspold_s_fx, st->lspold_s, 15, 16 ); + st->min_alpha = fix16_to_float( st->min_alpha_fx, 15 ); + st->ge_sm = fix_to_float( st->ge_sm_fx, 6 ); + st->exc_pe = fix16_to_float( st->exc_pe_fx, st->Q_stat_noise ); +#endif +#endif } /*-----------------------------------------------------------------* @@ -1052,7 +1086,19 @@ ivas_error acelp_core_enc( /* reset in case of bitrate switching in EVS */ if ( st->hSC_VBR != NULL ) { +#ifndef IVAS_FLOAT_FIXED update_average_rate( st->hSC_VBR, st->core_brate ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // performing float to fix conversions + st->hSC_VBR->SNR_THLD_fx = float_to_fix16( st->hSC_VBR->SNR_THLD, 8 ); +#endif + update_average_rate_fx( st->hSC_VBR, st->core_brate ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // performing fix to float conversions + st->hSC_VBR->SNR_THLD = fix16_to_float( st->hSC_VBR->SNR_THLD_fx, 8 ); +#endif +#endif } } @@ -1187,6 +1233,355 @@ ivas_error acelp_core_enc( tc_subfr = -1; position = -1; + exc = old_exc_flt + L_EXC_MEM; /* pointer to excitation signal in the current frame */ + mvr2r( hLPDmem->old_exc_flt, old_exc_flt, L_EXC_MEM ); + mvr2r( hLPDmem->mem_syn2_flt, hLPDmem->mem_syn1_flt, M ); + mvr2r( hLPDmem->mem_syn2_flt, hLPDmem->mem_syn3_flt, M ); + + /* update Aw[] coefficients */ + weight_a_subfr( st->L_frame / L_SUBFR, A, Aw, st->gamma_flt, M ); +} + +if ( st->last_bwidth == NB && st->bwidth != NB && st->ini_frame != 0 ) +{ + st->rate_switching_reset = 1; +} + +/*----------------------------------------------------------------* + * Encoding of CNG frames + *----------------------------------------------------------------*/ + +if ( st->core_brate == SID_2k40 || st->core_brate == FRAME_NO_DATA ) +{ + if ( st->cng_type == LP_CNG ) + { + /* Run CNG post parameter update */ + cng_params_postupd( st->hTdCngEnc->ho_circ_ptr, &st->hTdCngEnc->cng_buf_cnt, st->hTdCngEnc->cng_exc2_buf_flt, st->hTdCngEnc->cng_brate_buf, st->hTdCngEnc->ho_env_circ, st->element_mode, st->hFdCngEnc->hFdCngCom->CngBandwidth ); + + /* encode CNG parameters */ + CNG_enc( st, Aq, inp, ener, lsp_mid, lsp_new, lsf_new, &allow_cn_step, q_env, &sid_bw ); + + /* comfort noise generation */ + CNG_exc( st->core_brate, st->L_frame, &st->hTdCngEnc->Enew, &st->hTdCngEnc->cng_seed, exc, exc2, &st->hTdCngEnc->lp_ener, st->last_core_brate, &st->hDtxEnc->first_CNG, &st->hTdCngEnc->cng_ener_seed, bwe_exc, allow_cn_step, &st->hTdCngEnc->last_allow_cn_step, st->hTdCngEnc->num_ho, q_env, st->hTdCngEnc->lp_env, st->hTdCngEnc->old_env, st->hTdCngEnc->exc_mem, st->hTdCngEnc->exc_mem1, &sid_bw, &st->hTdCngEnc->cng_ener_seed1, exc3, st->Opt_AMR_WB, EVS_MONO ); + } + else + { + if ( st->core_brate == SID_2k40 && st->element_mode != IVAS_CPE_MDCT ) + { + FdCng_encodeSID( st ); + st->hDtxEnc->last_CNG_L_frame = st->L_frame; + } + + generate_comfort_noise_enc( st ); + + FdCng_exc_flt( st->hFdCngEnc->hFdCngCom, &st->hDtxEnc->CNG_mode, st->L_frame, st->lsp_old, st->hDtxEnc->first_CNG, st->hDtxEnc->lspCNG, Aq, lsp_new, lsf_new, exc, exc2, bwe_exc ); + mvr2r( exc2, exc3, st->L_frame ); + + if ( st->core_brate == SID_2k40 ) + { + if ( st->hTdCngEnc != NULL ) + { + tmpF = cng_energy( st->element_mode, st->bwidth, st->hDtxEnc->CNG_mode, st->hTdCngEnc->CNG_att, exc, st->L_frame ); + i = (int16_t) ( ( tmpF + 2.0f ) * STEP_SID ); + i = min( max( i, 0 ), 127 ); + st->hTdCngEnc->old_enr_index = i; + } + } + } + + /* Reset HO counter in the first SID frame */ + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->burst_ho_cnt = 0; + } + + /* synthesis at 12.8kHz sampling rate */ + syn_12k8( st->L_frame, Aq, exc3, syn1, hLPDmem->mem_syn3_flt, 1 ); + + /* reset the encoder */ + CNG_reset_enc( st, pitch_buf, voice_factors, 0 ); + + /* update st->mem_syn1_flt for ACELP core switching */ + mvr2r( hLPDmem->mem_syn3_flt, hLPDmem->mem_syn1_flt, M ); + + /* update ACELP core synthesis filter memory */ + mvr2r( hLPDmem->mem_syn3_flt, hLPDmem->mem_syn_flt, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn1 + st->L_frame - L_SYN_MEM, hLPDmem->mem_syn_r_flt, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + if ( st->hBWE_FD != NULL ) + { + save_old_syn( st->L_frame, syn1, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); + } + + /*Update MODE2 core switching memory*/ + deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); +} + +/*----------------------------------------------------------------* + * Encoding of all other frames + *----------------------------------------------------------------*/ + +else +{ + /*-----------------------------------------------------------------* + * Configure ACELP bit allocation + *-----------------------------------------------------------------*/ + + nb_bits = 0; + st->acelp_cfg.FEC_mode = 0; + uc_two_stage_flag = 0; + + if ( !nelp_mode && !ppp_mode ) + { + config_acelp1_IVAS( ENC, st->total_brate, st->core_brate, st->core, st->extl, st->extl_brate, st->L_frame, st->GSC_noisy_speech, &( st->acelp_cfg ), hBstr->nb_bits_tot, st->coder_type, tc_subfr, 0, &nb_bits, unbits, st->element_mode, &uc_two_stage_flag, tdm_lp_reuse_flag, tdm_low_rate_mode, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); + } + + /*-----------------------------------------------------------------* + * After inactive period, use the most up-to-date ISPs + *-----------------------------------------------------------------*/ + +#ifdef NON_BE_FIX_807_MASA_DTX_BRSW + if ( st->hDtxEnc != NULL && ( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_2k40 ) ) +#else + if ( st->last_core_brate == FRAME_NO_DATA || st->last_core_brate == SID_2k40 ) +#endif + { + mvr2r( st->hDtxEnc->lspCNG, st->lsp_old, M ); + lsp2lsf( st->hDtxEnc->lspCNG, st->lsf_old, M, int_fs ); + } + + /*-----------------------------------------------------------------* + * Reset higher ACELP pre-quantizer in case of switching + *-----------------------------------------------------------------*/ + + if ( !st->use_acelp_preq ) + { + st->mem_deemp_preQ = 0.0f; + st->mem_preemp_preQ = 0.0f; + st->last_code_preq = 0; + st->last_nq_preQ = 0; + } + st->use_acelp_preq = 0; + + /*-----------------------------------------------------------------* + * LSF Quantization + * A[z] calculation + *-----------------------------------------------------------------*/ + + /* SC-VBR & channel-aware mode - back-up memories for LSF quantizer and synthesis filter */ + lsf_syn_mem_backup( 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 ); + + if ( !tdm_lp_reuse_flag ) + { + lsf_enc( st, lsf_new, lsp_new, lsp_mid, Aq, tdm_low_rate_mode, st->GSC_IVAS_mode, tdm_lsfQ_PCh ); + } + else + { + const float *pt_interp_2; + + if ( st->active_cnt != 1 ) + { + int16_t beta_index; + float lsf_wgts[M]; + + /* intra_frame prediction for the LSFs */ + lsp2lsf( lsp_new, lsf_new, M, 12800 ); + + Unified_weighting( &st->Bin_E[L_FFT / 2], lsf_new, lsf_wgts, st->bwidth == NB, st->coder_type == UNVOICED, st->sr_core, M ); + + tdm_SCh_lsf_reuse( ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index ); + + push_indice( hBstr, IND_IC_LSF_PRED, beta_index, TDM_IC_LSF_PRED_BITS ); + } + + pt_interp_2 = interpol_frac_12k8; + if ( tdm_low_rate_mode == 1 && st->coder_type > UNVOICED ) + { + pt_interp_2 = interpol_frac2; + } + + if ( st->active_cnt == 1 ) + { + mvr2r( lsp_new, st->lsp_old, M ); + lsp2lsf( lsp_new, st->lsf_old, M, st->sr_core ); + lsp2lsf( lsp_new, lsf_new, M, st->sr_core ); + } + + /* LSP interpolation and conversion of LSPs to A(z) */ + int_lsp( st->L_frame, st->lsp_old, lsp_new, Aq, M, pt_interp_2, 0 ); + + /* Check LSF stability (distance between old LSFs and current LSFs) */ + st->stab_fac = lsf_stab( lsf_new, st->lsf_old, 0, st->L_frame ); + } + + if ( st->last_core == HQ_CORE && st->element_mode > EVS_MONO ) + { + /* Prepare ACB memory from last HQ frame */ + tmpF = hLPDmem->old_exc_flt[0]; + preemph( hLPDmem->old_exc_flt, st->preemph_fac_flt, st->L_frame, &tmpF ); + mvr2r( hLPDmem->old_exc_flt + st->L_frame - M, hLPDmem->mem_syn_flt, M ); + residu( Aq, M, hLPDmem->old_exc_flt, old_exc_flt, st->L_frame ); + } + + if ( st->last_core != ACELP_CORE && st->element_mode > EVS_MONO ) + { + /* Prepare ACB memory of old_bwe_exc */ + if ( st->L_frame == L_FRAME ) + { + lerp_flt( old_exc_flt, old_bwe_exc, L_EXC_MEM_DEC * HIBND_ACB_L_FAC, L_EXC_MEM_DEC ); + } + else + { + lerp_flt( old_exc_flt, old_bwe_exc, L_EXC_MEM_DEC * 2, L_EXC_MEM_DEC ); + } + } + + + /*---------------------------------------------------------------* + * Calculation of LP residual (filtering through A[z] filter) + *---------------------------------------------------------------*/ + + calc_residu( inp, res, Aq, st->L_frame ); + + calculate_hangover_attenuation_gain( st, &att, vad_hover_flag ); + if ( att != 1.0f ) + { + v_multc( res, att, res, st->L_frame ); + } + + /*-----------------------------------------------------------------* + * Determine TC subframe classification + *-----------------------------------------------------------------*/ + + if ( st->coder_type == TRANSITION ) + { + tc_classif_enc( st->L_frame, &tc_subfr, &position, attack_flag, st->pitch[0], res ); + + 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, 1, NULL, unbits, st->element_mode, &uc_two_stage_flag, tdm_lp_reuse_flag, tdm_low_rate_mode, st->idchan, st->active_cnt, tdm_Pitch_reuse_flag, st->tdm_LRTD_flag, st->GSC_IVAS_mode ); + } + + /*---------------------------------------------------------------* + * Calculation of prediction for scaled innovation energy + * (for memory-less gain quantizer) + *---------------------------------------------------------------*/ + + if ( nb_bits > 0 ) + { + Es_pred_enc( &Es_pred, &i, st->L_frame, L_SUBFR, res, st->voicing, nb_bits, uc_two_stage_flag ); + push_indice( hBstr, IND_ES_PRED, i, nb_bits ); + } + + /*------------------------------------------------------------* + * Encode excitation according to coding type + *------------------------------------------------------------*/ + + if ( tdm_low_rate_mode ) /* tdm stereo low rate mode */ + { + if ( st->coder_type <= UNVOICED ) + { + tdm_low_rate_enc( st, Aq, res, syn, exc, pitch_buf, voice_factors, bwe_exc, 0 /*attack_flag*/, lsf_new, &tmp_noise ); + } + else /* GENERIC */ + { + encod_gen_2sbfr( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + } + else if ( nelp_mode ) + { + /* SC-VBR - NELP frames */ + encod_nelp( st, inp, Aw, Aq, res, syn, &tmp_noise, exc, exc2, pitch_buf, voice_factors, bwe_exc ); + } + else if ( st->coder_type == UNVOICED ) + { + /* UNVOICED frames (Gauss. excitation) */ + encod_unvoiced( st, inp, Aw, Aq, Es_pred, uc_two_stage_flag, res, syn, &tmp_noise, exc, pitch_buf, voice_factors, bwe_exc ); + } + else if ( st->coder_type == TRANSITION ) + { + encod_tran( st, inp, Aw, Aq, Es_pred, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, tc_subfr, position, unbits ); + } + else if ( ppp_mode ) + { + /* SC-VBR - PPP frames */ + if ( ( error = encod_ppp( st, inp, Aw, Aq, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc ) ) != IVAS_ERR_OK ) + { + return error; + } + + + if ( st->hSC_VBR->bump_up ) /* PPP failed, bump up */ + { + /* restore memories of LSF quantizer and synthesis filter */ + 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 ); + + /* 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 ); + + /* redo LSF quantization */ + lsf_enc( st, lsf_new, lsp_new, lsp_mid, Aq, tdm_low_rate_mode, 0, NULL ); + + /* recalculation of LP residual (filtering through A[z] filter) */ + calc_residu( inp, res, Aq, st->L_frame ); + st->hTdCngEnc->burst_ho_cnt = 0; + + /* VOICED frames in SC-VBR */ + encod_gen_voic( st, inp, Aw, Aq, Es_pred, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, unbits, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + } + else if ( st->coder_type == AUDIO || ( st->coder_type == INACTIVE && st->inactive_coder_type_flag ) ) + { + /* AUDIO and INACTIVE frames (coded by GSC technology) */ + encod_audio( st, inp, Aw, Aq, res, syn, exc, pitch_buf, voice_factors, bwe_exc, attack_flag, lsf_new, &tmp_noise, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + else + { + /* GENERIC, VOICED and INACTIVE frames (coded by AVQ technology) */ + encod_gen_voic( st, inp, Aw, Aq, Es_pred, res, syn, exc, exc2, pitch_buf, voice_factors, bwe_exc, unbits, tdm_Pitch_reuse_flag, tdm_Pri_pitch_buf ); + } + + + /* update mem_syn1_flt for ACELP core switching */ + mvr2r( hLPDmem->mem_syn_flt, hLPDmem->mem_syn1_flt, M ); + + /* update old synthesis buffer - needed for ACELP internal sampling rate switching */ + mvr2r( syn + st->L_frame - L_SYN_MEM, hLPDmem->mem_syn_r_flt, L_SYN_MEM ); + + /* save and delay synthesis to be used by SWB BWE */ + if ( st->hBWE_FD != NULL ) + { + save_old_syn( st->L_frame, syn, old_syn_12k8_16k, st->hBWE_FD->old_syn_12k8_16k, st->preemph_fac_flt, &st->hBWE_FD->mem_deemph_old_syn ); + } + + /*Update MODE2 core switching memory*/ + mvr2r( syn, syn1, st->L_frame ); + deemph( syn1, st->preemph_fac_flt, st->L_frame, &( hLPDmem->syn_flt[M] ) ); + mvr2r( syn1 + st->L_frame - M - 1, hLPDmem->syn_flt, M + 1 ); + + if ( st->element_mode > EVS_MONO && st->hTcxEnc != NULL ) + { + mvr2r( syn1 + st->L_frame / 2, st->hTcxEnc->Txnq_flt, st->L_frame / 2 ); + } + + /*--------------------------------------------------------------------------------------* + * Modify the excitation signal when the noise is stationary + *--------------------------------------------------------------------------------------*/ + + if ( !( st->idchan == 1 && st->element_mode == IVAS_CPE_TD ) && nelp_mode != 1 && !( st->element_mode == IVAS_SCE && tdm_low_rate_mode ) ) + { + /* exc2 buffer is needed only for updating of Aq[] which is needed for core switching */ + mvr2r( exc, exc2, st->L_frame ); + stat_noise_uv_enc( st, epsP, lsp_new, lsp_mid, Aq, exc2, uc_two_stage_flag ); + } + + /*-----------------------------------------------------------------* + * Encode supplementary information for Frame Error Concealment + *-----------------------------------------------------------------*/ + + FEC_encode( hBstr, st->acelp_cfg, syn, st->coder_type, st->clas, pitch_buf, res, &st->Last_pulse_pos, st->L_frame, st->total_brate ); /* SC-VBR temporary variables */ pstreaklen = 0; clip_var = 0; @@ -1429,9 +1824,30 @@ ivas_error acelp_core_enc( lsp2lsf( lsp_new, lsf_new, M, 12800 ); Unified_weighting( &st->Bin_E[L_FFT / 2], lsf_new, lsf_wgts, st->bwidth == NB, st->coder_type == UNVOICED, st->sr_core, M ); +#ifdef IVAS_FLOAT_FIXED + Word16 lsf_new_fx[M]; + Word16 lsp_new_fx[M]; + Word16 tdm_lsfQ_PCh_fx[M]; + Word16 lsf_wgts_fx[M]; + for ( int ii = 0; ii < M; ii++ ) + { + lsf_new_fx[ii] = (Word16) ( ( lsf_new[ii] ) * 2.56f ); + tdm_lsfQ_PCh_fx[ii] = (Word16) ( ( tdm_lsfQ_PCh[ii] ) * 2.56f ); + lsf_wgts_fx[ii] = (Word16) ( ( lsf_wgts[ii] ) * 2.56f ); + } + floatToFixed_arr( lsp_new, lsp_new_fx, 15, M ); - tdm_SCh_lsf_reuse( ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index ); + tdm_SCh_lsf_reuse_fx( ENC, st->element_brate, lsf_new_fx, lsp_new_fx, tdm_lsfQ_PCh_fx, lsf_wgts_fx, &beta_index ); + for ( int ii = 0; ii < M; ii++ ) + { + lsf_new[ii] = (Word16) ( ( lsf_new_fx[ii] ) / 2.56f ); + lsf_wgts[ii] = (Word16) ( ( lsf_wgts_fx[ii] ) / 2.56f ); + } + fixedToFloat_arr( lsp_new_fx, lsp_new, 15, M ); +#else + tdm_SCh_lsf_reuse( ENC, st->element_brate, lsf_new, lsp_new, tdm_lsfQ_PCh, lsf_wgts, &beta_index ); +#endif push_indice( hBstr, IND_IC_LSF_PRED, beta_index, TDM_IC_LSF_PRED_BITS ); } diff --git a/lib_enc/cng_enc.c b/lib_enc/cng_enc.c index 40e488c4ffda29361be00c249f6ceaa992299a59..7620f2c4416d0a57147bc93d6555a7c3c40e2ef9 100644 --- a/lib_enc/cng_enc.c +++ b/lib_enc/cng_enc.c @@ -43,6 +43,12 @@ #include "prot.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#include "prot_fx.h" +#include "ivas_rom_com_fx.h" +#endif + /*---------------------------------------------------------------------* * Local constants *---------------------------------------------------------------------*/ @@ -58,6 +64,11 @@ static int16_t shb_DTX( Encoder_State *st, const float *shb_speech, const float static void shb_CNG_encod( Encoder_State *st, const int16_t update ); +#ifdef IVAS_FLOAT_FIXED + +static Word16 shb_DTX_ivas_fx( Encoder_State *st, const Word16 *shb_speech_fx, const Word16 *syn_12k8_16k_fx ); +static void shb_CNG_encod_ivas_fx( Encoder_State *st, const Word16 update ); +#endif /*---------------------------------------------------------------------* * CNG_enc() @@ -894,6 +905,52 @@ void swb_CNG_enc( return; } +#ifdef IVAS_FLOAT_FIXED +void swb_CNG_enc_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q0 */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz Q0 */ +) +{ + Word16 shb_SID_updt; + + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) || st->core_brate == FRAME_NO_DATA ) + { + IF( st->cng_type == LP_CNG ) + { + test(); + IF( GE_32( st->input_Fs, L_FRAME32k * FRAMES_PER_SEC ) ) + { + /* decide if SHB SID encoding or not */ + shb_SID_updt = shb_DTX_ivas_fx( st, shb_speech_fx, syn_12k8_16k_fx ); + + /* SHB CNG encoding */ + shb_CNG_encod_ivas_fx( st, shb_SID_updt ); + } + ELSE IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) && EQ_32( st->core_brate, SID_2k40 ) ) + { + /* LF-boost not used in DFT-stereo, instead the bandwidth is transmitted */ + delete_indice( st->hBstr, IND_CNG_ENV1 ); + push_indice( st->hBstr, IND_BWIDTH, st->bwidth, 2 ); + push_indice( st->hBstr, IND_UNUSED, 0, 4 ); + push_indice( st->hBstr, IND_SID_BW, 1, 1 ); + } + } + st->hTdCngEnc->last_vad = 0; + move16(); + } + ELSE + { + st->hTdCngEnc->last_vad = 1; + move16(); + } + + return; +} + +#endif + /*---------------------------------------------------------------------* * shb_CNG_encod() * @@ -975,6 +1032,121 @@ static void shb_CNG_encod( return; } +#ifdef IVAS_FLOAT_FIXED +static void shb_CNG_encod_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 update /* i : SID update flag */ +) +{ + Word16 idx_ener = 0; + move16(); + BSTR_ENC_HANDLE hBstr = st->hBstr; + + Word16 ener_mid_dec_thr_fx; + + IF( EQ_16( update, 1 ) ) + { + IF( st->element_mode == EVS_MONO ) + { + /* 6.0 in Q8 -> 1510 */ + /* 0.9 in Q15 29491 */ + /* ( 1 / log10(2.0) ) * 0.1 in Q15 ->10886 */ + idx_ener = shr( mult( add( mult( st->hTdCngEnc->mov_shb_cng_ener_fx, 10886 ), 1510 ), 29491 ), 8 ); /* Q0 */ + } + ELSE + { + /*idx_ener = (int16_t)(0.7f * (0.1f * st->hTdCngEnc->mov_shb_cng_ener / (float)log10(2.0f) + 6.0f) + 0.5f);*/ + // PMT("shb_CNG_encod_fx quantization in missing") + /* 6.0 in Q8 -> 1510 */ + /* 0.7 in Q15 22938 */ + /* ( 1 / log10(2.0) ) * 0.1 in Q15 -> 10886 */ + idx_ener = shr( mult( add( mult( st->hTdCngEnc->mov_shb_cng_ener_fx, 10886 ), 1510 ), 22938 ), 8 ); /* Q0 */ + } + + + if ( LT_16( st->bwidth, SWB ) ) + { + idx_ener = 0; + move16(); + } + + IF( GT_16( idx_ener, 15 ) ) + { + idx_ener = 15; + move16(); + } + ELSE IF( idx_ener < 0 ) + { + idx_ener = 0; + move16(); + } + + /* prevent toggling of idx_ener by adding small dead-zone interval around decision thresholds */ + IF( st->element_mode != EVS_MONO ) + { + IF( EQ_16( abs_s( sub( idx_ener, st->hTdCngEnc->last_idx_ener ) ), 1 ) ) + { + + Word16 tmp, tmp1, tmp2, scale, exp1, exp2, ener_mid_dec_thr_e; + tmp = BASOP_Util_Divide1616_Scale( st->hTdCngEnc->last_idx_ener, 22938, &scale ); // 0.7 in Q15 ->exp 0 + scale = scale + ( 15 - 0 ); + tmp = sub( tmp, shl( 6, sub( Q15, scale ) ) ); + tmp1 = BASOP_Util_Divide1616_Scale( tmp, 3277, &exp1 ); + exp1 = exp1 + ( scale - 0 ); + + ener_mid_dec_thr_fx = shr( mult( tmp1, 9864 ), 1 ); // exp = exp + + tmp = BASOP_Util_Divide1616_Scale( idx_ener, 22938, &scale ); // 0.7 in Q15 ->exp 0 + scale = add( scale, ( 15 - 0 ) ); + tmp = sub( tmp, shl( 6, sub( Q15, scale ) ) ); + tmp1 = BASOP_Util_Divide1616_Scale( tmp, 3277, &exp2 ); + exp2 = add( exp2, ( scale - 0 ) ); + + tmp2 = shr( mult( tmp1, 9864 ), 1 ); // exp = exp + + ener_mid_dec_thr_e = BASOP_Util_Add_MantExp( tmp2, exp2, ener_mid_dec_thr_fx, exp1, &ener_mid_dec_thr_fx ); + + + scale = BASOP_Util_Add_MantExp( st->hTdCngEnc->mov_shb_cng_ener_fx, 7, negate( ener_mid_dec_thr_fx ), ener_mid_dec_thr_e, &tmp ); + tmp1 = BASOP_Util_Divide1616_Scale( tmp, ener_mid_dec_thr_fx, &exp1 ); + exp1 = add( exp1, sub( scale, ener_mid_dec_thr_e ) ); + IF( LT_16( abs_s( tmp1 ), shr( 328, sub( 15, exp1 ) ) ) ) + { + idx_ener = st->hTdCngEnc->last_idx_ener; + move16(); + } + } + } + + st->hTdCngEnc->last_idx_ener = idx_ener; + move16(); + + push_indice( hBstr, IND_SHB_CNG_GAIN, idx_ener, 4 ); + push_indice( hBstr, IND_SID_BW, 1, 1 ); + delete_indice( hBstr, IND_CNG_ENV1 ); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + push_indice( st->hBstr, IND_BWIDTH, st->bwidth, 2 ); + } + ELSE + { + push_indice( hBstr, IND_UNUSED, 0, 2 ); + } + st->hTdCngEnc->ho_sid_bw = L_shl( L_and( st->hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1 ); + st->hTdCngEnc->ho_sid_bw = L_or( st->hTdCngEnc->ho_sid_bw, 0x1L ); + move32(); + move32(); + } + ELSE IF( EQ_32( st->core_brate, SID_2k40 ) ) + { + st->hTdCngEnc->ho_sid_bw = L_shl( L_and( st->hTdCngEnc->ho_sid_bw, (Word32) 0x3fffffffL ), 1 ); + move32(); + push_indice( hBstr, IND_SID_BW, 0, 1 ); + } + + return; +} +#endif /*---------------------------------------------------------------------* * shb_DTX() @@ -1113,6 +1285,221 @@ static int16_t shb_DTX( return ( update ); } +#ifdef IVAS_FLOAT_FIXED +static Word16 shb_DTX_ivas_fx( + Encoder_State *st, /* i/o: State structure */ + const Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q0 */ + const Word16 *syn_12k8_16k_fx /* i : ACELP core synthesis at 12.8kHz or 16kHz Q0 */ +) +{ + Word16 i; + Word16 update; + + Word16 allow_cn_step = 0; + move16(); + Word16 shb_old_speech_fx[( ACELP_LOOK_12k8 + L_SUBFR + L_FRAME ) * 5 / 4]; + Word16 *shb_new_speech_fx; + Word32 wb_ener_fx; + Word32 shb_ener_fx; + Word16 log_wb_ener_fx; + Word16 log_shb_ener_fx; + Word16 tmp; + Word16 exp; + Word16 fra; + Word16 att_fx; /*Q8*/ + + TD_CNG_ENC_HANDLE hTdCngEnc = st->hTdCngEnc; + TD_BWE_ENC_HANDLE hBWE_TD = st->hBWE_TD; + + +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move16(); +#endif + + shb_new_speech_fx = shb_old_speech_fx + ( ACELP_LOOK_12k8 + L_SUBFR ) * 5 / 4; + Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, ( ACELP_LOOK_12k8 + L_SUBFR ) * 5 / 4 ); // old_speech_shb_fx -> Q0 + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); // Q0 + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, ( ACELP_LOOK_12k8 + L_SUBFR ) * 5 / 4 ); // Q0 + + shb_ener_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME16k; i++ ) + { +#ifdef BASOP_NOGLOB + shb_ener_fx = L_mac_sat( shb_ener_fx, shb_old_speech_fx[i], shb_old_speech_fx[i] ); // ( Q0 + Q0 + Q1 ) --> Q1 due to left shift in L_mac +#else + shb_ener_fx = L_mac( shb_ener_fx, shb_old_speech_fx[i], shb_old_speech_fx[i] ); +#endif + } + + shb_ener_fx = L_add( Mpy_32_16_1( shb_ener_fx, 102 ), 1 ); /* ( 1 / L_FRAME16K ) -> 102 in Q15, shb_ener_fx in Q1 */ + + wb_ener_fx = L_deposit_l( 0 ); + FOR( i = 0; i < st->L_frame; i++ ) + { +#ifdef BASOP_NOGLOB + wb_ener_fx = L_mac_o( wb_ener_fx, syn_12k8_16k_fx[i], syn_12k8_16k_fx[i], &Overflow ); // ( Q0 + Q0 + Q1 ) --> Q1 due to left shift in L_mac +#else + wb_ener_fx = L_mac( wb_ener_fx, syn_12k8_16k[i], syn_12k8_16k[i] ); +#endif + } + + wb_ener_fx = L_add( Mpy_32_16_1( wb_ener_fx, 128 ), 1 ); /* 128 in Q15, wb_ener_fx in Q1 */ + + exp = norm_l( wb_ener_fx ); + fra = Log2_norm_lc( L_shl( wb_ener_fx, exp ) ); + exp = sub( 30 - 1, exp ); + wb_ener_fx = Mpy_32_16( exp, fra, LG10 ); + +#ifdef BASOP_NOGLOB + log_wb_ener_fx = round_fx_o( L_shl_o( wb_ener_fx, 10, &Overflow ), &Overflow ); /* log_wb_ener_fx in Q8 */ +#else + log_wb_ener_fx = round_fx( L_shl( wb_ener_fx, 10 ) ); /* log_wb_ener_fx in Q8 */ +#endif + exp = norm_l( shb_ener_fx ); + fra = Log2_norm_lc( L_shl( shb_ener_fx, exp ) ); + exp = sub( 30 - 1, exp ); + shb_ener_fx = Mpy_32_16( exp, fra, LG10 ); + + + test(); + IF( EQ_16( st->element_mode, IVAS_SCE ) || EQ_16( st->element_mode, IVAS_CPE_DFT ) ) + { + Word32 att_fx32 = 0; + move32(); + Word16 index; + + apply_scale_ivas_fx( &att_fx32, st->hFdCngEnc->hFdCngCom->CngBandwidth, st->hFdCngEnc->hFdCngCom->CngBitrate, scaleTableStereo, SIZE_SCALE_TABLE_STEREO, &index ); // Q23; + + att_fx = extract_l( L_shr( att_fx32, 15 ) ); // Q8 + } + ELSE + { + att_fx = -1664; // Q8 + move16(); + } + + +#ifdef BASOP_NOGLOB + log_shb_ener_fx = sub_o( round_fx_o( L_shl_o( shb_ener_fx, 10, &Overflow ), &Overflow ), att_fx, &Overflow ); /* log_shb_ener_fx in Q8 */ +#else + log_shb_ener_fx = sub( round_fx( L_shl( shb_ener_fx, 10 ) ), att_fx ); /* log_shb_ener_fx in Q8 */ +#endif + + IF( st->hDtxEnc->first_CNG == 0 ) + { + + + hTdCngEnc->mov_wb_cng_ener_fx = log_wb_ener_fx; // Q8 + hTdCngEnc->mov_shb_cng_ener_fx = log_shb_ener_fx; // Q8 + hTdCngEnc->last_wb_cng_ener_fx = log_wb_ener_fx; // Q8 + hTdCngEnc->last_shb_cng_ener_fx = log_shb_ener_fx; // Q8 + move16(); + move16(); + move16(); + move16(); + } + IF( GT_16( abs_s( sub( log_wb_ener_fx, hTdCngEnc->mov_wb_cng_ener_fx ) ), 3072 ) ) // 12 in Q8 + { + allow_cn_step = 1; + move16(); + } + + /* Also allow step if shb energy has dropped 12 dB */ + test(); + test(); + IF( ( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && GT_16( sub( hTdCngEnc->mov_shb_cng_ener_fx, log_shb_ener_fx ), 3072 ) ) + { + allow_cn_step = 1; + move16(); + } + + IF( EQ_16( allow_cn_step, 1 ) ) + { + hTdCngEnc->mov_wb_cng_ener_fx = log_wb_ener_fx; + hTdCngEnc->mov_shb_cng_ener_fx = log_shb_ener_fx; + } + ELSE + { + tmp = sub( log_wb_ener_fx, hTdCngEnc->mov_wb_cng_ener_fx ); /* Q8 */ + tmp = mult( tmp, 29491 ); /* Q8 */ + hTdCngEnc->mov_wb_cng_ener_fx = add( hTdCngEnc->mov_wb_cng_ener_fx, tmp ); /* Q8 */ + + tmp = sub( log_shb_ener_fx, hTdCngEnc->mov_shb_cng_ener_fx ); + tmp = mult( tmp, 8192 ); /* Q8 */ + hTdCngEnc->mov_shb_cng_ener_fx = add( hTdCngEnc->mov_shb_cng_ener_fx, tmp ); /* Q8 */ + } + + hTdCngEnc->shb_NO_DATA_cnt = add( hTdCngEnc->shb_NO_DATA_cnt, 1 ); + update = 0; + + move16(); + move16(); + + test(); + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) ) + { + IF( st->hDtxEnc->first_CNG == 0 ) + { + update = 1; + move16(); + } + ELSE IF( hTdCngEnc->shb_cng_ini_cnt > 0 ) + { + hTdCngEnc->shb_cng_ini_cnt = sub( hTdCngEnc->shb_cng_ini_cnt, 1 ); + update = 1; + move16(); + move16(); + } + ELSE IF( EQ_16( hTdCngEnc->last_vad, 1 ) ) + { + update = 1; + move16(); + } + ELSE IF( GE_16( hTdCngEnc->shb_NO_DATA_cnt, 100 ) ) + { + update = 1; + move16(); + } + ELSE IF( GT_16( abs_s( sub( sub( hTdCngEnc->mov_wb_cng_ener_fx, hTdCngEnc->mov_shb_cng_ener_fx ), sub( hTdCngEnc->last_wb_cng_ener_fx, hTdCngEnc->last_shb_cng_ener_fx ) ) ), 768 ) ) + { + update = 1; + move16(); + } + ELSE IF( ( GE_16( st->bwidth, SWB ) && LT_16( hTdCngEnc->last_SID_bwidth, SWB ) ) || ( LT_16( st->bwidth, SWB ) && GE_16( hTdCngEnc->last_SID_bwidth, SWB ) ) ) + { + update = 1; + move16(); + } + + hTdCngEnc->last_SID_bwidth = st->bwidth; + move16(); + } + + /* LF-boost not yet implemented in decoder which means that the specific wb_sid information is not used */ + test(); + test(); + if ( ( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) && EQ_32( st->core_brate, SID_2k40 ) ) + { + update = 1; + move16(); + } + + IF( EQ_16( update, 1 ) ) + { + hTdCngEnc->last_wb_cng_ener_fx = hTdCngEnc->mov_wb_cng_ener_fx; + hTdCngEnc->last_shb_cng_ener_fx = hTdCngEnc->mov_shb_cng_ener_fx; + hTdCngEnc->shb_NO_DATA_cnt = 0; + move16(); + move16(); + move16(); + } + + test(); + return ( update ); +} +#endif /*---------------------------------------------------------------------* * calculate_hangover_attenuation_gain() diff --git a/lib_enc/cod_tcx_fx.c b/lib_enc/cod_tcx_fx.c index a1282c7e9867030dd2518104cf26cbae72f9ce19..a364eea68cea150fcf254164475d6692a62bb1c3 100644 --- a/lib_enc/cod_tcx_fx.c +++ b/lib_enc/cod_tcx_fx.c @@ -18,6 +18,7 @@ #include "ivas_prot.h" #include "ivas_prot_fx.h" #include "ivas_rom_com_fx.h" +#include "prot.h" #endif #ifdef DEBUGGING #include "debug.h" @@ -1046,6 +1047,268 @@ void ShapeSpectrum_fx( PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e ); } } +#ifdef IVAS_FLOAT_FIXED +void ShapeSpectrum_ivas_fx( + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 A[], /* input: quantized coefficients NxAz_q[M+1], Q = 14 - norm(A[0]) */ + Word16 gainlpc[], /* output: MDCT gains for the previous frame */ + Word16 gainlpc_e[], /* output: MDCT gains exponents */ + Word16 L_frame_glob, /* input: frame length */ + Word16 L_spec, + Word32 spectrum[], /* i/o: MDCT spectrum */ + Word16 *spectrum_e, /* i/o: MDCT spectrum exponent */ + Word8 pfUseTns, /* output: Flag indicating if TNS is used */ + Encoder_State *st, + Word32 *scf /* Q16 */ +) +{ + Word16 L_frame; + Word16 Ap[M + 2]; + Word16 gamma1; + Word16 gainlpc_noinv[FDNS_NPTS]; + Word16 gainlpc_noinv_e[FDNS_NPTS]; + Word32 sns_int_scf[FDNS_NPTS]; + Word16 i; + Word16 q_spectrum; + Word32 max_low_pre = 0, max_high_pre = 0; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + move32(); + move32(); + + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + /* Init lengths */ + L_frame = L_frame_glob; + move16(); + gamma1 = st->gamma; + move16(); + if ( st->enableTcxLpc != 0 ) + { + gamma1 = 0x7FFF; + move16(); + } + + /* if past frame is ACELP */ + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) /* in MDCT, this is already done outside the function */ + { + IF( st->last_core == ACELP_CORE ) + { + L_frame = add( L_frame, hTcxCfg->tcx_offset ); + L_spec = add( L_spec, shr( hTcxCfg->tcx_coded_lines, 2 ) ); + IF( hTcxCfg->lfacNext < 0 ) + { + L_frame = sub( L_frame, hTcxCfg->lfacNext ); + move16(); + } + } + } + + test(); + tcxGetNoiseFillingTilt( A, + M, + L_frame, + ( GE_32( st->total_brate, ACELP_13k20 ) && st->rf_mode == 0 ), + &hTcxEnc->noiseTiltFactor ); + + /* Calculate Spectrum Flatness Measure for the TCX Concealment */ + IF( st->enablePlcWaveadjust ) + { + hTcxCfg->SFM2 = SFM_Cal_fx( spectrum, s_min( 200, L_frame ) ); + move32(); + } + + test(); + IF( LE_32( st->total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) ) + { + max_low_pre = 0; + move32(); + FOR( i = 0; i < L_frame; i++ ) + { + Word32 tmp = L_abs( spectrum[i] ); + if ( GT_32( tmp, max_low_pre ) ) + { + max_low_pre = tmp; + move32(); + } + } + + max_high_pre = 0; + move32(); + FOR( i = 0; i < L_spec - L_frame; i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame + i] ); + if ( GT_32( tmp, max_high_pre ) ) + { + max_high_pre = tmp; + move32(); + } + } + } + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + Word64 W_tmp; + q_spectrum = sub( 31, *spectrum_e ); + sns_interpolate_scalefactors_fx( &sns_int_scf[0], scf, ENC ); + sns_shape_spectrum_fx( spectrum, &q_spectrum, st->hTcxCfg->psychParamsCurrent, &sns_int_scf[0], Q16, L_frame, NULL ); + FOR( i = L_frame; i < L_spec - L_frame; i++ ) + { + W_tmp = W_mult0_32_32( spectrum[i], sns_int_scf[hTcxCfg->psychParamsCurrent->nBands - 1] ); + W_tmp = W_shr( W_tmp, Q16 ); + spectrum[i] = W_extract_l( W_tmp ); + move32(); + } + *spectrum_e = sub( 31, q_spectrum ); + move16(); + } + ELSE + { + /*-----------------------------------------------------------* + * Pre-shaping in frequency domain using weighted LPC (Wz) * + *-----------------------------------------------------------*/ + + weight_a_fx( A, Ap, gamma1, M ); + + lpc2mdct( Ap, M, gainlpc_noinv, gainlpc_noinv_e, gainlpc, gainlpc_e, FDNS_NPTS, 0 ); + + mdct_shaping( spectrum, L_frame, gainlpc_noinv, gainlpc_noinv_e ); + FOR( i = L_frame; i < L_spec; i++ ) + { + spectrum[i] = L_shl( Mpy_32_16_1( spectrum[i], gainlpc_noinv[FDNS_NPTS - 1] ), gainlpc_noinv_e[FDNS_NPTS - 1] ); + move32(); + } + } + + /* reduce the peaks in the IGF region, to make life of the core-coder easier... */ + test(); + IF( LE_32( st->total_brate, ACELP_13k20 ) && EQ_16( st->bwidth, SWB ) ) + { + Word16 sf_width; + Word16 dist_low, dist_high; + Word16 max_fac_s, max_fac_m; + Word32 max_low, max_low1, max_low2, max_high; + Word16 headroom, shift, tmp16; + + + max_fac_m = 24576; + move16(); + /* max_fac = 3 */ + max_fac_s = 2; + move16(); + if ( hTcxEnc->tcx_lpc_shaped_ari ) + { + /* max_fac = 1.5 */ + max_fac_s = 1; + move16(); + } + + sf_width = shr( L_frame, 1 ); + + max_low2 = 0; + move32(); + dist_low = 0; + move16(); + FOR( i = 0; i < sf_width; i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame - 1 - i] ); + IF( GT_32( tmp, max_low2 ) ) + { + max_low2 = tmp; + move32(); + dist_low = i; + move16(); + } + } + + max_low1 = 0; + move32(); + FOR( i = 0; i < sub( L_frame, sf_width ); i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame - sf_width - 1 - i] ); + if ( GT_32( tmp, max_low1 ) ) + { + max_low1 = tmp; + move32(); + } + IF( GT_32( tmp, max_low2 ) ) + { + dist_low = add( sf_width, i ); + } + } + + max_low = L_max( max_low1, max_low2 ); + + max_high = 0; + move32(); + dist_high = 0; + move16(); + FOR( i = 0; i < sub( L_spec, L_frame ); i++ ) + { + Word32 tmp = L_abs( spectrum[L_frame + i] ); + if ( GT_32( tmp, max_high ) ) + { + max_high = tmp; + move32(); + dist_high = i; + move16(); + } + } + + /* at least 9 bits headroom are needed for below multiplicitions */ + shift = 0; + move16(); + headroom = 31; + move16(); + + tmp16 = norm_l( max_low ); + if ( max_low != 0 ) + headroom = s_min( headroom, tmp16 ); + + tmp16 = norm_l( max_low2 ); + if ( max_low2 != 0 ) + headroom = s_min( headroom, tmp16 ); + + tmp16 = norm_l( max_high ); + if ( max_high != 0 ) + headroom = s_min( headroom, tmp16 ); + + if ( LT_16( headroom, 9 ) ) + { + shift = sub( 9, headroom ); + } + max_low = L_shr( max_low, shift ); + max_low2 = L_shr( max_low2, shift ); + max_high = L_shr( max_high, shift ); + + test(); + test(); + IF( GT_32( imult3216( max_high, dist_high ), imult3216( L_shr( max_low, 2 ), dist_low ) ) && ( GT_32( max_low_pre, L_shr( max_high_pre, 4 ) ) ) && ( GT_32( max_high, L_shl( Mpy_32_16_r( max_low2, max_fac_m ), max_fac_s ) ) ) ) + { + Word16 fac; + fac = divide3232( max_low2, max_high ); + fac = shl( mult_r( fac, max_fac_m ), max_fac_s ); + + FOR( i = 0; i < sub( L_spec, L_frame ); i++ ) + { + spectrum[L_frame + i] = Mpy_32_16_1( spectrum[L_frame + i], fac ); + move32(); + } + } + } + + + test(); + test(); + test(); + IF( st->tcxonly && hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !pfUseTns ) + { + PsychAdaptLowFreqEmph_fx( spectrum, gainlpc, gainlpc_e ); + } +} +#endif + #ifdef ADD_IVAS_TNS /*-----------------------------------------------------------* * EstimateStereoTCXNoiseLevel() @@ -1351,43 +1614,85 @@ void QuantizeSpectrum_ivas_fx( const int16_t vad_hover_flag /* i : VAD hangover flag */ ) { - int16_t L_frameTCX; /* full frame length */ - int16_t L_frame; /* frame length */ - int16_t L_spec; /* length of the coded spectrum */ - int16_t tcx_offset; /* folding point offset relative to the end of the previous frame */ - int16_t noiseFillingBorder; /* noise filling border */ - float quantized_spectrum[N_MAX]; /* quantized MDCT spectrum */ - Word32 quantized_spectrum_fx[N_MAX]; /* quantized MDCT spectrum */ - float lf_deemph_fact[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */ - int16_t hm_active; /* flag indicating if the harmonic model is active */ - float fac_ns; /* noise filling level */ - Word16 fac_ns_fx; /* noise filling level, Q15 */ - int16_t nf_seed; /* noise filling random seed */ - float ener; /* energy of the quantized spectrum */ - float gain_tcx; /* global gain */ - Word16 gain_tcx_fx; /* global gain */ - Word16 gain_tcx_e; /* global gain */ + int16_t L_frameTCX; /* full frame length */ + int16_t L_frame; /* frame length */ + int16_t L_spec; /* length of the coded spectrum */ + int16_t tcx_offset; /* folding point offset relative to the end of the previous frame */ + int16_t noiseFillingBorder; /* noise filling border */ + float quantized_spectrum[N_MAX]; /* quantized MDCT spectrum */ + Word32 quantized_spectrum_fx[N_MAX]; /* quantized MDCT spectrum */ + Word16 quantized_spectrum_e; /* quantized MDCT spectrum */ + float lf_deemph_fact[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */ + Word16 lf_deemph_fact_fx[L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX]; /* low frequency deemphasis factors */ + int16_t hm_active; /* flag indicating if the harmonic model is active */ + float fac_ns; /* noise filling level */ + Word16 fac_ns_fx; /* noise filling level, Q15 */ + int16_t nf_seed; /* noise filling random seed */ + float ener; /* energy of the quantized spectrum */ + Word32 ener_fx; /* energy of the quantized spectrum */ + Word16 ener_e; /* energy of the quantized spectrum */ + float gain_tcx; /* global gain */ + Word16 gain_tcx_fx; /* global gain */ + Word16 gain_tcx_e; /* global gain */ TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; /*-----------------------------------------------------------* * Quantize the MDCT spectrum * *-----------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 gainlpc_fx[FDNS_NPTS]; + Word16 gainlpc_e[FDNS_NPTS]; + st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); + floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); + st->hTcxEnc->spectrum_e[1] = st->hTcxEnc->spectrum_e[0]; + hTcxEnc->tcxltp_gain = float_to_fix16( hTcxEnc->tcxltp_gain_flt, Q15 ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + hTcxEnc->tcx_target_bits_fac = float_to_fix16( hTcxEnc->tcx_target_bits_fac_flt, Q14 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + if ( gainlpc ) + { + Word16 x, y; + for ( int ii = 0; ii < FDNS_NPTS; ii++ ) + { + f2me_16( gainlpc[ii], &x, &y ); + gainlpc_fx[ii] = x; + gainlpc_e[ii] = y; + } + } + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + } +#endif +#ifdef IVAS_FLOAT_FIXED + QuantizeTCXSpectrum_fx( st, frame_cnt, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], gainlpc_fx, gainlpc_e, Aqind, tnsSize, nb_bits, vad_hover_flag, + &L_frameTCX, &L_frame, &L_spec, &tcx_offset, &noiseFillingBorder, quantized_spectrum_fx, &quantized_spectrum_e, hm_cfg, &hm_active, lf_deemph_fact_fx, &nf_seed, &ener_fx, &ener_e, &gain_tcx_fx, &gain_tcx_e, prm ); +#else QuantizeTCXSpectrum( st, frame_cnt, hTcxEnc->spectrum[frame_cnt], gainlpc, Aqind, tnsSize, nb_bits, vad_hover_flag, &L_frameTCX, &L_frame, &L_spec, &tcx_offset, &noiseFillingBorder, quantized_spectrum, hm_cfg, &hm_active, lf_deemph_fact, &nf_seed, &ener, &gain_tcx, prm ); - +#endif +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + gain_tcx = me2f_16( gain_tcx_fx, gain_tcx_e ); + ener = me2f( ener_fx, ener_e ); + hTcxEnc->tcx_target_bits_fac_flt = me2f_16( hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); + fixedToFloat_arrL( quantized_spectrum_fx, quantized_spectrum, 31 - quantized_spectrum_e, L_spec ); + if ( lf_deemph_fact != NULL ) + { + fixedToFloat_arr( lf_deemph_fact_fx, lf_deemph_fact, Q14, L_MDCT_OVLP_MAX + L_FRAME_PLUS + L_MDCT_OVLP_MAX ); + } +#endif /*-----------------------------------------------------------* * Estimate and quantize noise factor * *-----------------------------------------------------------*/ #ifdef IVAS_FLOAT_FIXED_CONVERSIONS st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); st->hTcxEnc->tcxltp_gain = float_to_fix16( st->hTcxEnc->tcxltp_gain_flt, Q15 ); - st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q14 ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); floatToFixed_arrL( quantized_spectrum, quantized_spectrum_fx, 31 - st->hTcxEnc->spectrum_e[0], L_frame ); - gain_tcx_e = 15 - ( Q_factor( gain_tcx ) ); - gain_tcx_fx = float_to_fix16( gain_tcx, 15 - gain_tcx_e ); + f2me_16( gain_tcx, &gain_tcx_fx, &gain_tcx_e ); #endif EstimateTCXNoiseLevel_ivas_fx( st, hTcxEnc->spectrum_fx[frame_cnt], hTcxEnc->spectrum_e[frame_cnt], quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, &fac_ns_fx, &prm[1] ); @@ -3193,8 +3498,895 @@ void QuantizeSpectrum_fx( move16(); } +#ifdef IVAS_FLOAT_FIXED +static Word16 DecideTonalSideInfo_fx( + Word32 spectrum[], // Qx + const Word16 L_frame_glob, + Word32 SFM2 ) +{ + Word32 SFM, K, K2; + Word16 Tonal_SideInfo; -void coder_tcx_fx( + SFM = SFM_Cal_fx( spectrum, s_min( 200, L_frame_glob ) ); + test(); + IF( LE_16( L_frame_glob, 256 ) ) + { + K = 0x33333333; + move32(); + K2 = 0xCCCCCCD; + move32(); + } + ELSE IF( EQ_16( L_frame_glob, 320 ) || EQ_16( L_frame_glob, 512 ) ) + { + K = 0x33333333; + move32(); + K2 = 0xCCCCCCD; + move32(); + } + ELSE /*FrameSize_Core == 640*/ + { + K = 0x2CCCCCCD; + move32(); + K2 = 0x51EB852; + move32(); + } + + + Tonal_SideInfo = 0; + move16(); + if ( LT_32( SFM, K ) ) + { + Tonal_SideInfo = 1; + move16(); + } + if ( LT_32( SFM2, K2 ) ) + { + Tonal_SideInfo = 1; + move16(); + } + + return Tonal_SideInfo; +} +#endif + +#ifdef IVAS_FLOAT_FIXED +void QuantizeTCXSpectrum_fx( + Encoder_State *st, /* i : state handle */ + const Word16 frame_cnt, /* i : frame counter in the super_frame Q0 */ + Word32 *x_orig_fx, /* i : shaped MDCT spectrum */ + const Word16 x_orig_e, /* i : exp of shaped MDCT spectrum */ + Word16 *gainlpc_fx, /* i : FDNS gains */ + Word16 *gainlpc_e, /* i : exp of FDNS gains */ + const Word16 *Aqind, /* i : frame-independent quantized coefficients (M+1) Q0 */ + const Word16 tnsSize, /* i : number of tns parameters put into prm Q0 */ + const Word16 nb_bits, /* i : bit budget Q0 */ + const Word16 vad_hover_flag, /* i : VAD hangover flag Q0 */ + Word16 *pL_frameTCX, /* o : full frame length Q0 */ + Word16 *pL_frame, /* o : frame length Q0 */ + Word16 *pL_spec, /* o : length of the coded spectrum Q0 */ + Word16 *ptcx_offset, /* o : folding point offset relative to the end of the previous frame Q0 */ + Word16 *pnoiseFillingBorder, /* o : noise filling border Q0 */ + Word32 spectrum_fx[], /* o : quantized MDCT spectrum */ + Word16 *spectrum_e, /* o : exp of quantized MDCT spectrum */ + CONTEXT_HM_CONFIG *hm_cfg, /* o : Context-based harmonic model configuration */ + Word16 *hm_active, /* o : flag indicating if the harmonic model is active */ + Word16 lf_deemph_fact_fx[], /* o : low frequency deemphasis factors Q14*/ + Word16 *nf_seed, /* o : noise filling random seed Q0*/ + Word32 *ener_fx, /* o : energy of the quantized spectrum */ + Word16 *ener_e, /* o : exp of energy of the quantized spectrum */ + Word16 *gain_tcx_fx, /* o : global gain */ + Word16 *gain_tcx_e, /* o : exp of global gain */ + Word16 prm[] /* o : tcx parameters Q0 */ +) +{ + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + Word16 i, L_frame, L_frameTCX, L_spec, tcx_offset; + Word16 noiseFillingBorder, LtpPitchLag, PeriodicityIndex; + Word16 lastnzCtxHm, lastnz; + Word16 stop; + Word16 nEncodedCtxHm, stopCtxHm, sqBitsCtxHm, Selector; + Word16 nEncoded, sqBits_noStop; + Word16 NumIndexBits, signaling_bits, sqTargetBits, sqBits, ctxHmBits, resQBits, resQTargetBits; + Word16 *prm_ltp, *prm_tns, *prm_hm, *prm_lastnz, *sqQ, *prm_target; + Word32 total_brate, tmp32; + Word16 RelativeScore_fx, sqGain_fx, sqGain_e, gain_tcx_opt_fx, gain_tcx_opt_e; + Word16 tmp1, tmp2, max_iter, minSqGain; + CONTEXT_HM_CONFIG *phm_cfg; + Word16 att_fx = 0; + move16(); +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move16(); + Flag Carry = 0; + move16(); +#endif + /*-----------------------------------------------------------* + * Init * + *-----------------------------------------------------------*/ + + sqGain_fx = MAX_16; + move16(); + sqGain_e = 0; + move16(); + minSqGain = 0; + move16(); + resQTargetBits = 0; + move16(); + + NumIndexBits = 0; + move16(); + sqBits = 0; + move16(); + ctxHmBits = 0; + move16(); + resQBits = 0; + move16(); + prm_ltp = &prm[1 + NOISE_FILL_RANGES]; + prm_tns = prm_ltp + LTPSIZE; + prm_hm = prm_tns + tnsSize; + prm_lastnz = prm_hm + 2; + sqQ = prm_hm + NPRM_CTX_HM; + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + total_brate = st->element_brate; + } + ELSE + { + total_brate = st->total_brate; + } + move32(); + /*-----------------------------------------------------------* + * Init lengths * + *-----------------------------------------------------------*/ + + /******************************************************************************************/ + + L_frame = st->L_frame; + move16(); + L_frameTCX = hTcxEnc->L_frameTCX; + move16(); + L_spec = st->hTcxCfg->tcx_coded_lines; + move16(); + tcx_offset = st->hTcxCfg->tcx_offset; + move16(); + + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + L_frame = shr( L_frame, 1 ); + L_frameTCX = shr( L_frameTCX, 1 ); + L_spec = shr( L_spec, 1 ); + } + ELSE IF( st->last_core == ACELP_CORE ) + { + st->hTcxCfg->last_aldo = 0; + move16(); + L_frame = add( L_frame, tcx_offset ); + L_frameTCX = add( L_frameTCX, st->hTcxCfg->tcx_offsetFB ); + L_spec = add( L_spec, shr( st->hTcxCfg->tcx_coded_lines, 2 ) ); + + IF( st->hTcxCfg->lfacNext < 0 ) + { + L_frame = sub( L_frame, st->hTcxCfg->lfacNext ); + L_frameTCX = sub( L_frameTCX, st->hTcxCfg->lfacNextFB ); + tcx_offset = st->hTcxCfg->lfacNext; + move16(); + } + ELSE + { + tcx_offset = 0; + move16(); + } + hTcxEnc->noiseLevelMemory_cnt = 0; + move16(); + } + + *pL_frameTCX = L_frameTCX; + move16(); + *pL_frame = L_frame; + move16(); + *pL_spec = L_spec; + move16(); + *ptcx_offset = tcx_offset; + move16(); + + /* target bitrate for SQ */ + sqTargetBits = sub( nb_bits, NBITS_TCX_GAIN + NBITS_NOISE_FILL_LEVEL ); + + IF( st->enablePlcWaveadjust ) + { + Word16 L_frame_glob; + IF( EQ_16( st->core, TCX_20_CORE ) ) + { + L_frame_glob = st->L_frame; + } + ELSE + { + L_frame_glob = shr( st->L_frame, 1 ); + } + move16(); + st->Tonal_SideInfo = DecideTonalSideInfo_fx( x_orig_fx, L_frame_glob, st->hTcxCfg->SFM2 ); + } + + /* Start with the pre-shaped spectrum*/ + Copy32( x_orig_fx, spectrum_fx, L_spec ); + *spectrum_e = x_orig_e; + move16(); + + /*-----------------------------------------------------------* + * Bandwidth Limitation * + *-----------------------------------------------------------*/ + + noiseFillingBorder = L_spec; + move16(); + IF( st->igf ) + { + noiseFillingBorder = st->hIGFEnc->infoStartLine; + move16(); + } + *pnoiseFillingBorder = noiseFillingBorder; + move16(); + + IF( st->igf ) + { + FOR( i = st->hIGFEnc->infoStopLine; i < s_max( L_frame, L_frameTCX ); i++ ) + { + spectrum_fx[i] = 0; + move32(); + } + } + ELSE + { + FOR( i = noiseFillingBorder; i < s_max( L_frame, L_frameTCX ); i++ ) + { + spectrum_fx[i] = 0; + move32(); + } + } + + /*-----------------------------------------------------------* + * Quantization * + *-----------------------------------------------------------*/ + + IF( !hTcxEnc->tcx_lpc_shaped_ari ) + { + /* context based arithmetic coder */ + + /* initialize signaling to default, i.e. context based AC is inactive */ + prm_hm[0] = 0; + move16(); + prm_hm[1] = -1; + move16(); + + /* Fast estimation of the scalar quantizer step size */ + test(); + IF( st->hTcxCfg->ctx_hm && ( st->last_core != ACELP_CORE ) ) + { + LtpPitchLag = -1; + move16(); + + test(); + IF( ( st->tcxonly == 0 ) && ( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) ) ) + { + tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 ); + tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr ); + LtpPitchLag = div_l( tmp32, tmp1 ); + } + + ctxHmBits = add( ctxHmBits, 1 ); /* ContextHM flag */ + sqTargetBits = sub( sqTargetBits, 1 ); /* ContextHM flag */ + + Word16 LtpGain; + IF( hTcxEnc->tcxltp ) + { + LtpGain = hTcxEnc->tcxltp_gain; + } + ELSE + { + LtpGain = -MAX_16; + } + move16(); + PeriodicityIndex = SearchPeriodicityIndex_fx( spectrum_fx, NULL, L_spec, sqTargetBits, LtpPitchLag, LtpGain, &RelativeScore_fx ); + + NumIndexBits = CountIndexBits_fx( (Word16) GE_16( L_spec, (Word16) 256 ), PeriodicityIndex ); + + IF( st->element_mode > EVS_MONO ) + { + ConfigureContextHm( L_spec, sub( sqTargetBits, NumIndexBits ), PeriodicityIndex, LtpPitchLag, hm_cfg ); + } + ELSE + { + ConfigureContextHm( L_spec, sqTargetBits, PeriodicityIndex, LtpPitchLag, hm_cfg ); + } + + /* Quantize original spectrum */ + sqGain_fx = SQ_gain_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e ); + + tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly ); + + /* Estimate original bitrate */ + stop = 0; + move16(); + IF( st->element_mode > EVS_MONO ) + { + sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL ); + } + ELSE + { + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnz, &nEncoded, sqTargetBits, &stop, NULL ); + } + + /* Estimate context mapped bitrate */ + stopCtxHm = 0; + move16(); + + /* Context Mapping */ + IF( st->element_mode > EVS_MONO ) + { + sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, 0, hm_cfg ); + } + ELSE + { + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg ); + } + + /* Decide whether or not to use context mapping */ + Selector = sub( s_max( stop, sqBits ), ( add( s_max( stopCtxHm, sqBitsCtxHm ), NumIndexBits ) ) ); + + test(); + test(); + IF( GT_16( Selector, 2 ) || ( LE_16( abs_s( Selector ), 2 ) && LT_16( kCtxHmOlRSThr, RelativeScore_fx ) ) ) + { + /* CtxHm is likely better */ + sqTargetBits = sub( sqTargetBits, NumIndexBits ); + ctxHmBits = add( ctxHmBits, NumIndexBits ); + prm_hm[0] = 1; + move16(); + prm_hm[1] = PeriodicityIndex; + move16(); + *prm_lastnz = lastnzCtxHm; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + ELSE + { + /* Original is better or not much difference */ + prm_hm[0] = 0; + move16(); + prm_hm[1] = PeriodicityIndex; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + + sqBits_noStop = sqBits; + move16(); + } + + if ( stop != 0 ) + { + sqBits = stop; + move16(); + } + } + ELSE + { + /* no context hm*/ + PeriodicityIndex = -1; + move16(); + + IF( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + sqGain_fx = SQ_gain_estimate_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e ); + } + ELSE + { + sqGain_fx = SQ_gain_fx( spectrum_fx, *spectrum_e, shl( mult( hTcxEnc->tcx_target_bits_fac, sqTargetBits ), 1 ), L_spec, &sqGain_e ); + } + /* Quantize spectrum */ + tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly ); + + /* Estimate bitrate */ + stop = 0; + move16(); + + IF( st->element_mode > EVS_MONO ) + { + sqBits_noStop = sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL ); + move16(); + } + ELSE + { + sqBits_noStop = sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, NULL ); + move16(); + } + + if ( stop != 0 ) + { + sqBits = stop; + move16(); + } + } /* end of if (ctx_hm) */ + + /* Adjust correction factor */ + tmp1 = sqBits; + move16(); + + if ( s_and( L_spec, sub( L_spec, 1 ) ) == 0 ) /* power-of-2 */ + { + tmp1 = add( tmp1, 1 ); + } + + tmp1 = BASOP_Util_Divide1616_Scale( sqTargetBits, tmp1, &tmp2 ); + BASOP_SATURATE_WARNING_OFF_EVS +#ifdef BASOP_NOGLOB + hTcxEnc->tcx_target_bits_fac = shl_o( mult( hTcxEnc->tcx_target_bits_fac, tmp1 ), tmp2, &Overflow ); +#else /* BASOP_NOGLOB */ + hTcxEnc->tcx_target_bits_fac = shl( mult( hTcxEnc->tcx_target_bits_fac, tmp1 ), tmp2 ); +#endif /* BASOP_NOGLOB */ + BASOP_SATURATE_WARNING_ON_EVS + + if ( GT_16( hTcxEnc->tcx_target_bits_fac, 20480 ) ) + { + hTcxEnc->tcx_target_bits_fac = 20480; + move16(); + } + if ( LT_16( hTcxEnc->tcx_target_bits_fac, 12288 ) ) + { + hTcxEnc->tcx_target_bits_fac = 12288; + move16(); + } + + /* Refine quantizer step size with a rate-control-loop (optional) */ + phm_cfg = NULL; + move16(); + if ( PeriodicityIndex >= 0 ) + { + phm_cfg = hm_cfg; + move16(); + } + + max_iter = 4; + move16(); + if ( EQ_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + max_iter = 2; + move16(); + } + sqBits = tcx_scalar_quantization_rateloop_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, &sqGain_fx, &sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, prm_lastnz, /* lastnz */ sqTargetBits, &nEncoded, &stop, sqBits_noStop, sqBits, st->hTcxCfg->tcxRateLoopOpt, st->tcxonly, phm_cfg, max_iter, st->element_mode ); + + IF( ctxHmBits > 0 ) + { + /* Mapping tool is enabled */ + /* Truncate spectrum */ + FOR( i = nEncoded; i < L_spec; i++ ) + { + IF( st->element_mode > EVS_MONO ) + { + break; + } + ELSE + { + sqQ[i] = 0; + move16(); + } + } + + IF( PeriodicityIndex >= 0 ) + { + /* Mapping is used */ + /* Estimate non-mapped bitrate */ + stopCtxHm = 1; + move16(); + IF( st->element_mode > EVS_MONO ) + { + /* Fix: Use updated value for target bits (sqTargetBits + NumIndexBits) before computing non-mapped estimate */ + sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits + NumIndexBits, &stopCtxHm, 0, NULL ); + } + ELSE + { + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnz, &nEncodedCtxHm, sqTargetBits, &stopCtxHm, NULL ); + } + + /* Decide whether or not to revert mapping */ + Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) ); + + IF( st->element_mode > EVS_MONO ) + { + test(); + test(); + IF( ( stopCtxHm == 0 && Selector > 0 ) || stop ) /* If overflow occured with mapped, select non-mapped */ + { + /* Non-mapped is better */ + sqTargetBits = add( sqTargetBits, NumIndexBits ); + ctxHmBits = sub( ctxHmBits, NumIndexBits ); + prm_hm[0] = 0; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + ELSE + { + test(); + IF( stopCtxHm == 0 && Selector > 0 ) + { + /* Non-mapped is better */ + sqTargetBits = add( sqTargetBits, NumIndexBits ); + ctxHmBits = sub( ctxHmBits, NumIndexBits ); + prm_hm[0] = 0; + move16(); + *prm_lastnz = lastnz; + move16(); + PeriodicityIndex = -1; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + } + ELSE + { + /* Mapping is not used */ + IF( st->element_mode > EVS_MONO ) + { + /* Truncate Spectrum */ + FOR( i = nEncoded; i < L_spec; i++ ) + { + sqQ[i] = 0; + move16(); + } + } + /* Estimate mapped bitrate */ + stopCtxHm = 1; + move16(); + IF( st->element_mode > EVS_MONO ) + { + sqBitsCtxHm = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, 0, hm_cfg ); + } + ELSE + { + sqBitsCtxHm = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, &lastnzCtxHm, &nEncodedCtxHm, sqTargetBits - NumIndexBits, &stopCtxHm, hm_cfg ); + } + + /* Decide whether or not to use mapping */ + Selector = sub( sqBits, add( sqBitsCtxHm, NumIndexBits ) ); + test(); + IF( stopCtxHm == 0 && Selector > 0 ) + { + /* Mapped is better */ + sqTargetBits = sub( sqTargetBits, NumIndexBits ); + ctxHmBits = add( ctxHmBits, NumIndexBits ); + prm_hm[0] = 1; + move16(); + *prm_lastnz = lastnzCtxHm; + move16(); + PeriodicityIndex = prm_hm[1]; + move16(); + sqBits_noStop = sqBits = sqBitsCtxHm; + move16(); + move16(); + nEncoded = nEncodedCtxHm; + move16(); + stop = stopCtxHm; + move16(); + } + } + } + + /* Limit low sqGain for avoiding saturation of the gain quantizer*/ + /*(float) sqrt( (float) NORM_MDCT_FACTOR / (float) L_spec ) in Q14 */ + SWITCH( L_spec ) + { + case 80: + minSqGain = 23170; + BREAK; + case 100: + minSqGain = 20724; + BREAK; + case 160: + minSqGain = 16384; + BREAK; + case 200: + minSqGain = 14654; + BREAK; + case 240: + minSqGain = 13377; + BREAK; + case 300: + minSqGain = 11965; + BREAK; + case 320: + minSqGain = 11585; + BREAK; + case 400: + minSqGain = 10362; + BREAK; + case 480: + minSqGain = 9459; + BREAK; + case 600: + minSqGain = 8461; + BREAK; + case 640: + minSqGain = 8192; + BREAK; + case 800: + minSqGain = 7327; + BREAK; + case 960: + minSqGain = 6689; + BREAK; + case 1200: + minSqGain = 5983; + BREAK; + case 1440: + minSqGain = 5461; + BREAK; + case 1800: + minSqGain = 4885; + BREAK; + case 2048: + minSqGain = 4579; + BREAK; + default: + assert( 0 ); + } + move16(); + Word16 shift_tmp = s_max( sqGain_e, 1 ); + test(); + IF( LT_16( st->hTcxCfg->tcxRateLoopOpt, 3 ) && LT_16( shl( sqGain_fx, sub( sqGain_e, shift_tmp ) ), shl( minSqGain, sub( 1, shift_tmp ) ) ) ) + { + sqGain_fx = minSqGain; + move16(); + sqGain_e = 1; + move16(); + + tcx_scalar_quantization_ivas_fx( spectrum_fx, *spectrum_e, sqQ, L_spec, sqGain_fx, sqGain_e, st->hTcxCfg->sq_rounding, hTcxEnc->memQuantZeros, st->tcxonly ); + stop = 1; + IF( st->element_mode > EVS_MONO ) + { + /* Ensure non-mapped estimation is used for limiting low sqGain considering that this refinement occurs very rarely */ + PeriodicityIndex = -1; + move16(); + IF( prm_hm[0] == 1 ) + { + prm_hm[0] = 0; + move16(); + sqTargetBits = add( sqTargetBits, NumIndexBits ); + ctxHmBits = sub( ctxHmBits, NumIndexBits ); + } + sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, 0, NULL ); + } + ELSE + { + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( sqQ, L_spec, prm_lastnz, &nEncoded, sqTargetBits, &stop, PeriodicityIndex >= 0 ? hm_cfg : NULL ); + } + } + + /* Truncate spectrum (for CBR) */ + IF( stop ) + { + FOR( i = nEncoded; i < L_spec; i++ ) + { + sqQ[i] = 0; + move16(); + } + } + + /* Save quantized Values */ + *nf_seed = 0; + move16(); + FOR( i = 0; i < L_spec; i++ ) + { + spectrum_fx[i] = (Word32) sqQ[i]; + /* noise filling seed */ + *nf_seed = (Word16) L_add( *nf_seed, L_mult0( abs_s( sqQ[i] ), shl( i, 1 ) ) ); + } + + tmp32 = L_deposit_l( 0 ); + FOR( i = 0; i < L_spec; i++ ) + { + spectrum_fx[i] = L_mult( sqQ[i], 1 << ( 30 - SPEC_EXP_DEC ) ); + move32(); + /* noise filling seed */ +#ifdef BASOP_NOGLOB + tmp32 = L_macNs_co( tmp32, abs_s( sqQ[i] ), i, &Carry, &Overflow ); +#else /* BASOP_NOGLOB */ + tmp32 = L_macNs( tmp32, abs_s( sqQ[i] ), i ); +#endif /* BASOP_NOGLOB */ + } + *spectrum_e = SPEC_EXP_DEC; + move16(); + + *nf_seed = extract_l( tmp32 ); + } + ELSE + { + /* low rates: envelope based arithmetic coder */ + + AdaptLowFreqEmph_fx( spectrum_fx, *spectrum_e, NULL, 0, 0, 1, gainlpc_fx, gainlpc_e, L_frame ); + + prm_target = sqQ; + sqQ = prm_target + 1; + + LtpPitchLag = -1; + move16(); + + IF( LT_16( hTcxEnc->tcxltp_pitch_int, st->L_frame ) ) + { + tmp32 = L_shl( L_mult0( st->L_frame, st->pit_res_max ), 1 + kLtpHmFractionalResolution + 1 ); + tmp1 = add( imult1616( hTcxEnc->tcxltp_pitch_int, st->pit_res_max ), hTcxEnc->tcxltp_pitch_fr ); + LtpPitchLag = div_l( tmp32, tmp1 ); + } + + Word8 tmp8 = 1; + move16(); + if ( ( st->last_core == ACELP_CORE ) ) + { + tmp8 = 0; + move16(); + } + Word16 low_complexiety = 0; + move16(); + if ( GT_16( st->bwidth, WB ) ) + { + low_complexiety = 1; + move16(); + } + tcx_arith_encode_envelope_fx( spectrum_fx, spectrum_e, hm_cfg->indexBuffer, L_frame, L_spec, st, Aqind, sqTargetBits, sqQ, tmp8, prm_hm, /* HM parameter area */ LtpPitchLag, &sqBits, &signaling_bits, nf_seed, low_complexiety ); + + sqTargetBits = sub( sqTargetBits, signaling_bits ); + *prm_target = sqTargetBits; + move16(); + + /* Noise filling seed */ + } + + *hm_active = prm_hm[0]; + move16(); + + /*-----------------------------------------------------------* + * Compute optimal TCX gain. * + *-----------------------------------------------------------*/ + + IF( lf_deemph_fact_fx != NULL ) + { + /* initialize LF deemphasis factors in lf_deemph_fact */ + FOR( i = 0; i < L_spec; i++ ) + { + lf_deemph_fact_fx[i] = ONE_IN_Q14; + move16(); + } + } + + IF( !st->tcxonly ) + { + AdaptLowFreqDeemph( spectrum_fx, *spectrum_e, hTcxEnc->tcx_lpc_shaped_ari, gainlpc_fx, gainlpc_e, L_frame, lf_deemph_fact_fx ); + } + + assert( x_orig_fx != spectrum_fx ); + + tcx_get_gain( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, &gain_tcx_opt_fx, &gain_tcx_opt_e, ener_fx, ener_e ); + + IF( gain_tcx_opt_fx <= 0 ) + { + gain_tcx_opt_fx = sqGain_fx; + move16(); + gain_tcx_opt_e = sqGain_e; + move16(); + } + *gain_tcx_fx = gain_tcx_opt_fx; + move16(); + *gain_tcx_e = gain_tcx_opt_e; + move16(); + + test(); + IF( EQ_16( st->element_mode, IVAS_CPE_DFT ) || EQ_16( st->element_mode, IVAS_CPE_TD ) ) + { + calculate_hangover_attenuation_gain_ivas_fx( st, &att_fx, vad_hover_flag ); + *gain_tcx_fx = mult( *gain_tcx_fx, att_fx ); + } + + /*-----------------------------------------------------------* + * Quantize TCX gain * + *-----------------------------------------------------------*/ + + /* gain quantization here in case of VBR unvoiced coding; fixes problems of uninitialized global gain values */ + test(); + IF( GE_32( total_brate, ACELP_13k20 ) && st->rf_mode == 0 ) + { + QuantizeGain( L_spec, gain_tcx_fx, gain_tcx_e, &prm[0] ); + } + + /*-----------------------------------------------------------* + * Residual Quantization * + *-----------------------------------------------------------*/ + + IF( st->hTcxCfg->resq ) + { + resQTargetBits = sub( sqTargetBits, sqBits ); + + IF( hTcxEnc->tcx_lpc_shaped_ari ) + { + /* envelope based arithmetic coder */ + Word16 *prm_resq; + + prm_resq = sqQ + sub( sqTargetBits, resQTargetBits ); + + resQBits = tcx_ari_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, hm_cfg->indexBuffer, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, prm_resq, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, lf_deemph_fact_fx ); + + /* Transmit zeros when there bits remain after RESQ */ + FOR( i = resQBits; i < resQTargetBits; ++i ) + { + prm_resq[i] = 0; + move16(); + } + } + ELSE + { + /* context based arithmetic coder */ + resQBits = tcx_res_Q_gain_fx( gain_tcx_opt_fx, gain_tcx_opt_e, gain_tcx_fx, gain_tcx_e, sqQ + L_spec, resQTargetBits ); + IF( st->tcxonly ) + { + resQBits = tcx_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, sqQ + L_spec, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, NULL ); + } + ELSE + { + resQBits = tcx_res_Q_spec_ivas_fx( x_orig_fx, x_orig_e, spectrum_fx, *spectrum_e, L_spec, *gain_tcx_fx, *gain_tcx_e, sqQ + L_spec, resQTargetBits, resQBits, st->hTcxCfg->sq_rounding, lf_deemph_fact_fx ); + } + } + } + + tmp1 = norm_s( *gain_tcx_fx ); + *gain_tcx_fx = shl( *gain_tcx_fx, tmp1 ); + move16(); + *gain_tcx_e = sub( *gain_tcx_e, tmp1 ); + move16(); + + /*-----------------------------------------------------------* + * ALFE tcx only bitrates * + *-----------------------------------------------------------*/ + + IF( NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + IF( st->tcxonly ) + { + test(); + test(); + IF( hTcxEnc->tcxltp && ( hTcxEnc->tcxltp_gain > 0 ) && !hTcxEnc->fUseTns[frame_cnt] ) + { + PsychAdaptLowFreqDeemph( spectrum_fx, gainlpc_fx, gainlpc_e, NULL ); + } + } + } + + return; +} +#endif + +void coder_tcx_fx( Word16 n, TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ Word16 A[], /* input: quantized coefficients NxAz_q[M+1] */ @@ -3425,3 +4617,30 @@ void coder_tcx_post_fx( return; } +#ifdef IVAS_FLOAT_FIXED +void coder_tcx_post_ivas_fx( + Encoder_State *st, + LPD_state *LPDmem, + TCX_CONFIG_HANDLE hTcxCfg, /* i : configuration of TCX */ + Word16 *synth, + const Word16 *A, + const Word16 *Ai, + Word16 *wsig, + Word16 Q_new ) +{ + Word16 xn_buf[L_FRAME_MAX]; + + /* TCX output */ + Copy( synth, xn_buf, st->L_frame ); + + + /*-----------------------------------------------------------* + * Memory update * + *-----------------------------------------------------------*/ + + /* Update LPDmem (Txnq,syn,syn_pe,old_exc,wsyn,Ai,Aq) */ + tcx_encoder_memory_update_ivas_fx( wsig, xn_buf, st->L_frame, Ai, A, hTcxCfg->preemph_fac, LPDmem, st, synth, Q_new ); + + return; +} +#endif diff --git a/lib_enc/core_enc_init.c b/lib_enc/core_enc_init.c index 98483e7f8cbcd5eefbc0a99cbae586932614fc0a..168c336b7ef9d32714e4af619451dd1d87dc80dc 100644 --- a/lib_enc/core_enc_init.c +++ b/lib_enc/core_enc_init.c @@ -1474,7 +1474,7 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh /*AMR-WBIO->MODE2*/ IF( EQ_16( st->last_core, AMR_WB_CORE ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->last_core = ACELP_CORE; move16(); @@ -1484,7 +1484,7 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh IF( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->last_core, HQ_CORE ) ) { /*Reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); @@ -1587,7 +1587,7 @@ static void init_acelp_ivas_fx( Encoder_State *st, Word16 L_frame_old, Word16 sh ELSE IF( ( NE_16( st->L_frame, L_frame_old ) ) ) { /*Partial reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); diff --git a/lib_enc/core_enc_init_fx.c b/lib_enc/core_enc_init_fx.c index 58657bb6b78f737852110fc86262ef8ab352ae90..06eb4fc5b798449b360eeea63ec5a496dc48b996 100644 --- a/lib_enc/core_enc_init_fx.c +++ b/lib_enc/core_enc_init_fx.c @@ -136,7 +136,7 @@ void init_coder_ace_plus_fx( } - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; move16(); test(); test(); @@ -639,7 +639,7 @@ static void init_acelp_fx( Encoder_State *st, Word16 L_frame_old, const Word16 s /*AMR-WBIO->MODE2*/ IF( EQ_16( st->last_core, AMR_WB_CORE ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->last_core = ACELP_CORE; move16(); @@ -649,7 +649,7 @@ static void init_acelp_fx( Encoder_State *st, Word16 L_frame_old, const Word16 s IF( EQ_16( st->last_codec_mode, MODE1 ) && EQ_16( st->last_core, HQ_CORE ) ) { /*Reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); @@ -740,7 +740,7 @@ static void init_acelp_fx( Encoder_State *st, Word16 L_frame_old, const Word16 s ELSE IF( ( NE_16( st->L_frame, L_frame_old ) ) ) { /*Partial reset of ACELP memories*/ - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); st->rate_switching_reset = 1; move16(); diff --git a/lib_enc/core_enc_ol.c b/lib_enc/core_enc_ol.c index 85c1c0b04ce03a0109f12d923ca54dc84961b96a..97ada614e79071ac7d96825d77f68570e6e8ead6 100644 --- a/lib_enc/core_enc_ol.c +++ b/lib_enc/core_enc_ol.c @@ -42,6 +42,9 @@ #include "rom_com.h" #include "basop_proto_func.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#endif /*-------------------------------------------------------------------* * Local function prototypes @@ -261,6 +264,9 @@ void core_encode_openloop( if ( st->last_core != ACELP_CORE ) { TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#ifdef IVAS_FLOAT_FIXED + TBEreset_enc_fx( st, st->bwidth ); +#endif } /* Run ACELP encoder */ diff --git a/lib_enc/core_enc_switch.c b/lib_enc/core_enc_switch.c index e5bf41ca4a85add9a0b79eeeaffabf4724bab242..6c0b66bb9123cc45acde7a1c3e55488e679bfa4c 100644 --- a/lib_enc/core_enc_switch.c +++ b/lib_enc/core_enc_switch.c @@ -39,8 +39,10 @@ #include "prot.h" #include "rom_com.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" #include "prot_fx_enc.h" +#endif /*-------------------------------------------------------------------* @@ -388,6 +390,9 @@ void core_coder_mode_switch( ( st->bwidth == FB && st->last_extl != FB_TBE ) ) { TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#ifdef IVAS_FLOAT_FIXED + TBEreset_enc_fx( st, st->bwidth ); +#endif } else { diff --git a/lib_enc/core_switching_enc.c b/lib_enc/core_switching_enc.c index 075868e79569c1f2ea3b279ff9732337186e1447..805f04b5e82a15793b9782bf3455499943944d13 100644 --- a/lib_enc/core_switching_enc.c +++ b/lib_enc/core_switching_enc.c @@ -42,12 +42,13 @@ #include "rom_com.h" #include "prot.h" #include "wmc_auto.h" - #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot_fx.h" #endif + /*---------------------------------------------------------------------* * core_switching_pre_enc() * @@ -822,6 +823,9 @@ void core_switching_post_enc( else if ( st->last_core == TCX_20_CORE || st->last_core == TCX_10_CORE ) { TBEreset_enc( st->hBWE_TD, st->last_core, st->bwidth ); +#ifdef IVAS_FLOAT_FIXED + TBEreset_enc_fx( st, st->bwidth ); +#endif } /* Interp_3_2 CNG buffers reset */ diff --git a/lib_enc/decision_matrix_enc.c b/lib_enc/decision_matrix_enc.c index e6363d0cc42d5ad3fa9d08bbaa20980edfb0ccd7..addccb333d06cb2d2866e55f6131c6693c14f191 100644 --- a/lib_enc/decision_matrix_enc.c +++ b/lib_enc/decision_matrix_enc.c @@ -38,6 +38,7 @@ #include #include "options.h" #include "prot.h" +#include "prot_fx_enc.h" #include "stat_enc.h" #include "stat_dec.h" #include "rom_com.h" diff --git a/lib_enc/decision_matrix_enc_fx.c b/lib_enc/decision_matrix_enc_fx.c index 922883ffc4b46ffb89a5e85986cf8a4f489b95ae..517a5e2af37f1df1e6894eb54aaf27e84d8da8cb 100644 --- a/lib_enc/decision_matrix_enc_fx.c +++ b/lib_enc/decision_matrix_enc_fx.c @@ -736,7 +736,82 @@ void signalling_enc_fx( * * write channel-aware signalling information into the bitstream *---------------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED +void signaling_enc_rf_fx( + Encoder_State *st /* i : encoder state structure */ +) +{ + Word16 i; + Word16 sfr; + RF_ENC_HANDLE hRF = st->hRF; + + /* write partial copy into bitstream */ + IF( EQ_16( st->rf_mode, 1 ) ) + { + enc_prm_rf_ivas_fx( st, hRF->rf_indx_frametype[st->rf_fec_offset], st->rf_fec_offset ); + hRF->rf_indx_tbeGainFr[0] = hRF->RF_bwe_gainFr_ind; + move16(); + } + + /* Shift the RF indices such that the partial copy associated with + (n-fec_offset)th frame is included in the bitstream in nth frame. */ + IF( hRF != NULL ) + { + FOR( i = st->rf_fec_offset; i >= 0; i-- ) + { + /* rf frame type */ + hRF->rf_indx_frametype[i + 1] = hRF->rf_indx_frametype[i]; + move16(); + /* rf target bits buffer */ + hRF->rf_targetbits_buff[i + 1] = hRF->rf_targetbits_buff[i]; + move16(); + /* lsf indx */ + hRF->rf_indx_lsf[i + 1][0] = hRF->rf_indx_lsf[i][0]; + hRF->rf_indx_lsf[i + 1][1] = hRF->rf_indx_lsf[i][1]; + hRF->rf_indx_lsf[i + 1][2] = hRF->rf_indx_lsf[i][2]; + move16(); + move16(); + move16(); + /* ES pred energy */ + hRF->rf_indx_EsPred[i + 1] = hRF->rf_indx_EsPred[i]; + move16(); + /* LTF mode, sfr params: pitch, fcb and gain */ + FOR( sfr = 0; sfr < st->nb_subfr; sfr++ ) + { + hRF->rf_indx_ltfMode[i + 1][sfr] = hRF->rf_indx_ltfMode[i][sfr]; + hRF->rf_indx_pitch[i + 1][sfr] = hRF->rf_indx_pitch[i][sfr]; + hRF->rf_indx_fcb[i + 1][sfr] = hRF->rf_indx_fcb[i][sfr]; + hRF->rf_indx_gain[i + 1][sfr] = hRF->rf_indx_gain[i][sfr]; + move16(); + move16(); + move16(); + move16(); + } + + /* shift the nelp indices */ + hRF->rf_indx_nelp_iG1[i + 1] = hRF->rf_indx_nelp_iG1[i]; + hRF->rf_indx_nelp_iG2[i + 1][0] = hRF->rf_indx_nelp_iG2[i][0]; + hRF->rf_indx_nelp_iG2[i + 1][1] = hRF->rf_indx_nelp_iG2[i][1]; + hRF->rf_indx_nelp_fid[i + 1] = hRF->rf_indx_nelp_fid[i]; + move16(); + move16(); + move16(); + move16(); + /* tbe gain Fr shift */ + hRF->rf_indx_tbeGainFr[i + 1] = hRF->rf_indx_tbeGainFr[i]; + hRF->rf_clas[i + 1] = hRF->rf_clas[i]; + hRF->rf_gain_tcx[i + 1] = hRF->rf_gain_tcx[i]; + hRF->rf_tcxltp_param[i + 1] = hRF->rf_tcxltp_param[i]; + move16(); + move16(); + move16(); + move16(); + } + } + return; +} +#endif void signalling_enc_rf( Encoder_State *st /* i : encoder state structure */ ) diff --git a/lib_enc/enc_prm_fx.c b/lib_enc/enc_prm_fx.c index 92386c2259b9ddf41b68372bdcbb1be81d62fceb..52d7dc8ddcc4d918d57a637a10bd90373c5c9271 100644 --- a/lib_enc/enc_prm_fx.c +++ b/lib_enc/enc_prm_fx.c @@ -101,7 +101,178 @@ static void enc_prm_hm_ivas_fx( * * * encode RF parameters for ACELP and TCX partial copy * *-----------------------------------------------------------------*/ +#ifdef IVAS_FLOAT_FIXED + +void enc_prm_rf_ivas_fx( Encoder_State *st, + const Word16 rf_frame_type, + const Word16 fec_offset ) +{ + Word16 sfr, nb_subfr, n, index; + Word16 ltp_mode, ltf_mode, gains_mode; + RF_ENC_HANDLE hRF = st->hRF; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + BSTR_ENC_HANDLE hBstr = st->hBstr; + + nb_subfr = st->nb_subfr; + move16(); + /* partial copy bitstream writing */ + test(); + IF( GE_16( rf_frame_type, RF_TCXFD ) && LE_16( rf_frame_type, RF_TCXTD2 ) ) + { + /* TCX frames partial copy write */ + + /* LSF indices */ + IF( EQ_16( rf_frame_type, RF_TCXFD ) ) + { + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][0], lsf_numbits[0] ); /* VQ 1 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][1], lsf_numbits[1] ); /* VQ 2 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][2], lsf_numbits[2] ); /* VQ 3 */ + } + + /* classification */ + test(); + IF( EQ_16( hRF->rf_clas[fec_offset], UNVOICED_CLAS ) ) + { + index = 0; + move16(); + } + ELSE IF( ( EQ_16( hRF->rf_clas[fec_offset], VOICED_TRANSITION ) ) || ( EQ_16( hRF->rf_clas[fec_offset], UNVOICED_TRANSITION ) ) ) + { + index = 1; + move16(); + } + ELSE IF( EQ_16( hRF->rf_clas[fec_offset], VOICED_CLAS ) ) + { + index = 2; + move16(); + } + ELSE + { + index = 3; + move16(); + } + push_next_indice_fx( hBstr, index, 2 ); + + IF( EQ_16( rf_frame_type, RF_TCXFD ) ) + { + /* TCX global gain = 7 bits */ + push_next_indice( hBstr, hRF->rf_gain_tcx[fec_offset], 7 ); + /*window info + 1 bit for long overlap + 2 if minimum or half overlap*/ + } + ELSE + { + /*gains adapt + gains inov*/ + + /*LPC on full rate -> excitation */ + /* pitch and gain */ + /* LTP data */ + test(); + test(); + IF( ( EQ_16( rf_frame_type, RF_TCXTD1 ) || EQ_16( rf_frame_type, RF_TCXTD2 ) ) && hTcxEnc->tcxltp != 0 ) + { + push_next_indice( hBstr, hRF->rf_tcxltp_param[fec_offset], 9 ); + } + } + } + ELSE IF( EQ_16( rf_frame_type, 7 ) ) /* NELP bitstream writing */ + { + /* LSF indices */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][0], 8 ); /* VQ 1 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][1], 8 ); /* VQ 2 */ + + /* NELP gain indices */ + push_next_indice( hBstr, hRF->rf_indx_nelp_iG1[fec_offset], 5 ); + push_next_indice( hBstr, hRF->rf_indx_nelp_iG2[fec_offset][0], 6 ); + push_next_indice( hBstr, hRF->rf_indx_nelp_iG2[fec_offset][1], 6 ); + + /* NELP filter selection index */ + push_next_indice( hBstr, hRF->rf_indx_nelp_fid[fec_offset], 2 ); + + /* tbe gainFr */ + push_next_indice( hBstr, hRF->rf_indx_tbeGainFr[fec_offset], 5 ); + } + ELSE IF( GE_16( rf_frame_type, 4 ) ) /* rf_frame_type ALL_PRED: 4, NO_PRED: 5, GEN_PRED: 6 */ + { + /* LSF indices */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][0], 8 ); /* VQ 1 */ + push_next_indice( hBstr, hRF->rf_indx_lsf[fec_offset][1], 8 ); /* VQ 2 */ + + /* ES pred */ + push_next_indice( hBstr, hRF->rf_indx_EsPred[fec_offset], 3 ); + + ltp_mode = ACELP_LTP_MODE[1][1][rf_frame_type]; + ltf_mode = ACELP_LTF_MODE[1][1][rf_frame_type]; + gains_mode = ACELP_GAINS_MODE[1][1][rf_frame_type]; + move16(); + move16(); + move16(); + /* Subframe parameters */ + FOR( sfr = 0; sfr < nb_subfr; sfr++ ) + { + /* Pitch lag (5, or 8 bits) */ + n = ACELP_LTP_BITS_SFR[ltp_mode][sfr]; + move16(); + IF( n != 0 ) + { + push_next_indice( hBstr, hRF->rf_indx_pitch[fec_offset][sfr], n ); + } + + /* Adaptive codebook filtering (1 bit) */ + IF( EQ_16( ltf_mode, 2 ) ) + { + push_next_indice( hBstr, hRF->rf_indx_ltfMode[fec_offset][sfr], 1 ); + } + + /*Innovative codebook*/ + test(); + test(); + test(); + IF( ( EQ_16( rf_frame_type, RF_NOPRED ) ) || + ( EQ_16( rf_frame_type, RF_GENPRED ) && + ( sfr == 0 || EQ_16( sfr, 2 ) ) ) ) + { + push_next_indice( hBstr, hRF->rf_indx_fcb[fec_offset][sfr], 7 ); + } + + /* Gains (5b, 6b or 7b / subfr) */ + test(); + IF( sfr == 0 || EQ_16( sfr, 2 ) ) + { + n = ACELP_GAINS_BITS[gains_mode]; + move16(); + push_next_indice( hBstr, hRF->rf_indx_gain[fec_offset][sfr], n ); + } + } + /* tbe gainFr */ + push_next_indice( hBstr, hRF->rf_indx_tbeGainFr[fec_offset], 2 ); + } + + /***************/ + /*IMPORTANT: The last three bits are always the rf_frame_type in the bitstream (for both acelp and tcx partial copy); + the rf_frame_type indicates the length of the partial copy payload at the decoder. + The 2 bits before the rf_frame_type contains the fec_offset */ + + /***************/ + /* write FEC offset just before the rf_frame_type */ + test(); + test(); + IF( EQ_16( fec_offset, 2 ) ) + { + push_next_indice( hBstr, 0, 2 ); + } + ELSE IF( EQ_16( fec_offset, 3 ) || EQ_16( fec_offset, 5 ) || EQ_16( fec_offset, 7 ) ) + { + push_next_indice( hBstr, shr( sub( fec_offset, 1 ), 1 ), 2 ); + } + + /* write RF frame type last in the bitstream */ + push_next_indice( hBstr, rf_frame_type, 3 ); +} +#endif void enc_prm_rf_fx( Encoder_State *st, const Word16 rf_frame_type, const Word16 fec_offset ) diff --git a/lib_enc/fd_cng_enc.c b/lib_enc/fd_cng_enc.c index 5dc4290c0516494c0afb783992292cb18c5180a5..bf0cc2136174a68cd4fe8029be99eb31d35ff277 100644 --- a/lib_enc/fd_cng_enc.c +++ b/lib_enc/fd_cng_enc.c @@ -732,7 +732,23 @@ void FdCng_encodeSID( mvr2r( tot_sig_ext, v, FDCNG_VQ_MAX_LEN ); /* write extended result as input to VQ stage #1 */ } create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 v_e; + Word16 w_fx[24]; + + f2me_buf( v, v_fx, &v_e, N ); + floatToFixed_arrL( invTrfMatrix, invTrfMatrix_fx, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + floatToFixed_arr( w, w_fx, Q8, 24 ); + +#endif + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, v_fx, v_e, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w_fx, N, FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); +#endif +#else msvq_enc( cdk_37bits_ivas, NULL, NULL, v, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, w, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices ); +#endif msvq_dec_float( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N, FD_CNG_maxN_37bits, indices, 1, invTrfMatrix, v, NULL ); } else @@ -1292,7 +1308,27 @@ void FdCngEncodeMDCTStereoSID( /* & side channel quantization using stages 1 through 4 */ { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 ms_ptr_fx[24]; + Word16 ms_ptr_e; + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; + Word16 weights_fx[24]; + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; + + f2me_buf( ms_ptr[ch], ms_ptr_fx, &ms_ptr_e, N ); + floatToFixed_arrL( invTrfMatrix, invTrfMatrix_fx, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + floatToFixed_arr( weights, weights_fx, Q8, 24 ); + +#endif + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_fx, ms_ptr_e, levels_37bits, FD_CNG_maxC_37bits, stages, weights_fx, N, FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[ch] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); +#endif +#else msvq_enc( cdk_37bits_ivas, NULL, NULL, ms_ptr[ch], levels_37bits, FD_CNG_maxC_37bits, stages, weights, N, FD_CNG_maxN_37bits, 1, invTrfMatrix, indices[ch] ); +#endif msvq_dec_float( cdk_37bits_ivas, NULL, NULL, stages, N, FD_CNG_maxN_37bits, indices[ch], 1, invTrfMatrix, ms_ptr[ch], NULL ); } } @@ -1493,7 +1529,27 @@ void FdCngEncodeDiracMDCTStereoSID( } create_IDCT_N_Matrix( invTrfMatrix, FDCNG_VQ_MAX_LEN, FDCNG_VQ_DCT_MAXTRUNC, sizeof( tmpRAM ) / ( sizeof( float ) ) ); +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 ms_ptr_t_fx[24]; + Word16 ms_ptr_t_e; + Word32 *invTrfMatrix_fx; + Word32 tmpRAM_fx[FDCNG_VQ_MAX_LEN][FDCNG_VQ_DCT_MAXTRUNC]; + Word16 weights_fx[24]; + invTrfMatrix_fx = (Word32 *) tmpRAM_fx; + + f2me_buf( ms_ptr[0], ms_ptr_t_fx, &ms_ptr_t_e, N[0] ); + floatToFixed_arrL( invTrfMatrix, invTrfMatrix_fx, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); + floatToFixed_arr( weights, weights_fx, Q8, 24 ); + +#endif + msvq_enc_ivas_fx( ivas_cdk_37bits_fx, Q7, NULL, NULL, ms_ptr_t_fx, ms_ptr_t_e, levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights_fx, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix_fx, indices[0] ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arrL( invTrfMatrix_fx, invTrfMatrix, Q31, FDCNG_VQ_MAX_LEN * FDCNG_VQ_DCT_MAXTRUNC ); +#endif +#else msvq_enc( cdk_37bits_ivas, NULL, NULL, ms_ptr[0], levels_37bits, FD_CNG_maxC_37bits, FD_CNG_stages_37bits, weights, N[0], FD_CNG_maxN_37bits, 1, invTrfMatrix, indices[0] ); +#endif msvq_dec_float( cdk_37bits_ivas, NULL, NULL, FD_CNG_stages_37bits, N[0], FD_CNG_maxN_37bits, indices[0], 1, invTrfMatrix, ms_ptr[0], NULL ); diff --git a/lib_enc/init_enc.c b/lib_enc/init_enc.c index 31e075fd766ec928031c8437a7c06cd407fe7982..47b00e2c763a9cba8b27a9f3f76baa2d6500db81 100644 --- a/lib_enc/init_enc.c +++ b/lib_enc/init_enc.c @@ -256,7 +256,12 @@ ivas_error init_encoder( st->noimix_seed = RANDOM_INITSEED; st->min_alpha = 1; st->exc_pe = 0; - +#ifdef IVAS_FLOAT_FIXED + st->exc_pe_fx = 0; + move16(); + st->Q_stat_noise = 15; + move16(); +#endif /* FEC */ st->last_clas = UNVOICED_CLAS; st->prev_fmerit_flt = 0.0f; @@ -693,6 +698,9 @@ ivas_error init_encoder( } InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif ResetSHBbuffer_Enc( st->hBWE_TD ); } else @@ -1179,7 +1187,12 @@ ivas_error init_encoder_ivas_fx( st->noimix_seed = RANDOM_INITSEED; st->min_alpha_fx = 1; st->exc_pe = 0; - +#ifdef IVAS_FLOAT_FIXED + st->exc_pe_fx = 0; + move16(); + st->Q_stat_noise = 15; + move16(); +#endif /* FEC */ st->last_clas = UNVOICED_CLAS; st->prev_fmerit = 0; diff --git a/lib_enc/init_enc_fx.c b/lib_enc/init_enc_fx.c index aa7a2954988e09070aab8c9222cd631d69faec8a..e21e082254136989b4fa9edd5a1289c7ac5ca5e9 100644 --- a/lib_enc/init_enc_fx.c +++ b/lib_enc/init_enc_fx.c @@ -157,7 +157,7 @@ ivas_error init_encoder_fx( Copy( GEWB_Ave_fx, st_fx->lsfoldbfi1_fx, M ); Copy( GEWB_Ave_fx, st_fx->lsf_adaptive_mean_fx, M ); init_lvq_fx( st_fx->offset_scale1_fx, st_fx->offset_scale2_fx, st_fx->offset_scale1_p_fx, st_fx->offset_scale2_p_fx, st_fx->no_scales_fx, st_fx->no_scales_p_fx ); - st_fx->next_force_safety_net_fx = 0; + st_fx->next_force_safety_net = 0; st_fx->pstreaklen = 0; move16(); diff --git a/lib_enc/ivas_core_enc.c b/lib_enc/ivas_core_enc.c index eb369c78a7a99ee4826e2d9165db3a7671a8a588..10ce8d8165868318e4b32f13a2ea971235be0429 100644 --- a/lib_enc/ivas_core_enc.c +++ b/lib_enc/ivas_core_enc.c @@ -41,7 +41,9 @@ #include #ifdef IVAS_FLOAT_FIXED #include "prot_fx.h" +#include "prot_fx_enc.h" #include "ivas_prot_fx.h" +#include "prot_fx_enc.h" #endif #ifdef DEBUGGING #include "debug.h" @@ -94,21 +96,38 @@ ivas_error ivas_core_enc( float hb_speech[L_FRAME16k / 4]; float *new_swb_speech; float new_swb_speech_buffer[L_FRAME48k + STEREO_DFT_OVL_MAX]; + float bwe_exc_extended[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; + float voice_factors[CPE_CHANNELS][NB_SUBFR16k]; #ifdef IVAS_FLOAT_FIXED Word32 *new_swb_speech_fx; + Word16 shb_speech_fx[L_FRAME16k]; Word32 new_swb_speech_buffer_fx[L_FRAME48k + STEREO_DFT_OVL_MAX]; + Word16 new_inp_resamp16k_fx[CPE_CHANNELS][L_FRAME16k]; + Word16 hb_speech_fx[L_FRAME16k / 4]; + Word32 bwe_exc_extended_fx[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; + Word16 voice_factors_fx[CPE_CHANNELS][NB_SUBFR16k]; /* Q15 */ + Word16 old_syn_12k8_16k_fx[CPE_CHANNELS][L_FRAME16k]; /* ACELP core synthesis at 12.8kHz or 16kHz to be used by the SWB BWE */ + Word16 *new_swb_speech_fx1; + Word16 new_swb_speech_buffer_fx1[L_FRAME48k + STEREO_DFT_OVL_MAX]; #endif - float bwe_exc_extended[CPE_CHANNELS][L_FRAME32k + NL_BUFF_OFFSET]; - float voice_factors[CPE_CHANNELS][NB_SUBFR16k]; int16_t Voicing_flag[CPE_CHANNELS]; float pitch_buf[CPE_CHANNELS][NB_SUBFR16k]; +#ifdef IVAS_FLOAT_FIXED + Word16 pitch_buf_fx[CPE_CHANNELS][NB_SUBFR16k]; /* Q6 */ +#endif int16_t unbits[CPE_CHANNELS]; float tdm_lspQ_PCh[M], tdm_lsfQ_PCh[M]; +#ifdef IVAS_FLOAT_FIXED + Word16 tdm_lspQ_PCh_fx[M], tdm_lsfQ_PCh_fx[M]; /* 1 : Q15, 2 : Q2.56 */ +#endif int16_t last_element_mode, tdm_Pitch_reuse_flag; int32_t element_brate, last_element_brate, input_Fs; int16_t diff_nBits; ivas_error error; int16_t max_num_indices_BWE; +#ifdef IVAS_FLOAT_FIXED + Word16 i, Q_new; +#endif push_wmops( "ivas_core_enc" ); @@ -314,7 +333,29 @@ ivas_error ivas_core_enc( if ( st->element_mode == IVAS_CPE_TD && n == 0 ) { +#ifndef IVAS_FLOAT_FIXED td_stereo_param_updt( st->lsp_old, st->lsf_old, pitch_buf[0], tdm_lspQ_PCh, tdm_lsfQ_PCh, hStereoTD->tdm_Pri_pitch_buf, st->flag_ACELP16k, hStereoTD->tdm_use_IAWB_Ave_lpc ); +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // lsp_old - Q15, lsf_old - Qlog2(2.56), pitch_buf - Q6 + floatToFixed_arr16( st->lsp_old, st->lsp_old_fx, Q15, M ); + for ( i = 0; i < M; i++ ) + { + st->lsf_old_fx[i] = (Word16) ( st->lsf_old[i] * 2.56f ); + } + floatToFixed_arr16( pitch_buf[0], pitch_buf_fx[0], Q6, NB_SUBFR ); +#endif + td_stereo_param_updt_fx( st->lsp_old_fx, st->lsf_old_fx, pitch_buf_fx[0], tdm_lspQ_PCh_fx, tdm_lsfQ_PCh_fx, hStereoTD->tdm_Pri_pitch_buf_fx, st->flag_ACELP16k, hStereoTD->tdm_use_IAWB_Ave_lpc ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + // tdm_lspQ_PCh - Q15, tdm_lsfQ_PCh - Qlog2(2.56), hStereoTD->tdm_Pri_pitch_buf - Q6 + fixedToFloat_arr( tdm_lspQ_PCh_fx, tdm_lspQ_PCh, Q15, M ); + for ( i = 0; i < M; i++ ) + { + tdm_lsfQ_PCh[i] = tdm_lsfQ_PCh_fx[i] / 2.56f; + } + fixedToFloat_arr( hStereoTD->tdm_Pri_pitch_buf_fx, hStereoTD->tdm_Pri_pitch_buf, Q6, NB_SUBFR ); +#endif +#endif } } @@ -380,6 +421,7 @@ ivas_error ivas_core_enc( * WB BWE encoding *---------------------------------------------------------------------*/ +#ifndef IVAS_FLOAT_FIXED if ( input_Fs >= 16000 && st->bwidth < SWB && st->hBWE_TD != NULL ) { /* Common pre-processing for WB TBE and WB BWE */ @@ -396,6 +438,105 @@ ivas_error ivas_core_enc( /* WB BWE encoder */ wb_bwe_enc( st, new_inp_resamp16k[n] ); } +#else +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /* Temporarily calculating variable Q. Will get Q values from core processing */ + Q_new = Q_factor_arrL( bwe_exc_extended[n], L_FRAME32k + NL_BUFF_OFFSET ); + Q_new = Q_new / 2; + if ( st->hBWE_TD != NULL ) + { + Word16 tmp_q_1 = Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb, 2 * ALLPASSSECTIONS_STEEP + 1 ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb2, 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb3, 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_syn_shbexc, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->state_lpc_syn, L_SHB_LAHEAD ) ); + tmp_q_1 = min( tmp_q_1, Q_factor_arr( st->hBWE_TD->old_bwe_exc_extended, NL_BUFF_OFFSET ) ); + Word16 tmp_q_2 = Q_factor_arrL( st->hBWE_TD->mem_csfilt, 2 ); + st->prev_Q_bwe_exc = min( tmp_q_2, tmp_q_1 + 16 ) - 2 /* Guard bits */; /* This reset need to be looked into once core processing is complete */ + } + + floatToFixed_arr16( new_inp_resamp16k[n], new_inp_resamp16k_fx[n], -1, L_FRAME16k ); + floatToFixed_arr( voice_factors[n], voice_factors_fx[n], Q15, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr( pitch_buf[n], pitch_buf_fx[n], Q6, NB_SUBFR16k ); // Saturation Conversion used as last values have garbage values even in float + floatToFixed_arr32( bwe_exc_extended[n], bwe_exc_extended_fx[n], 2 * Q_new, L_FRAME32k + NL_BUFF_OFFSET ); + + // prev_lsp_wb_temp_fx, prev_lsp_wb_fx and prev_lpc_wb_fx in Q15. No float counterparts + floatToFixed_arr16( st->voicing, st->voicing_fx, Q15, 3 ); + + if ( st->hBWE_TD != NULL ) + { + st->hBWE_TD->prev_wb_GainShape = float_to_fix16( st->hBWE_TD->prev_wb_GainShape_flt, Q15 ); + floatToFixed_arr16( st->hBWE_TD->decim_state1, st->hBWE_TD->decim_state1_fx, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->decim_state2, st->hBWE_TD->decim_state2_fx, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->old_speech_wb, st->hBWE_TD->old_speech_wb_fx, -1, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); + floatToFixed_arr16( st->hBWE_TD->mem_genSHBexc_filt_down_shb, st->hBWE_TD->mem_genSHBexc_filt_down_shb_fx, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->mem_genSHBexc_filt_down_wb2, st->hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->mem_genSHBexc_filt_down_wb3, st->hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + floatToFixed_arr16( st->hBWE_TD->state_syn_shbexc, st->hBWE_TD->state_syn_shbexc_fx, ( st->prev_Q_bwe_exc - 16 ), L_SHB_LAHEAD ); + floatToFixed_arr16( st->hBWE_TD->state_lpc_syn, st->hBWE_TD->state_lpc_syn_fx, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + floatToFixed_arr16( st->hBWE_TD->old_bwe_exc_extended, st->hBWE_TD->old_bwe_exc_extended_fx, ( st->prev_Q_bwe_exc - 16 ), NL_BUFF_OFFSET ); + floatToFixed_arr16( st->hBWE_TD->syn_overlap, st->hBWE_TD->syn_overlap_fx, 0, L_SHB_LAHEAD ); + floatToFixed_arr32( st->hBWE_TD->mem_csfilt, st->hBWE_TD->mem_csfilt_fx, st->prev_Q_bwe_exc, 2 ); + } + + if ( st->hBWE_FD != NULL ) + { + floatToFixed_arr16( st->hBWE_FD->old_input_wb, st->hBWE_FD->old_input_wb_fx, -1, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + floatToFixed_arr16( st->hBWE_FD->old_wtda_swb, st->hBWE_FD->L_old_wtda_swb_fx, -1, L_FRAME48k ); + floatToFixed_arr16( &st->hBWE_FD->mem_old_wtda_swb, &st->hBWE_FD->mem_old_wtda_swb_fx, -1, 1 ); + st->Q_old_wtda = -1; // This reset is required for resolving crash issue. Needs to be looked into further + } +#endif + test(); + test(); + IF( GE_32( input_Fs, 16000 ) && LT_16( st->bwidth, SWB ) && st->hBWE_TD != NULL ) + { + /* Common pre-processing for WB TBE and WB BWE */ + wb_pre_proc_ivas_fx( st, last_element_mode, new_inp_resamp16k_fx[n], hb_speech_fx ); + } + + test(); + test(); + IF( EQ_16( st->extl, WB_TBE ) ) + { + /* WB TBE encoder */ + wb_tbe_enc_ivas_fx( st, hb_speech_fx, bwe_exc_extended_fx[n], Q_new, voice_factors_fx[n], pitch_buf_fx[n] ); + } + ELSE IF( EQ_16( st->extl, WB_BWE ) && n == 0 && NE_16( st->element_mode, IVAS_CPE_MDCT ) ) + { + /* WB BWE encoder */ + wb_bwe_enc_ivas_fx( st, new_inp_resamp16k_fx[n] ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( hb_speech_fx, hb_speech, -1, L_FRAME16k / 4 ); + fixedToFloat_arr( voice_factors_fx[n], voice_factors[n], Q15, NB_SUBFR16k ); + fixedToFloat_arr( pitch_buf_fx[n], pitch_buf[n], Q6, NB_SUBFR16k ); + fixedToFloat_arrL( bwe_exc_extended_fx[n], bwe_exc_extended[n], 2 * Q_new, L_FRAME32k + NL_BUFF_OFFSET ); + + if ( st->hBWE_TD != NULL ) + { + st->hBWE_TD->prev_wb_GainShape_flt = fix_to_float( st->hBWE_TD->prev_wb_GainShape, Q15 ); + fixedToFloat_arr( st->hBWE_TD->decim_state1_fx, st->hBWE_TD->decim_state1, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->decim_state2_fx, st->hBWE_TD->decim_state2, -1, 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->old_speech_wb_fx, st->hBWE_TD->old_speech_wb, -1, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); + fixedToFloat_arr( st->hBWE_TD->mem_genSHBexc_filt_down_shb_fx, st->hBWE_TD->mem_genSHBexc_filt_down_shb, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, st->hBWE_TD->mem_genSHBexc_filt_down_wb2, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, st->hBWE_TD->mem_genSHBexc_filt_down_wb3, ( st->prev_Q_bwe_exc - 16 ), 2 * ALLPASSSECTIONS_STEEP + 1 ); + fixedToFloat_arr( st->hBWE_TD->state_syn_shbexc_fx, st->hBWE_TD->state_syn_shbexc, ( st->prev_Q_bwe_exc - 16 ), L_SHB_LAHEAD ); + fixedToFloat_arr( st->hBWE_TD->state_lpc_syn_fx, st->hBWE_TD->state_lpc_syn, ( st->prev_Q_bwe_exc - 16 ), LPC_SHB_ORDER ); + fixedToFloat_arr( st->hBWE_TD->old_bwe_exc_extended_fx, st->hBWE_TD->old_bwe_exc_extended, ( st->prev_Q_bwe_exc - 16 ), NL_BUFF_OFFSET ); + fixedToFloat_arr( st->hBWE_TD->syn_overlap_fx, st->hBWE_TD->syn_overlap, 0, L_SHB_LAHEAD ); + fixedToFloat_arrL( st->hBWE_TD->mem_csfilt_fx, st->hBWE_TD->mem_csfilt, st->prev_Q_bwe_exc, 2 ); + } + + if ( st->hBWE_FD != NULL ) + { + fixedToFloat_arr( st->hBWE_FD->old_input_wb_fx, st->hBWE_FD->old_input_wb, -1, NS2SA( 16000, DELAY_FD_BWE_ENC_NS ) ); + fixedToFloat_arr( st->hBWE_FD->L_old_wtda_swb_fx, st->hBWE_FD->old_wtda_swb, -1, L_FRAME48k ); + st->hBWE_FD->mem_old_wtda_swb = fixedToFloat( st->hBWE_FD->mem_old_wtda_swb_fx, st->Q_old_wtda ); + } +#endif +#endif /*---------------------------------------------------------------------* * SWB(FB) TBE encoding @@ -405,6 +546,7 @@ ivas_error ivas_core_enc( new_swb_speech = new_swb_speech_buffer + STEREO_DFT_OVL_MAX; #ifdef IVAS_FLOAT_FIXED new_swb_speech_fx = new_swb_speech_buffer_fx + STEREO_DFT_OVL_MAX; + new_swb_speech_fx1 = new_swb_speech_buffer_fx1 + STEREO_DFT_OVL_MAX; #endif if ( !st->Opt_SC_VBR && input_Fs >= 32000 && st->hBWE_TD != NULL ) @@ -442,8 +584,67 @@ ivas_error ivas_core_enc( } else if ( st->extl == SWB_BWE || st->extl == FB_BWE ) { +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 old_inp_12k8_fx[L_INP_12k8], old_inp_16k_fx[L_INP]; + Word16 old_syn_12k8_16k_fx[L_FRAME16k], q_val; + Word16 shb_speech_fx[L_FRAME16k]; + Word16 q_old_inp_16k_fx, q_old_syn_12k8_16k_fx, q_old_input_lp; + Word16 q_old_inp_12k8_fx, q_shb_speech_fx, q_new_input_hp; + + q_old_inp_12k8_fx = Q_factor_arr( old_inp_12k8[n], L_INP_12k8 ); + q_old_inp_16k_fx = Q_factor_arr( old_inp_16k[n], L_INP ); + q_old_syn_12k8_16k_fx = Q_factor_arr( old_syn_12k8_16k[n], L_FRAME16k ); + q_shb_speech_fx = Q_factor_arr( shb_speech, L_FRAME16k ); + + q_val = s_min( q_old_inp_12k8_fx, q_old_inp_16k_fx ); + q_val = s_min( q_val, q_old_syn_12k8_16k_fx ); + + if ( st->hBWE_FD != NULL ) + { + q_old_input_lp = Q_factor_arr( st->hBWE_FD->old_input_lp, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS ) ); + q_val = s_min( q_val, q_old_input_lp ); + q_new_input_hp = Q_factor_arr( st->hBWE_FD->new_input_hp, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ) ); + q_shb_speech_fx = s_min( q_shb_speech_fx, q_new_input_hp ); + st->Q_old_wtda = Q_factor_arr( st->hBWE_FD->old_wtda_swb, L_FRAME48k ); + floatToFixed_arr16( st->hBWE_FD->old_input_lp, st->hBWE_FD->old_input_lp_fx, q_val, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS ) ); + floatToFixed_arr16( st->hBWE_FD->new_input_hp, st->hBWE_FD->new_input_hp_fx, q_shb_speech_fx, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ) ); + floatToFixed_arr16( st->hBWE_FD->old_wtda_swb, st->hBWE_FD->L_old_wtda_swb_fx, st->Q_old_wtda, L_FRAME48k ); + } + + floatToFixed_arr16( old_inp_12k8[n], old_inp_12k8_fx, q_val, L_INP_12k8 ); + floatToFixed_arr16( old_inp_16k[n], old_inp_16k_fx, q_val, L_INP ); + floatToFixed_arr16( old_syn_12k8_16k[n], old_syn_12k8_16k_fx, q_val, L_FRAME16k ); + floatToFixed_arr16( shb_speech, shb_speech_fx, q_shb_speech_fx, L_FRAME16k ); + + for ( int ii = 0; ii < L_FRAME48k + STEREO_DFT_OVL_MAX; ii++ ) + { + new_swb_speech_buffer_fx1[ii] = (Word16) new_swb_speech_buffer[ii]; + } + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input_fx[ii] = (Word16) st->hBWE_FD->old_input[ii]; + } +#endif + /* SWB(FB) BWE encoder */ + swb_bwe_enc_ivas_fx( st, last_element_mode, old_inp_12k8_fx, old_inp_16k_fx, old_syn_12k8_16k_fx, new_swb_speech_fx1, shb_speech_fx, q_shb_speech_fx, q_val ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + if ( st->hBWE_FD != NULL ) + { + fixedToFloat_arr( st->hBWE_FD->old_input_lp_fx, st->hBWE_FD->old_input_lp, q_val, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS ) ); + fixedToFloat_arr( st->hBWE_FD->new_input_hp_fx, st->hBWE_FD->new_input_hp, q_shb_speech_fx, NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ) ); + fixedToFloat_arr( st->hBWE_FD->L_old_wtda_swb_fx, st->hBWE_FD->old_wtda_swb, st->Q_old_wtda, L_FRAME48k ); + } + for ( int ii = 0; ii < NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ); ii++ ) + { + st->hBWE_FD->old_input[ii] = (float) st->hBWE_FD->old_input_fx[ii]; + } + st->EnergyLT = fixedToFloat( st->EnergyLT_fx, st->EnergyLT_fx_exp ); +#endif +#else /* SWB(FB) BWE encoder */ swb_bwe_enc( st, last_element_mode, old_inp_12k8[n], old_inp_16k[n], old_syn_12k8_16k[n], new_swb_speech, shb_speech ); +#endif } /*---------------------------------------------------------------------* @@ -453,7 +654,32 @@ ivas_error ivas_core_enc( if ( st->hTdCngEnc != NULL && st->Opt_DTX_ON && ( input_frame >= L_FRAME32k || st->element_mode == IVAS_CPE_DFT ) ) { /* SHB DTX/CNG encoder */ +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( i = 0; i < CPE_CHANNELS; i++ ) + { + floatToFixed_arr( old_syn_12k8_16k[i], old_syn_12k8_16k_fx[i], 0, L_FRAME16k ); + } + + floatToFixed_arr( shb_speech, shb_speech_fx, 0, L_FRAME16k ); + + test(); + IF( EQ_32( st->core_brate, SID_2k40 ) || st->core_brate == FRAME_NO_DATA ) + { + IF( st->cng_type == LP_CNG ) + { + IF( GE_32( st->input_Fs, L_FRAME32k * FRAMES_PER_SEC ) ) + { + /* decide if SHB SID encoding or not */ + floatToFixed_arr( st->hBWE_TD->old_speech_shb, st->hBWE_TD->old_speech_shb_fx, 0, L_LOOK_16k + L_SUBFR16k ); + } + } + } +#endif + swb_CNG_enc_ivas_fx( st, shb_speech_fx, old_syn_12k8_16k_fx[n] ); +#else swb_CNG_enc( st, shb_speech, old_syn_12k8_16k[n] ); +#endif } /*-------------------------------------------------------------------* @@ -525,9 +751,11 @@ ivas_error ivas_core_enc( /*---------------------------------------------------------------------* * Channel-aware mode - write signaling information into the bitstream *---------------------------------------------------------------------*/ - +#ifdef IVAS_FLOAT_FIXED + signaling_enc_rf_fx( st ); +#else signaling_enc_rf( st ); - +#endif /*---------------------------------------------------------------------* * Common updates *---------------------------------------------------------------------*/ diff --git a/lib_enc/ivas_mct_enc.c b/lib_enc/ivas_mct_enc.c index 484abca22ffb48cbe788b4f647b26239a1e1308f..992b49ac57fed8eb5f4b858300f1f36d78b352b3 100644 --- a/lib_enc/ivas_mct_enc.c +++ b/lib_enc/ivas_mct_enc.c @@ -483,9 +483,37 @@ ivas_error ivas_mct_enc( { hCPE->hCoreCoder[0]->hBstr->ind_list = st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->ind_list + st_ivas->hCPE[cpe_id - 1]->hCoreCoder[1]->hBstr->nb_ind_tot; } - +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Encoder_State *st, **sts; + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts = hCPE->hCoreCoder; + st = sts[ch]; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + st->hTcxEnc->tcx_target_bits_fac = float_to_fix16( st->hTcxEnc->tcx_target_bits_fac_flt, Q14 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + } + floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + } +#endif ivas_mdct_quant_coder_fx( hCPE, hMCT->tnsBits[cpe_id], hMCT->tnsSize[cpe_id], hMCT->p_param[cpe_id], 1 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts = hCPE->hCoreCoder; + st = sts[ch]; + st->hTcxEnc->tcx_target_bits_fac_flt = me2f_16( st->hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); + } +#endif /* update input samples buffer (as done in ivas_cpe_enc() for other than MCT coding) */ FOR( n = 0; n < CPE_CHANNELS; n++ ) { diff --git a/lib_enc/ivas_mdct_core_enc.c b/lib_enc/ivas_mdct_core_enc.c index 9bf39785e2234827e1c2f5621d0bb83ab1ad4172..89b0070ae8f3c16366c026638f18c312525ea7e5 100644 --- a/lib_enc/ivas_mdct_core_enc.c +++ b/lib_enc/ivas_mdct_core_enc.c @@ -44,6 +44,7 @@ #ifdef IVAS_FLOAT_FIXED #include "prot_fx_enc.h" #include "prot_fx.h" +#include "ivas_prot_fx.h" #endif @@ -1624,24 +1625,23 @@ void ivas_mdct_quant_coder( ) { Encoder_State *st, **sts; - int16_t bitsAvailable, target_bits, nSubframes, ch, n; - int16_t L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ - int16_t L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ - int16_t L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ - int16_t tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ - int16_t noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + Word16 bitsAvailable, target_bits, nSubframes, ch, n; + Word16 L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ + Word16 L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ + Word16 L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ + Word16 tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ + Word16 noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + Word16 nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ + Word16 hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ float fac_ns[CPE_CHANNELS][NB_DIV]; /* noise filling level */ - int16_t nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ - int16_t hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ float ener[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ float gain_tcx[CPE_CHANNELS][NB_DIV]; /* global gain */ float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ float *quantized_spectrum[CPE_CHANNELS][NB_DIV]; - int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; - int16_t ignore_chan[CPE_CHANNELS]; - int16_t target_bitsTCX10[CPE_CHANNELS][NB_DIV]; - int16_t nbits_start, total_nbbits; - + Word16 param_core[CPE_CHANNELS][2 * NPRM_DIV]; + Word16 ignore_chan[CPE_CHANNELS]; + Word16 target_bitsTCX10[CPE_CHANNELS][NB_DIV]; + Word16 nbits_start, total_nbbits; push_wmops( "mdct_core_Q" ); sts = hCPE->hCoreCoder; @@ -1649,8 +1649,6 @@ void ivas_mdct_quant_coder( for ( ch = 0; ch < CPE_CHANNELS; ch++ ) { set_f( fac_ns[ch], 0.0f, NB_DIV ); - set_s( nf_seed[ch], 0, NB_DIV ); - set_s( hm_active[ch], 0, NB_DIV ); set_f( ener[ch], 0.0f, NB_DIV ); set_f( gain_tcx[ch], 0.0f, NB_DIV ); } @@ -1659,6 +1657,7 @@ void ivas_mdct_quant_coder( { quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; + st = sts[ch]; if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) @@ -1749,15 +1748,7 @@ void ivas_mdct_quant_coder( } nbits_start = st->hBstr->nb_bits_tot; -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); -#endif - - writeTCXparam_fx( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#else writeTCXparam( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#endif total_nbbits = st->hBstr->nb_bits_tot - nbits_start - nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ); @@ -1769,104 +1760,102 @@ void ivas_mdct_quant_coder( } #ifdef IVAS_FLOAT_FIXED void ivas_mdct_quant_coder_fx( - CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ - int16_t tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ - int16_t tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ - int16_t p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ - const int16_t MCT_flag /* i : hMCT handle allocated (1) or not (0) */ + CPE_ENC_HANDLE hCPE, /* i/o: Encoder CPE handle */ + Word16 tnsBits[CPE_CHANNELS][NB_DIV], /* i : bits needed for TNS parameters */ + Word16 tnsSize[CPE_CHANNELS][NB_DIV], /* i : size of TNS */ + Word16 p_param[CPE_CHANNELS][NB_DIV], /* i : pointer to parameter array */ + const Word16 MCT_flag /* i : hMCT handle allocated (1) or not (0) */ ) { Encoder_State *st, **sts; - int16_t bitsAvailable, target_bits, nSubframes, ch, n; - int16_t L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ - int16_t L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ - int16_t L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ - int16_t tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ - int16_t noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ - float fac_ns[CPE_CHANNELS][NB_DIV]; /* noise filling level */ - int16_t nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ - int16_t hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ - float ener[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ - float gain_tcx[CPE_CHANNELS][NB_DIV]; /* global gain */ - float quantized_spectrum_long[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ - float *quantized_spectrum[CPE_CHANNELS][NB_DIV]; - int16_t param_core[CPE_CHANNELS][2 * NPRM_DIV]; - int16_t ignore_chan[CPE_CHANNELS]; - int16_t target_bitsTCX10[CPE_CHANNELS][NB_DIV]; - int16_t nbits_start, total_nbbits; -#ifdef IVAS_FLOAT_FIXED + Word16 bitsAvailable, target_bits, nSubframes, ch, n; + Word16 L_frameTCX[CPE_CHANNELS][NB_DIV]; /* full frame length */ + Word16 L_frame[CPE_CHANNELS][NB_DIV]; /* frame length */ + Word16 L_spec[CPE_CHANNELS][NB_DIV]; /* length of the coded spectrum */ + Word16 tcx_offset[CPE_CHANNELS][NB_DIV]; /* folding point offset relative to the end of the previous frame */ + Word16 noiseFillingBorder[CPE_CHANNELS][NB_DIV]; /* noise filling border */ + Word16 nf_seed[CPE_CHANNELS][NB_DIV]; /* noise filling random seed */ + Word16 hm_active[CPE_CHANNELS][NB_DIV]; /* flag indicating if the harmonic model is active */ + Word16 param_core[CPE_CHANNELS][2 * NPRM_DIV]; + Word16 ignore_chan[CPE_CHANNELS]; + Word16 target_bitsTCX10[CPE_CHANNELS][NB_DIV]; + Word16 nbits_start, total_nbbits; + Word16 fac_ns_fx[CPE_CHANNELS][NB_DIV]; /* noise filling level */ - Word16 ener_fx[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ + Word32 ener_fx[CPE_CHANNELS][NB_DIV]; /* energy of the quantized spectrum */ Word16 gain_tcx_fx[CPE_CHANNELS][NB_DIV]; /* global gain */ - Word16 gain_tcx_e; + Word16 gain_tcx_e[CPE_CHANNELS][NB_DIV]; Word32 quantized_spectrum_long_fx[CPE_CHANNELS][N_MAX]; /* quantized MDCT spectrum, inv ms mask mdst spectrum, scratch for MS spectra in the MS decision */ Word32 *quantized_spectrum_fx[CPE_CHANNELS][NB_DIV]; -#endif + Word16 quantized_spectrum_e[CPE_CHANNELS][NB_DIV]; + Word16 ener_e[CPE_CHANNELS][NB_DIV]; + Word16 gain_tcx_ee; push_wmops( "mdct_core_Q" ); sts = hCPE->hCoreCoder; -#ifdef IVAS_FLOAT_FIXED FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { set16_fx( fac_ns_fx[ch], 0, NB_DIV ); set16_fx( nf_seed[ch], 0, NB_DIV ); set16_fx( hm_active[ch], 0, NB_DIV ); - set16_fx( ener_fx[ch], 0, NB_DIV ); + set32_fx( ener_fx[ch], 0, NB_DIV ); + set32_fx( quantized_spectrum_long_fx[ch], 0, N_MAX ); set16_fx( gain_tcx_fx[ch], 0, NB_DIV ); + set16_fx( gain_tcx_e[ch], -1000, NB_DIV ); set16_fx( L_frame[ch], 0, NB_DIV ); + set16_fx( L_spec[ch], 0, NB_DIV ); } -#endif - - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) - { - set_f( fac_ns[ch], 0.0f, NB_DIV ); - set_s( nf_seed[ch], 0, NB_DIV ); - set_s( hm_active[ch], 0, NB_DIV ); - set_f( ener[ch], 0.0f, NB_DIV ); - set_f( gain_tcx[ch], 0.0f, NB_DIV ); - } - - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { - quantized_spectrum[ch][0] = quantized_spectrum_long[ch]; - quantized_spectrum[ch][1] = quantized_spectrum_long[ch] + N_TCX10_MAX; -#ifdef IVAS_FLOAT_FIXED quantized_spectrum_fx[ch][0] = quantized_spectrum_long_fx[ch]; quantized_spectrum_fx[ch][1] = quantized_spectrum_long_fx[ch] + N_TCX10_MAX; -#endif st = sts[ch]; - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { ignore_chan[ch] = 1; + move16(); continue; } - nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + ignore_chan[ch] = 0; + move16(); - bitsAvailable = st->bits_frame_channel + nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ) + tnsBits[ch][0] + tnsBits[ch][1]; + bitsAvailable = add( add( st->bits_frame_channel, i_mult( nSubframes, NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ) ), add( tnsBits[ch][0], tnsBits[ch][1] ) ); /* calculate TCX10 target bits before to assure minimum amount is distributed between subframes */ - if ( st->hTcxEnc->tcxMode == TCX_10 ) + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_10 ) ) { - int16_t nTnsBitsTCX10Tmp[2]; + Word16 nTnsBitsTCX10Tmp[2]; nTnsBitsTCX10Tmp[0] = tnsBits[ch][0]; + move16(); nTnsBitsTCX10Tmp[1] = tnsBits[ch][1]; + move16(); - ivas_mdct_tcx10_bit_distribution( target_bitsTCX10[ch], bitsAvailable, nTnsBitsTCX10Tmp ); + ivas_mdct_tcx10_bit_distribution_fx( target_bitsTCX10[ch], bitsAvailable, nTnsBitsTCX10Tmp ); } - for ( n = 0; n < nSubframes; n++ ) + FOR( n = 0; n < nSubframes; n++ ) { - if ( nSubframes == 2 ) + IF( EQ_16( nSubframes, 2 ) ) { target_bits = target_bitsTCX10[ch][n]; + move16(); } - else + ELSE { - target_bits = bitsAvailable / nSubframes - tnsBits[ch][n]; + target_bits = sub( idiv1616( bitsAvailable, nSubframes ), tnsBits[ch][n] ); } assert( target_bits >= NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL + SMDCT_MINIMUM_ARITH_BITS ); @@ -1875,74 +1864,129 @@ void ivas_mdct_quant_coder_fx( * Quantize the MDCT spectrum * *-----------------------------------------------------------*/ - QuantizeTCXSpectrum( st, n, st->hTcxEnc->spectrum[n], NULL, NULL, tnsSize[ch][n], target_bits, 0, &L_frameTCX[ch][n], - &L_frame[ch][n], &L_spec[ch][n], &tcx_offset[ch][n], &noiseFillingBorder[ch][n], quantized_spectrum[ch][n], NULL, - &hm_active[ch][n], NULL, &nf_seed[ch][n], &ener[ch][n], &gain_tcx[ch][n], param_core[ch] + n * NPRM_DIV ); + QuantizeTCXSpectrum_fx( st, n, st->hTcxEnc->spectrum_fx[n], st->hTcxEnc->spectrum_e[n], NULL, 0, NULL, tnsSize[ch][n], target_bits, 0, &L_frameTCX[ch][n], + &L_frame[ch][n], &L_spec[ch][n], &tcx_offset[ch][n], &noiseFillingBorder[ch][n], quantized_spectrum_fx[ch][n], &quantized_spectrum_e[ch][n], NULL, + &hm_active[ch][n], NULL, &nf_seed[ch][n], &ener_fx[ch][n], &ener_e[ch][n], &gain_tcx_fx[ch][n], &gain_tcx_e[ch][n], param_core[ch] + n * NPRM_DIV ); } } -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + /* Scaling buffers to common exp*/ + + Word16 temp_scale, min_shift = -1000; + move16(); FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; - TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; - floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); - - st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); - st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); - st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q14 ); - st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], L_frame[ch][0] ) - 4 ); - st->hTcxEnc->spectrum_e[1] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[1], L_frame[ch][1] ) - 4 ); - floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], Q31 - st->hTcxEnc->spectrum_e[0], L_frame[ch][0] ); - floatToFixed_arrL( st->hTcxEnc->spectrum[1], st->hTcxEnc->spectrum_fx[1], Q31 - st->hTcxEnc->spectrum_e[1], L_frame[ch][1] ); - - floatToFixed_arrL( quantized_spectrum[ch][0], quantized_spectrum_fx[ch][0], Q31 - st->hTcxEnc->spectrum_e[0], L_frame[ch][0] ); - floatToFixed_arrL( quantized_spectrum[ch][1], quantized_spectrum_fx[ch][1], Q31 - st->hTcxEnc->spectrum_e[1], L_frame[ch][1] ); - } - gain_tcx_e = Q_factor_arr( gain_tcx[0], NB_DIV ); - gain_tcx_e = 15 - min( gain_tcx_e, Q_factor_arr( gain_tcx[1], NB_DIV ) ); - floatToFixed_arr( gain_tcx[0], gain_tcx_fx[0], 15 - gain_tcx_e, NB_DIV ); - floatToFixed_arr( gain_tcx[1], gain_tcx_fx[1], 15 - gain_tcx_e, NB_DIV ); -#endif + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + FOR( n = 0; n < nSubframes; n++ ) + { + temp_scale = getScaleFactor32( quantized_spectrum_fx[ch][n], L_spec[ch][n] ); + scale_sig32( quantized_spectrum_fx[ch][n], L_spec[ch][n], temp_scale ); + quantized_spectrum_e[ch][n] = sub( quantized_spectrum_e[ch][n], temp_scale ); + min_shift = s_max( min_shift, quantized_spectrum_e[ch][n] ); + temp_scale = getScaleFactor32( st->hTcxEnc->spectrum_fx[n], L_spec[ch][n] ); + scale_sig32( st->hTcxEnc->spectrum_fx[n], L_spec[ch][n], temp_scale ); + st->hTcxEnc->spectrum_e[n] = sub( st->hTcxEnc->spectrum_e[n], temp_scale ); + min_shift = s_max( min_shift, st->hTcxEnc->spectrum_e[n] ); + } + } + min_shift = add( min_shift, 4 ); + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + FOR( n = 0; n < nSubframes; n++ ) + { + scale_sig32( quantized_spectrum_fx[ch][n], L_spec[ch][n], sub( quantized_spectrum_e[ch][n], min_shift ) ); + quantized_spectrum_e[ch][n] = min_shift; + move16(); + scale_sig32( st->hTcxEnc->spectrum_fx[n], L_spec[ch][n], sub( st->hTcxEnc->spectrum_e[n], min_shift ) ); + st->hTcxEnc->spectrum_e[n] = min_shift; + move16(); + } + } - EstimateStereoTCXNoiseLevel_fx( sts, quantized_spectrum_fx, gain_tcx_fx, gain_tcx_e, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns_fx, param_core, MCT_flag ); + gain_tcx_ee = s_max( gain_tcx_e[0][0], gain_tcx_e[0][1] ); + gain_tcx_ee = s_max( gain_tcx_ee, gain_tcx_e[1][0] ); + gain_tcx_ee = s_max( gain_tcx_ee, gain_tcx_e[1][1] ); + gain_tcx_fx[0][0] = shl( gain_tcx_fx[0][0], sub( gain_tcx_e[0][0], gain_tcx_ee ) ); + gain_tcx_fx[0][1] = shl( gain_tcx_fx[0][1], sub( gain_tcx_e[0][1], gain_tcx_ee ) ); + gain_tcx_fx[1][0] = shl( gain_tcx_fx[1][0], sub( gain_tcx_e[1][0], gain_tcx_ee ) ); + gain_tcx_fx[1][1] = shl( gain_tcx_fx[1][1], sub( gain_tcx_e[1][1], gain_tcx_ee ) ); -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - floatToFixed_arr( fac_ns[0], fac_ns_fx[0], Q15, NB_DIV ); - floatToFixed_arr( fac_ns[1], fac_ns_fx[1], Q15, NB_DIV ); -#endif -#else - EstimateStereoTCXNoiseLevel( sts, quantized_spectrum, gain_tcx, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns, param_core, MCT_flag ); -#endif - for ( ch = 0; ch < CPE_CHANNELS; ch++ ) + EstimateStereoTCXNoiseLevel_fx( sts, quantized_spectrum_fx, gain_tcx_fx, gain_tcx_ee, L_frame, noiseFillingBorder, hm_active, ignore_chan, fac_ns_fx, param_core, MCT_flag ); + + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) { st = sts[ch]; /* update the pointer to the buffer of indices of the second channel */ - if ( ch > 0 ) + IF( ch > 0 ) { st->hBstr->ind_list = sts[0]->hBstr->ind_list + sts[0]->hBstr->nb_ind_tot; } - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + IF( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { /*Enable appropriate upadte of tcx_curr_overlap_mode even for uncoded channel index 1*/ L_frameTCX[ch][0] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; L_frameTCX[ch][1] = ( st->core == TCX_10_CORE ) ? st->hTcxEnc->L_frameTCX >> 1 : st->hTcxEnc->L_frameTCX; + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + L_frameTCX[ch][0] = shr( st->hTcxEnc->L_frameTCX, 1 ); + L_frameTCX[ch][1] = shr( st->hTcxEnc->L_frameTCX, 1 ); + } + ELSE + { + L_frameTCX[ch][0] = st->hTcxEnc->L_frameTCX; + move16(); + L_frameTCX[ch][1] = st->hTcxEnc->L_frameTCX; + move16(); + } L_frame[ch][0] = st->L_frame; + move16(); L_frame[ch][1] = st->L_frame; + move16(); } - nSubframes = ( st->hTcxEnc->tcxMode == TCX_20 ) ? 1 : NB_DIV; - for ( n = 0; n < nSubframes; n++ ) + IF( EQ_16( st->hTcxEnc->tcxMode, TCX_20 ) ) + { + nSubframes = 1; + } + ELSE + { + nSubframes = NB_DIV; + } + move16(); + FOR( n = 0; n < nSubframes; n++ ) { /* Update L_frame_past */ st->L_frame_past = L_frame[ch][n]; + move16(); /* Update overlap */ - if ( ( ( ( L_frameTCX[ch][n] == st->hTcxEnc->L_frameTCX >> 1 ) && n > 0 ) || ( st->hTcxCfg->tcx_last_overlap_mode == TRANSITION_OVERLAP ) ) && ( st->hTcxCfg->tcx_curr_overlap_mode == FULL_OVERLAP ) ) + test(); + test(); + test(); + IF( ( ( EQ_16( L_frameTCX[ch][n], shr( st->hTcxEnc->L_frameTCX, 1 ) ) && n > 0 ) || EQ_16( st->hTcxCfg->tcx_last_overlap_mode, TRANSITION_OVERLAP ) ) && EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, FULL_OVERLAP ) ) { st->hTcxCfg->tcx_curr_overlap_mode = ALDO_WINDOW; + move16(); } } @@ -1950,21 +1994,14 @@ void ivas_mdct_quant_coder_fx( * Generate Bitstream *---------------------------------------------------------------*/ - if ( st->mct_chan_mode == MCT_CHAN_MODE_IGNORE ) + if ( EQ_16( st->mct_chan_mode, MCT_CHAN_MODE_IGNORE ) ) { continue; } nbits_start = st->hBstr->nb_bits_tot; - -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); -#endif + move16(); writeTCXparam_fx( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#else - writeTCXparam( st, st->hBstr, NULL, param_core[ch], 0, 0, 0, NULL, p_param[ch], target_bitsTCX10[ch], 1 ); -#endif total_nbbits = st->hBstr->nb_bits_tot - nbits_start - nSubframes * ( NBITS_TCX_GAIN + NOISE_FILL_RANGES * NBITS_NOISE_FILL_LEVEL ); diff --git a/lib_enc/ivas_sns_enc.c b/lib_enc/ivas_sns_enc.c index 1373e8a6238339c24c7b06f06faa6f1068f7a031..e8113d90f3eb08dfb425dbcda194d11fdaf1d629 100644 --- a/lib_enc/ivas_sns_enc.c +++ b/lib_enc/ivas_sns_enc.c @@ -41,6 +41,7 @@ #include "prot_fx.h" #include "rom_com.h" #include "ivas_rom_com.h" +#include "ivas_rom_com_fx.h" #include "ivas_cnst.h" #include "wmc_auto.h" #include "prot_fx_enc.h" @@ -891,6 +892,9 @@ int16_t quantize_sns( if ( is_side ) { +#ifdef IVAS_FLOAT_FIXED + const Word16 *const *side_cdbks_fx = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_fx : ivas_sns_cdbks_side_tcx10_fx; +#endif const float *const *side_cdbks = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20 : ivas_sns_cdbks_side_tcx10; const int16_t *side_levels = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_levels : ivas_sns_cdbks_side_tcx10_levels; @@ -902,7 +906,21 @@ int16_t quantize_sns( nStages = SNS_MSVQ_NSTAGES_SIDE; bits = ( st->core == TCX_20_CORE ) ? ivas_sns_cdbks_side_tcx20_bits : ivas_sns_cdbks_side_tcx10_bits; +#ifdef IVAS_FLOAT_FIXED +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word32 snsQ_fx[32]; + Word16 sns_e; + Word16 weights_fx[24]; + + f2me_buf( snsQ, snsQ_fx, &sns_e, M ); + Scale_sig32( snsQ_fx, M, sns_e - s_max( 0, sns_e ) ); + sns_e = s_max( sns_e, 0 ); + floatToFixed_arr( weights, weights_fx, Q8, 24 ); +#endif + msvq_enc_ivas_fx( side_cdbks_fx, Q15, NULL, NULL, snsQ_fx, sns_e, side_levels, 3, nStages, weights_fx, M, M, 0, NULL, &indices[idxIndices] ); +#else msvq_enc( side_cdbks, NULL, NULL, snsQ, side_levels, 3, nStages, weights, M, M, 0, NULL, &indices[idxIndices] ); +#endif msvq_dec_float( side_cdbks, NULL, NULL, nStages, M, M, &indices[idxIndices], 0, NULL, snsQ, NULL ); } else diff --git a/lib_enc/ivas_stat_enc.h b/lib_enc/ivas_stat_enc.h index d843afc7078ab19786ed7ad26cb4ebaf44952bd3..173ac1be12b2debb2c2bd44b6474f72791158034 100644 --- a/lib_enc/ivas_stat_enc.h +++ b/lib_enc/ivas_stat_enc.h @@ -522,17 +522,17 @@ typedef struct stereo_td_enc_data_structure Word16 tdm_SM_modi_flag; /* Flag that indicates to modify ratio */ Word16 tdm_SM_reset_flag; /* Flag that indicates to reset the parameters for SM mode */ - Word16 tdm_FD2LRTD_SW_cnt; /* Count the number of frames following a FD to LRTD switching */ - Word16 tdm_LRTD_flag; /* LRTD stereo mode flag */ - Word16 prev_fr_LRTD_TD_dec; /* At the beginning of a frame, contains the previous LRTD decision that might have been modified during last frame */ - Word16 tdm_inst_ratio_idx; /* Instantaneous correlation ratio index */ - Word16 tdm_last_inst_ratio_idx; /* previous frame instantaneous correlation ratio index */ - Word16 tdm_vad_hangover_cnt; /* Count the number of frames where hangover_cnt >= 5 in both primary and secondary channel */ - Word16 tdm_ini_frame_cnt; /* Count the number of frame to decide how to evaluate the local VAD of primary and secondary channel */ - Word16 tdm_last_LRTD_frame_cnt; /* Count the number of frame since the last LRTD frame */ - Word16 tdm_last_LRTD_PriCh_cnt; /* Count the number of frame since the primary channel changed */ - Word16 flag_skip_DMX; /* flag that indicates whether the TD downmixing is skipped */ - Word32 tdm_Pri_pitch_buf_fx[NB_SUBFR]; + Word16 tdm_FD2LRTD_SW_cnt; /* Count the number of frames following a FD to LRTD switching */ + Word16 tdm_LRTD_flag; /* LRTD stereo mode flag */ + Word16 prev_fr_LRTD_TD_dec; /* At the beginning of a frame, contains the previous LRTD decision that might have been modified during last frame */ + Word16 tdm_inst_ratio_idx; /* Instantaneous correlation ratio index */ + Word16 tdm_last_inst_ratio_idx; /* previous frame instantaneous correlation ratio index */ + Word16 tdm_vad_hangover_cnt; /* Count the number of frames where hangover_cnt >= 5 in both primary and secondary channel */ + Word16 tdm_ini_frame_cnt; /* Count the number of frame to decide how to evaluate the local VAD of primary and secondary channel */ + Word16 tdm_last_LRTD_frame_cnt; /* Count the number of frame since the last LRTD frame */ + Word16 tdm_last_LRTD_PriCh_cnt; /* Count the number of frame since the primary channel changed */ + Word16 flag_skip_DMX; /* flag that indicates whether the TD downmixing is skipped */ + Word16 tdm_Pri_pitch_buf_fx[NB_SUBFR]; /* Q6 */ } STEREO_TD_ENC_DATA, *STEREO_TD_ENC_DATA_HANDLE; diff --git a/lib_enc/ivas_stereo_mdct_core_enc.c b/lib_enc/ivas_stereo_mdct_core_enc.c index 96108be8b1c354f82ceb9a6d40bbb4dd9601563e..643dfca8c591650dd3f5c25b5a519c1ff90014c1 100644 --- a/lib_enc/ivas_stereo_mdct_core_enc.c +++ b/lib_enc/ivas_stereo_mdct_core_enc.c @@ -1421,9 +1421,36 @@ void stereo_mdct_core_enc( push_next_indice( hBstr, hStereoMdct->split_ratio, SMDCT_NBBITS_SPLIT_RATIO ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + sts = hCPE->hCoreCoder; + st = sts[ch]; + TCX_ENC_HANDLE hTcxEnc = st->hTcxEnc; + st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + st->hTcxEnc->tcx_target_bits_fac = float_to_fix16( st->hTcxEnc->tcx_target_bits_fac_flt, Q14 ); + st->hTcxCfg->sq_rounding = float_to_fix16( st->hTcxCfg->sq_rounding_flt, Q15 ); + if ( st->hTdCngEnc != NULL ) + { + st->hTdCngEnc->CNG_att_fx = float_to_fix16( st->hTdCngEnc->CNG_att, Q12 ); + } + floatToFixed_arr( hTcxEnc->ltpGainMemory, hTcxEnc->ltpGainMemory_fx, Q15, N_LTP_GAIN_MEMS ); + st->hTcxEnc->measuredBwRatio = float_to_fix16( st->hTcxEnc->measuredBwRatio_flt, Q14 ); + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + st->hTcxEnc->tcxltp_gain = (Word16) ( st->hTcxEnc->tcxltp_gain_flt * ( 1 << Q15 ) ); + } +#endif ivas_mdct_quant_coder_fx( hCPE, tnsBits, tnsSize, p_param, 0 ); +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + FOR( ch = 0; ch < CPE_CHANNELS; ch++ ) + { + st = sts[ch]; + st->hTcxEnc->tcx_target_bits_fac_flt = me2f_16( st->hTcxEnc->tcx_target_bits_fac, Q15 - Q14 ); + } +#endif pop_wmops(); return; diff --git a/lib_enc/ivas_stereo_switching_enc.c b/lib_enc/ivas_stereo_switching_enc.c index 165db27f982f92be65fef4a7adb4799a2ffdad4b..c817a366b62acf3749e3ede3204bb8c526496040 100644 --- a/lib_enc/ivas_stereo_switching_enc.c +++ b/lib_enc/ivas_stereo_switching_enc.c @@ -39,6 +39,9 @@ #include "ivas_rom_com.h" #include "assert.h" #include "wmc_auto.h" +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#endif /*-------------------------------------------------------------------* * Function allocate_CoreCoder_enc() @@ -434,6 +437,9 @@ ivas_error stereo_memory_enc( } InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif ResetSHBbuffer_Enc( st->hBWE_TD ); if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) diff --git a/lib_enc/ivas_stereo_td_enc.c b/lib_enc/ivas_stereo_td_enc.c index 6a5866ef52c3f0487d69b72c1759ca1b37d28994..b1ba9d5597687dc38150cc1300eec73548e5820a 100644 --- a/lib_enc/ivas_stereo_td_enc.c +++ b/lib_enc/ivas_stereo_td_enc.c @@ -42,6 +42,9 @@ #ifdef DEBUGGING #include "debug.h" #endif +#ifdef IVAS_FLOAT_FIXED +#include "prot_fx_enc.h" +#endif /*-------------------------------------------------------------------* @@ -347,6 +350,9 @@ ivas_error stereo_set_tdm( } InitSWBencBuffer( st->hBWE_TD ); +#ifdef IVAS_FLOAT_FIXED + InitSWBencBuffer_fx( st ); +#endif ResetSHBbuffer_Enc( st->hBWE_TD ); if ( ( st->hBWE_FD = (FD_BWE_ENC_HANDLE) malloc( sizeof( FD_BWE_ENC_DATA ) ) ) == NULL ) diff --git a/lib_enc/ivas_tcx_core_enc.c b/lib_enc/ivas_tcx_core_enc.c index 21250b5e433cedeaa27acc966d76e81012714970..8f840c4208d428417f3d61deca46acb72dff8c8f 100644 --- a/lib_enc/ivas_tcx_core_enc.c +++ b/lib_enc/ivas_tcx_core_enc.c @@ -239,7 +239,7 @@ void stereo_tcx_core_enc( { #ifdef IVAS_FLOAT_FIXED_CONVERSIONS Word32 pitch_buf_fx[NB_SUBFR16k]; /* 15Q16 */ - + Word16 lsp_new_fx[M], lsp_mid_fx[M]; // Convert gamma to fixed point. if ( (Word16) ( st->gamma_flt * 100 ) == 92 ) { @@ -278,22 +278,20 @@ void stereo_tcx_core_enc( Word16 bits_param_lpc[10], no_param_lpc; /*LPC*/ - float lsf_q[M], lsp_q[M], lsf[M]; - Word16 lsp_q_fx[M], lsf_fx[M]; - float lspmid_q[M]; - Word16 lspmid_q_fx[M]; + float lsf[M]; float A_q[M + 1]; - Word16 A_q_fx[M + 1]; float gainlpc[2][FDNS_NPTS]; - float lsp_tcx_q[M], lsf_tcx_q[M]; + float lsf_tcx_q[M]; + Word16 lsp_q_fx[M], lsf_q_fx[M], lsf_fx[M]; + Word16 lspmid_q_fx[M]; + Word16 A_q_fx[M + 1]; + Word16 gainlpc_fx[2][FDNS_NPTS]; + Word16 gainlpc_e[2][FDNS_NPTS]; Word16 lsp_tcx_q_fx[M], lsf_tcx_q_fx[M]; int16_t tcx_lpc_cdk; Word16 A_q_ind[M + 1]; /*for LPC-based AC*/ Word16 lspq_ind[M]; /*for LPC-based AC*/ -#ifdef MSAN_FIX - set_zero( lspmid_q, M ); -#endif /*TCX-LTP*/ Word16 T_op[3]; @@ -312,6 +310,9 @@ void stereo_tcx_core_enc( assert( st->mdct_sw == MODE1 && "MDCT switching should be in TCX MODE 1\n" ); assert( st->rf_mode == 0 && "Channel aware not supported! " ); + set16_fx( gainlpc_e[0], 0, FDNS_NPTS ); + set16_fx( gainlpc_e[1], 0, FDNS_NPTS ); + no_param_lpc = 0; move16(); n_subframes = 1; @@ -319,6 +320,24 @@ void stereo_tcx_core_enc( hTcxEnc = st->hTcxEnc; +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + Word16 Q_new, q_comm_Bin; + Word16 lsp_fx[M]; + Word16 Aw_fx[NB_SUBFR16k * ( M + 1 )]; + float Aw_flt[NB_SUBFR16k * ( M + 1 )], max = 0; + + st->hTcxEnc->noiseTiltFactor = float_to_fix16( st->hTcxEnc->noiseTiltFactor_flt, Q15 ); + mvr2r( Aw, Aw_flt, st->nb_subfr * ( M + 1 ) ); + floatToFixed_arr( Aw_flt, Aw_fx, Q12, st->nb_subfr * ( M + 1 ) ); + st->hTcxCfg->preemph_fac = float_to_fix16( st->hTcxCfg->preemph_fac_flt, Q15 ); + + for ( int j = 0; j < 6; j++ ) + { + st->clip_var_fx[j] = (Word16) ( st->clip_var[j] * 2.56f ); + } +#endif + + /*--------------------------------------------------------------* * Configuration of TCX *---------------------------------------------------------------*/ @@ -331,6 +350,7 @@ void stereo_tcx_core_enc( /* Subtract the bits of common header */ st->bits_frame_core = extract_l( L_sub( Mpy_32_32( st->total_brate, ONE_BY_FRAMES_PER_SEC_Q31 ), hBstr->nb_bits_tot ) ); + move16(); /*Get Bits of TCX header*/ nbits_header = 3; /* Coder types (2) + last_core for bfi (1) */ @@ -343,6 +363,7 @@ void stereo_tcx_core_enc( } /* bits for TCX overlap mode (1 bit: full, 2 bits: half or no overlap) */ + test(); IF( EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, HALF_OVERLAP ) || EQ_16( st->hTcxCfg->tcx_curr_overlap_mode, MIN_OVERLAP ) ) { nbits_header = add( nbits_header, 2 ); @@ -468,6 +489,298 @@ void stereo_tcx_core_enc( { bitsAvailable = sub( bitsAvailable, st->hIGFEnc->infoTotalBitsWritten ); } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); + floatToFixed_arr( lsp_mid, lsp_mid_fx, Q15, M ); + + q_comm_Bin = s_min( Q_factor_arrL( st->Bin_E_old, 128 ), Q_factor_arrL( st->Bin_E, 256 ) ); + Q_new = q_comm_Bin - ( QSCALE - 2 ); + const Word16 Q_ener = Q_new + Q_SCALE - 2; // Q_new + Q_SCALE -2 + + st->stab_fac_fx = float_to_fix16( st->stab_fac, Q15 ); + floatToFixed_arrL( st->Bin_E_old, st->Bin_E_old_fx, q_comm_Bin, 128 ); + floatToFixed_arrL( st->Bin_E, st->Bin_E_fx, q_comm_Bin, 256 ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + for ( int j = 0; j < M; j++ ) + { + st->lsf_old_fx[j] = (Word16) ( st->lsf_old[j] * 2.56f ); + st->lsf_adaptive_mean_fx[j] = (Word16) ( st->lsf_adaptive_mean[j] * 2.56f ); + st->mem_MA_fx[j] = (Word16) ( st->mem_MA[j] * 2.56f ); + st->mem_AR_fx[j] = (Word16) ( st->mem_AR[j] * 2.56f ); + } + + st->gamma = float_to_fix16( st->gamma_flt, Q15 ); + floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); + floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); + + st->hTcxEnc->spectrum_e[0] = 31 - ( Q_factor_arrL( st->hTcxEnc->spectrum[0], N_MAX ) - 4 ); + floatToFixed_arrL( st->hTcxEnc->spectrum[0], st->hTcxEnc->spectrum_fx[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); +#endif // IVAS_FLOAT_FIXED_CONVERSIONS + + IF( !st->enableTcxLpc ) + { + IF( st->envWeighted ) + { + /* Unweight the envelope */ + E_LPC_lsp_unweight( st->lsp_old_fx, st->lsp_old_fx, st->lsf_old_fx, st->inv_gamma, M ); + st->envWeighted = 0; + move16(); + } + + lpc_quantization_ivas_fx( st, lsp_new_fx, lsp_mid_fx, lsp_q_fx, lsf_q_fx, lspmid_q_fx, AUDIO, 0, /*No acelp->no need to compute any mid-LPC*/ + param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc, Q_ener ); + + /*--------------------------------------------------------------* + * Rate switching + *--------------------------------------------------------------*/ + + IF( st->rate_switching_reset ) + { + Copy( lsp_q_fx, st->lsp_old_fx, M ); + Copy( lsf_q_fx, st->lsf_old_fx, M ); + } + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + st->streaklimit = fix16_to_float( st->streaklimit_fx, Q15 ); + fixedToFloat_arr( lsp_new_fx, lsp_new, Q15, M ); + fixedToFloat_arr( lsp_mid_fx, lsp_mid, Q15, M ); + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + for ( int j = 0; j < M; j++ ) + { + st->lsf_old[j] = (float) st->lsf_old_fx[j] / 2.56f; + st->lsf_adaptive_mean[j] = (float) st->lsf_adaptive_mean_fx[j] / 2.56f; + st->mem_MA[j] = (float) st->mem_MA_fx[j] / 2.56f; + st->mem_AR[j] = (float) st->mem_AR_fx[j] / 2.56f; + } + fixedToFloat_arrL( st->Bin_E_old_fx, st->Bin_E_old, q_comm_Bin, 128 ); + fixedToFloat_arrL( st->Bin_E_fx, st->Bin_E, q_comm_Bin, 256 ); +#endif + + last_core_orig = st->last_core; + move16(); + + FOR( n = 0; n < n_subframes; n++ ) + { + /* Get the envelope */ + IF( st->enableTcxLpc ) + { + tcx_lpc_cdk = tcxlpc_get_cdk( st->hTcxCfg->coder_type ); + + /* NOTE: High MLD observed for the below function. */ + /* Get the envelope corresponding to the current frame */ + E_LPC_int_lpc_tcx( st->lspold_enc_fx, lsp_new_fx, A_q_fx ); + + /* Weight the envelope */ + weight_a_fx( A_q_fx, A_q_fx, st->gamma, M ); + + /* Convert to lsp and lsf */ + E_LPC_a_lsp_conversion( A_q_fx, lsp_fx, lsp_new_fx, M ); + + E_LPC_lsp_lsf_conversion( lsp_fx, lsf_fx, M ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int j = 0; j < M; j++ ) + { + lsf[j] = (float) lsf_fx[j] / 2.56f; + } +#endif + + /* Quantize */ + /* TODO: integrate this. */ + Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->hTcxCfg->coder_type, st->Bin_E ); + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int j = 0; j < M; j++ ) + { + lsf_tcx_q_fx[j] = (Word16) ( lsf_tcx_q[j] * 2.56f ); + } +#endif + + /* Account for consumed bits */ + nbits_lpc[0] = TCXLPC_NUMBITS; + move16(); + IF( param_lpc[0] ) + { + nbits_lpc[0] = add( nbits_lpc[0], TCXLPC_IND_NUMBITS ); + move16(); + } + + /* NOTE: High MLD observed for the below function. */ + /* Convert quantized lsf to lsp and A */ + E_LPC_lsf_lsp_conversion( lsf_tcx_q_fx, lsp_tcx_q_fx, M ); + E_LPC_f_lsp_a_conversion( lsp_tcx_q_fx, A_q_fx, M ); + } + ELSE IF( !st->tcxonly ) + { + E_LPC_int_lpc_tcx( st->lsp_old_fx, lsp_q_fx, A_q_fx ); + } + ELSE IF( EQ_16( add( n, 2 ), n_subframes ) ) /* First TCX10/5 subframe */ + { + E_LPC_f_lsp_a_conversion( lspmid_q_fx, A_q_fx, M ); + } + ELSE + { + E_LPC_f_lsp_a_conversion( lsp_q_fx, A_q_fx, M ); + } + + IF( hTcxEnc->tcx_lpc_shaped_ari ) + { + basop_E_LPC_f_lsp_a_conversion( lspq_ind, A_q_ind, M ); + } + + bitsAvailable = sub( bitsAvailable, nbits_lpc[n] ); + + /* Shape spectrum */ + ShapeSpectrum_ivas_fx( st->hTcxCfg, A_q_fx, gainlpc_fx[n], gainlpc_e[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum_fx[n], &hTcxEnc->spectrum_e[n], hTcxEnc->fUseTns[n], st, NULL ); + + st->last_core = st->core; + move16(); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + fixedToFloat_arr( A_q_fx, A_q, Q14 - norm_s( A_q_fx[0] ), M + 1 ); + fixedToFloat_arrL( st->hTcxEnc->spectrum_fx[0], st->hTcxEnc->spectrum[0], 31 - st->hTcxEnc->spectrum_e[0], N_MAX ); + st->hTcxEnc->noiseTiltFactor_flt = fix16_to_float( st->hTcxEnc->noiseTiltFactor, Q15 ); + if ( st->enablePlcWaveadjust ) + { + st->hTcxCfg->SFM2_flt = fix_to_float( st->hTcxCfg->SFM2, Q31 ); + } + for ( n = 0; n < n_subframes; n++ ) + { + for ( int k = 0; k < FDNS_NPTS; k++ ) + { + gainlpc[n][k] = fix16_to_float( gainlpc_fx[n][k], 15 - gainlpc_e[n][k] ); + } + } +#endif + + st->last_core = last_core_orig; + move16(); + + /*--------------------------------------------------------------------------------* + * Write LPC parameters + *--------------------------------------------------------------------------------*/ + writeLPCparam_fx( st, hBstr, param_lpc, bits_param_lpc, no_param_lpc, &total_nbbits ); + + assert( total_nbbits == ( nbits_lpc[0] + nbits_lpc[1] ) ); + + /*--------------------------------------------------------------* + * Run TCX10/20 Core + *---------------------------------------------------------------*/ + + hTcxEnc->measuredBwRatio = ONE_IN_Q14; + move16(); + + FOR( n = 0; n < n_subframes; n++ ) + { + target_bits[n] = sub( idiv1616( add( bitsAvailable, sub( sub( n_subframes, 1 ), n ) ), n_subframes ), tnsBits[n] ); + move16(); + + test(); + IF( st->enablePlcWaveadjust && EQ_16( n, sub( n_subframes, 1 ) ) ) + { + target_bits[n] = sub( target_bits[n], 1 ); + move16(); + } + IF( n == 0 ) + { + target_bits[n] = sub( target_bits[n], ltpBits ); + move16(); + } + + /* Run TCX20/10 encoder */ + tmp1 = imult1616( n, st->L_frame ); + IF( tmp1 != 0 ) + { + tmp1 = idiv1616( tmp1, n_subframes ); + } + tmp2 = imult1616( n, NPRM_DIV ); + + QuantizeSpectrum_ivas_fx( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + tmp1, target_bits[n], tnsSize[n], param_core + tmp2, n, &hm_cfg[n], vad_hover_flag ); + } +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + for ( int k = 0; k < st->L_frame; k++ ) + { + if ( max < (float) fabs( st->synth_flt[k] ) ) + { + max = (float) fabs( st->synth_flt[k] ); + } + } + if ( max >= 32768.f ) + { + Q_new = -1; + } + else + { + Q_new = norm_s( (Word16) max ) - 2; + } + 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 ); + floatToFixed_arr( st->hLPDmem->old_exc_flt, st->hLPDmem->old_exc, Q_new, L_EXC_MEM ); + st->wspeech_enc[st->L_frame - 1] = (Word16) floatToFixed( st->wspeech_enc_flt[st->L_frame - 1], Q_new ); +#endif + + /* Update tcx overlap mode */ + st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; + move16(); + + coder_tcx_post_ivas_fx( st, st->hLPDmem, st->hTcxCfg, st->synth, A_q_fx, Aw_fx, st->wspeech_enc, Q_new ); + + IF( st->enableTcxLpc ) + { + E_LPC_lsp_unweight( lsp_tcx_q_fx, lsp_q_fx, lsf_q_fx, st->inv_gamma, M ); /* Update lsf_q for encoderSideLossSimulation() */ + } + + /* Update lsp/lsf memory */ + test(); + IF( st->enableTcxLpc && st->core != ACELP_CORE ) + { + /* Update lsf / lsp memory */ + Copy( lsf_tcx_q_fx, st->lsf_old_fx, M ); + Copy( lsp_tcx_q_fx, st->lsp_old_fx, M ); + st->envWeighted = 1; + move16(); + + /* Update ACELP quantizer state */ + lsf_update_memory( st->narrowBand, st->lsf_old_fx, st->mem_MA_fx, st->mem_MA_fx, M ); + st->pstreaklen = 0; + st->streaklimit_fx = 32767; // 1.0 in Q15 + move16(); + move16(); + + /* check resonance for pitch clipping algorithm */ + gp_clip_test_lsf_ivas_fx( st->element_mode, st->core_brate, st->lsf_old_fx, st->clip_var_fx, 0 ); + Copy( st->lsf_old_fx, st->mem_AR_fx, M ); + } + ELSE + { + Copy( lsf_q_fx, st->lsf_old_fx, M ); + Copy( lsp_q_fx, st->lsp_old_fx, M ); + } + +#ifdef IVAS_FLOAT_FIXED_CONVERSIONS + hTcxEnc->measuredBwRatio_flt = fix16_to_float( hTcxEnc->measuredBwRatio, Q14 ); + + fixedToFloat_arr( st->synth, st->synth_flt, Q_new, st->L_frame ); + fixedToFloat_arr( st->hLPDmem->mem_syn_r, st->hLPDmem->mem_syn_r_flt, Q_new + ( Q_new - 1 ), L_SYN_MEM ); + fixedToFloat_arr( st->hLPDmem->mem_syn, st->hLPDmem->mem_syn_flt, Q_new + ( Q_new - 1 ), M ); + fixedToFloat_arr( st->hLPDmem->mem_syn2, st->hLPDmem->mem_syn2_flt, Q_new + ( Q_new - 1 ), M ); + fixedToFloat_arr( st->hLPDmem->syn, st->hLPDmem->syn_flt, Q_new, M + 1 ); + fixedToFloat_arr( st->hLPDmem->old_exc, st->hLPDmem->old_exc_flt, Q_new + ( Q_new - 1 ) + 1, L_EXC_MEM ); + st->hLPDmem->mem_w0_flt = fixedToFloat_16( st->hLPDmem->mem_w0, Q_new ); + + st->streaklimit = fix16_to_float( st->streaklimit_fx, Q15 ); + fixedToFloat_arr( st->lsp_old_fx, st->lsp_old, Q15, M ); + for ( int j = 0; j < 6; j++ ) + { + st->clip_var[j] = (float) st->clip_var_fx[j] / 2.56f; + } + for ( int j = 0; j < M; j++ ) + { + st->lsf_old[j] = (float) st->lsf_old_fx[j] / 2.56f; + st->mem_MA[j] = (float) st->mem_MA_fx[j] / 2.56f; + } +#endif #else TCX_ENC_HANDLE hTcxEnc; int16_t i, n; @@ -634,26 +947,15 @@ void stereo_tcx_core_enc( /*--------------------------------------------------------------* * Envelope Quantization and FDNS *---------------------------------------------------------------*/ -#endif - IF( !st->enableTcxLpc ) + if ( !st->enableTcxLpc ) { -#ifdef IVAS_FLOAT_FIXED - IF( st->envWeighted ) - { - /* Unweight the envelope */ - E_LPC_lsp_unweight( st->lsp_old_fx, st->lsp_old_fx, st->lsf_old_fx, st->inv_gamma, M ); - st->envWeighted = 0; - move16(); - } -#else if ( st->envWeighted ) { /* Unweight the envelope */ E_LPC_lsp_unweight_float( st->lsp_old, st->lsp_old, st->lsf_old, 1.0f / st->gamma_flt ); st->envWeighted = 0; } -#endif lpc_quantization( st, lsp_new, lsp_mid, lsp_q, lsf_q, lspmid_q, AUDIO, 0, /*No acelp->no need to compute any mid-LPC*/ param_lpc, nbits_lpc, bits_param_lpc, &no_param_lpc ); @@ -670,105 +972,7 @@ void stereo_tcx_core_enc( } last_core_orig = st->last_core; - move16(); -#ifdef IVAS_FLOAT_FIXED -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // Float to fix - Word16 lsp_new_fx[M], lsp_fx[M]; - st->gamma = float_to_fix16( st->gamma_flt, Q15 ); - floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); - floatToFixed_arr( st->lspold_enc, st->lspold_enc_fx, Q15, M ); - floatToFixed_arr( st->lsp_old, st->lsp_old_fx, Q15, M ); - if ( !st->enableTcxLpc ) - { - floatToFixed_arr( lsp_q, lsp_q_fx, Q15, M ); - floatToFixed_arr( lspmid_q, lspmid_q_fx, Q15, M ); - } -#endif - FOR( n = 0; n < n_subframes; n++ ) - { - /* Get the envelope */ - IF( st->enableTcxLpc ) - { - tcx_lpc_cdk = tcxlpc_get_cdk( st->hTcxCfg->coder_type ); - - /* NOTE: High MLD observed for the below function. */ - /* Get the envelope corresponding to the current frame */ - E_LPC_int_lpc_tcx( st->lspold_enc_fx, lsp_new_fx, A_q_fx ); - - /* Weight the envelope */ - weight_a_fx( A_q_fx, A_q_fx, st->gamma, M ); - - /* Convert to lsp and lsf */ - E_LPC_a_lsp_conversion( A_q_fx, lsp_fx, lsp_new_fx, M ); - - E_LPC_lsp_lsf_conversion( lsp_fx, lsf_fx, M ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - for ( int j = 0; j < M; j++ ) - { - lsf[j] = (float) lsf_fx[j] / 2.56f; - } -#endif - - /* Quantize */ - /* TODO: integrate this. */ - Q_lsf_tcxlpc( lsf, lsf_tcx_q, lspq_ind, param_lpc, st->narrowBand, tcx_lpc_cdk, st->mem_MA, st->hTcxCfg->coder_type, st->Bin_E ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - for ( int j = 0; j < M; j++ ) - { - lsf_tcx_q_fx[j] = (Word16) ( lsf_tcx_q[j] * 2.56f ); - } -#endif - - /* Account for consumed bits */ - nbits_lpc[0] = TCXLPC_NUMBITS; - move16(); - IF( param_lpc[0] ) - { - nbits_lpc[0] = add( nbits_lpc[0], TCXLPC_IND_NUMBITS ); - move16(); - } - - /* NOTE: High MLD observed for the below function. */ - /* Convert quantized lsf to lsp and A */ - E_LPC_lsf_lsp_conversion( lsf_tcx_q_fx, lsp_tcx_q_fx, M ); - E_LPC_f_lsp_a_conversion( lsp_tcx_q_fx, A_q_fx, M ); - } - ELSE IF( !st->tcxonly ) - { - E_LPC_int_lpc_tcx( st->lsp_old_fx, lsp_q_fx, A_q_fx ); - } - ELSE IF( EQ_16( add( n, 2 ), n_subframes ) ) /* First TCX10/5 subframe */ - { - E_LPC_f_lsp_a_conversion( lspmid_q_fx, A_q_fx, M ); - } - ELSE - { - E_LPC_f_lsp_a_conversion( lsp_q_fx, A_q_fx, M ); - } - - IF( hTcxEnc->tcx_lpc_shaped_ari ) - { - basop_E_LPC_f_lsp_a_conversion( lspq_ind, A_q_ind, M ); - } - - bitsAvailable = sub( bitsAvailable, nbits_lpc[n] ); - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - fixedToFloat_arr( A_q_fx, A_q, Q14 - norm_s( A_q_fx[0] ), M + 1 ); -#endif - - /* Shape spectrum */ - /* TODO: integrate this. */ - ShapeSpectrum( st->hTcxCfg, A_q, gainlpc[n], st->L_frame / n_subframes, st->hTcxCfg->tcx_coded_lines / n_subframes, hTcxEnc->spectrum[n], hTcxEnc->fUseTns[n], st, NULL ); - - st->last_core = st->core; - move16(); - } -#else for ( n = 0; n < n_subframes; n++ ) { /* Get the envelope */ @@ -826,61 +1030,7 @@ void stereo_tcx_core_enc( st->last_core = st->core; } -#endif - -#ifdef IVAS_FLOAT_FIXED - st->last_core = last_core_orig; - move16(); - - /*--------------------------------------------------------------------------------* - * Write LPC parameters - *--------------------------------------------------------------------------------*/ - writeLPCparam_fx( st, hBstr, param_lpc, bits_param_lpc, no_param_lpc, &total_nbbits ); - - assert( total_nbbits == ( nbits_lpc[0] + nbits_lpc[1] ) ); - - /*--------------------------------------------------------------* - * Run TCX10/20 Core - *---------------------------------------------------------------*/ - - hTcxEnc->measuredBwRatio = ONE_IN_Q14; - move16(); - - FOR( n = 0; n < n_subframes; n++ ) - { - target_bits[n] = sub( idiv1616( add( bitsAvailable, sub( sub( n_subframes, 1 ), n ) ), n_subframes ), tnsBits[n] ); - move16(); - - test(); - IF( st->enablePlcWaveadjust && EQ_16( n, sub( n_subframes, 1 ) ) ) - { - target_bits[n] = sub( target_bits[n], 1 ); - move16(); - } - IF( n == 0 ) - { - target_bits[n] = sub( target_bits[n], ltpBits ); - move16(); - } - - /* Run TCX20/10 encoder */ - tmp1 = imult1616( n, st->L_frame ); - IF( tmp1 != 0 ) - { - tmp1 = idiv1616( tmp1, n_subframes ); - } - tmp2 = imult1616( n, NPRM_DIV ); - - QuantizeSpectrum_ivas_fx( st, A_q, A_q_ind, gainlpc[n], st->synth_flt + tmp1, target_bits[n], tnsSize[n], param_core + tmp2, n, &hm_cfg[n], vad_hover_flag ); - } - - /* Update tcx overlap mode */ - st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; - move16(); - // Fix to float - hTcxEnc->measuredBwRatio_flt = fix16_to_float( hTcxEnc->measuredBwRatio, Q14 ); -#else st->last_core = last_core_orig; /*--------------------------------------------------------------------------------* @@ -916,39 +1066,13 @@ void stereo_tcx_core_enc( /* Update tcx overlap mode */ st->hTcxCfg->tcx_last_overlap_mode = st->hTcxCfg->tcx_curr_overlap_mode; -#endif coder_tcx_post( st, A_q, Aw ); -#ifdef IVAS_FLOAT_FIXED - IF( st->enableTcxLpc ) - { -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - Word16 lsf_q_fx[M]; -#endif - E_LPC_lsp_unweight( lsp_tcx_q_fx, lsp_q_fx, lsf_q_fx, st->inv_gamma, M ); /* Update lsf_q for encoderSideLossSimulation() */ -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - // Fixed to float - for ( int j = 0; j < M; j++ ) - { - lsp_q[j] = fix16_to_float( lsp_q_fx[j], Q15 ); - lsf_q[j] = (float) lsf_q_fx[j] / 2.56f; - } -#endif - } -#else if ( st->enableTcxLpc ) { E_LPC_lsp_unweight_float( lsp_tcx_q, lsp_q, lsf_q, 1.0f / st->gamma_flt ); /* Update lsf_q for encoderSideLossSimulation() */ } -#endif - -#ifdef IVAS_FLOAT_FIXED_CONVERSIONS - if ( st->enableTcxLpc ) - { - fixedToFloat_arr( lsp_tcx_q_fx, lsp_tcx_q, Q15, M ); - } -#endif /* Update lsp/lsf memory */ if ( st->enableTcxLpc && st->core != ACELP_CORE ) @@ -971,7 +1095,7 @@ void stereo_tcx_core_enc( mvr2r( lsf_q, st->lsf_old, M ); mvr2r( lsp_q, st->lsp_old, M ); } - +#endif #ifdef IVAS_FLOAT_FIXED_CONVERSIONS // Float to fixed @@ -992,9 +1116,6 @@ void stereo_tcx_core_enc( { floatToFixed_arr( st->hDtxEnc->lspCNG, st->hDtxEnc->lspCNG_fx, Q15, M ); } - - floatToFixed_arr( lsp_new, lsp_new_fx, Q15, M ); - st->preemph_fac = float_to_fix16( st->preemph_fac_flt, Q15 ); st->hTcxCfg->bandwidth = float_to_fix16( st->hTcxCfg->bandwidth_flt, Q15 ); #endif diff --git a/lib_enc/lsf_enc_fx.c b/lib_enc/lsf_enc_fx.c index 058af1b18bbe8e5435d2f93689057f1ec3ca892a..03579f6a8bb239e6bb9d073f2f7b6f582bc90958 100644 --- a/lib_enc/lsf_enc_fx.c +++ b/lib_enc/lsf_enc_fx.c @@ -196,11 +196,11 @@ void lsf_enc_fx( } /* in case of unstable filter in decoder FEC, choose safety-net to help FEC */ - IF( EQ_16( st_fx->next_force_safety_net_fx, 1 ) ) + IF( EQ_16( st_fx->next_force_safety_net, 1 ) ) { force_sf = 1; move16(); - st_fx->next_force_safety_net_fx = 0; + st_fx->next_force_safety_net = 0; move16(); } @@ -266,12 +266,12 @@ void lsf_enc_fx( /* If decoder FEC frame may be unstable force safety-net usage */ IF( ( EQ_16( st_fx->L_frame, L_FRAME16k ) ) && ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( coder_type, GENERIC ) ) ) { - st_fx->next_force_safety_net_fx = 1; + st_fx->next_force_safety_net = 1; move16(); } ELSE IF( ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( st_fx->clas, VOICED_CLAS ) || ( LT_16( st_fx->clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) ) ) ) { - st_fx->next_force_safety_net_fx = 1; + st_fx->next_force_safety_net = 1; move16(); } @@ -463,11 +463,11 @@ void lsf_enc_ivas_fx( } /* in case of unstable filter in decoder FEC, choose safety-net to help FEC */ - IF( EQ_16( st->next_force_safety_net_fx, 1 ) ) + IF( EQ_16( st->next_force_safety_net, 1 ) ) { force_sf = 1; move16(); - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; move16(); } @@ -529,12 +529,12 @@ void lsf_enc_ivas_fx( /* If decoder FEC frame may be unstable force safety-net usage */ IF( ( EQ_16( st->L_frame, L_FRAME16k ) ) && ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( coder_type, GENERIC ) ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); } ELSE IF( ( LT_16( stab, STAB_FAC_LIMIT_FX ) ) && ( EQ_16( st->clas, VOICED_CLAS ) || ( LT_16( st->clas, VOICED_CLAS ) && EQ_16( coder_type, AUDIO ) ) ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; move16(); } diff --git a/lib_enc/lsf_msvq_ma_enc.c b/lib_enc/lsf_msvq_ma_enc.c index c1ce3812c5101972dadc968984d979a11c9194fd..2b57ba975b9e8709d412c20d4bfd41ce87d8ea4c 100644 --- a/lib_enc/lsf_msvq_ma_enc.c +++ b/lib_enc/lsf_msvq_ma_enc.c @@ -39,11 +39,21 @@ #include "cnst.h" #include "ivas_prot.h" #include "prot.h" +#include "prot_fx.h" #include "rom_com.h" #include "rom_enc.h" #include "basop_proto_func.h" #include "wmc_auto.h" +#ifndef swap +#define swap( x, y, type ) \ + { \ + type u__p; \ + u__p = x; \ + x = y; \ + y = u__p; \ + } +#endif /*--------------------------------------------------------------------------* * Local constants @@ -51,7 +61,6 @@ #define kMaxC 8 - /*--------------------------------------------------------------------------* * msvq_encmsvq_stage1_dct_search() * @@ -59,6 +68,292 @@ *--------------------------------------------------------------------------*/ /*! r: (p_max , best candidate sofar ) */ +#ifdef IVAS_FLOAT_FIXED +Word16 msvq_stage1_dct_search_fx( + const Word32 *u_fx, /* i : target exp : u_e */ + const Word16 u_e, /* i : exp for target Q0 */ + const Word16 N, /* i : target length and IDCT synthesis length */ + const Word16 maxC_st1, /* i : number of final stage 1 candidates to provide */ + const DCTTYPE dcttype, /* e.g. DCT_T2_16_XX, DCT_T2_24_XX; */ + const Word16 max_dct_trunc, /* i : maximum of truncation lenghts */ + Word32 *invTrfMatrix_fx, /* i : IDCT synthesis matrix for dim N Q31 */ + const Word16 *midQ_truncQ_fx, /* i : midQ vector */ + const Word32 *dct_scaleF_fx, /* i : global scale factors Q10 */ + const Word16 n_segm, /* i : number of segments */ + const Word16 *cols_per_segment, /* i : remaining length per segment */ + const Word16 *trunc_dct_cols_per_segment, /* i : trunc length per segment */ + const Word16 *entries_per_segment, /* i : number of rows per segment */ + const Word16 *cum_entries_per_segment, /* i : number of cumulative entries */ + const Word8 *const W8Qx_dct_sections[], /* i : Word8(byte) segment table ptrs */ + const Word16 *col_syn_shift[], /* i : columnwise syn shift tables */ + const Word8 *segm_neighbour_fwd, /* i : circular neighbour list fwd */ + const Word8 *segm_neighbour_rev, /* i : circular neighbour list reverse */ + const Word16 npost_check, /* i : number of neigbours to check , should be even */ + Word32 *st1_mse_ptr_fx, /* i : dynRAM buffer for MSEs exp : u_e */ + Word16 *indices_st1_local, /* o : selected cand indices */ + Word32 *st1_syn_vec_ptr_fx, /* i/o: buffer for IDCT24 synthesis i :exp : u_e */ + Word32 *dist1_ptr_fx, /* o : resulting stage 1 MSEs in DCT-N domain */ + Word16 *dist1_ptr_e ) +{ + Word32 dct_target_fx[FDCNG_VQ_DCT_MAXTRUNC]; + Word32 u_mr_fx[FDCNG_VQ_MAX_LEN]; + Word16 dist1_ptr_e_buf[2 * LSFMBEST_MAX]; + Word64 mse_trunc_segm_fx[FDCNG_VQ_DCT_NSEGM]; + Word32 tmp_fx, check_mse; + Word16 tmp_e, check_mse_e; + Word64 mse_fx; /* Word64 in BASOP */ + + Word16 p_max, c, c2, segm, j_full, j, i; + Word16 n_ana, p_mins[2], idx_min[2]; + + Word16 st1_mse_ptr_e[128]; + + const Word8 *cbpW8; + const Word16 *dct_col_shift_tab; + + Word32 *st1_mse_pair_fx; + Word16 *st1_mse_pair_e; + Word16 *st1_idx_pair; + + Word32 tmp2_fx; + Word16 check_ind[FDCNG_VQ_DCT_NPOST]; + assert( ( npost_check % 2 == 0 ) && ( npost_check <= FDCNG_VQ_DCT_NPOST ) ); + + assert( n_segm <= FDCNG_VQ_DCT_NSEGM ); + + n_ana = N; /* VQ stage#1 core is currently always using stored DCT N coeffs */ + move16(); + assert( n_ana >= max_dct_trunc ); /* check for FDCNGVQ WB , SWB, FB operation */ + + /* remove mid stage#1 vector, in original input domain */ + tmp_e = s_max( 12, u_e ); + FOR( i = 0; i < n_ana; i++ ) + { + u_mr_fx[i] = L_sub( L_shl( u_fx[i], sub( u_e, tmp_e ) ), L_shl( midQ_truncQ_fx[i], sub( Q31 - Q10, tmp_e ) ) ); + move32(); + } + + dctT2_N_apply_matrix_fx( (const Word32 *) u_mr_fx, dct_target_fx, s_min( max_dct_trunc, n_ana ), n_ana, invTrfMatrix_fx, max_dct_trunc, dcttype ); // exp : tmp_e + + /* init search state ptr's at the top */ + set32_fx( dist1_ptr_fx, MAX_32, maxC_st1 ); + set16_fx( dist1_ptr_e_buf, 32, maxC_st1 ); + st1_mse_pair_fx = &( dist1_ptr_fx[0] ); /* req. ptr post upd +=2 */ + st1_mse_pair_e = &( dist1_ptr_e_buf[0] ); /* req. ptr post upd +=2 */ + st1_idx_pair = &( indices_st1_local[0] ); /* req. ptr post upd +=2 */ + set64_fx( mse_trunc_segm_fx, 0, n_segm ); + + // set16_fx( mse_trunc_segm_e, u_e, FDCNG_VQ_DCT_NSEGM ); + + FOR( segm = 0; segm < n_segm; segm++ ) + { /* point to a new paired location for each segment */ + p_max = 0; /* req. to point to one of 1 or 0, this init can potentially be omitted here,as p_max is always 1 or 0 */ + move16(); + + /* compute segment common trunction error in dctN domain */ + + FOR( i = 0; i < trunc_dct_cols_per_segment[segm]; i++ ) + { + mse_trunc_segm_fx[segm] = W_mac_32_32( mse_trunc_segm_fx[segm], dct_target_fx[cols_per_segment[segm] + i], dct_target_fx[cols_per_segment[segm] + i] ); + move64(); + } + + cbpW8 = W8Qx_dct_sections[segm]; /* Word8 column variable Qx storage , table ptr init */ + + FOR( j = 0; j < entries_per_segment[segm]; j++ ) + { + /* unweighted segmented search DCT domain loop */ + j_full = add( j, cum_entries_per_segment[segm] ); /* or simply use j_full++ */ + + mse_fx = mse_trunc_segm_fx[segm]; /* init mse with with common mse truncation part, in BASOP a move32() */ + move64(); + + dct_col_shift_tab = col_syn_shift[segm]; /* ptr init */ + + FOR( c2 = 0; c2 < cols_per_segment[segm]; c2++ ) + { +#define WMC_TOOL_SKIP + tmp_fx = L_sub( dct_target_fx[c2], Mpy_32_32( L_shl( cbpW8[c2], add( sub( Q31, tmp_e ), dct_col_shift_tab[c2] ) ), dct_scaleF_fx[1] ) ); /* note: BASOP shift left defined for signed integers */ + LOGIC( 1 ); + SHIFT( 1 ); + ADD( 1 ); /* in BASOP: s_and(for W8->W16), shl(), sub()*/ +#undef WMC_TOOL_SKIP + mse_fx = W_mac_32_32( mse_fx, tmp_fx, tmp_fx ); /* L_mac or L_mac0() square Word16 -> Word32*/ + } + Word16 L_tmp = W_norm( mse_fx ); + st1_mse_ptr_fx[j_full] = W_extract_h( W_lshl( mse_fx, L_tmp ) ); /* save MSE in shared dynamic RAM, move32() in BASOP */ + move32(); + st1_mse_ptr_e[j_full] = sub( shl( tmp_e, 1 ), L_tmp ); + move16(); + +#define WMC_TOOL_SKIP + cbpW8 += cols_per_segment[segm]; /* fixed pointer increment for each segment */ +#undef WMC_TOOL_SKIP + + /* overwrite with a new worst index at p_max */ + + /* Note: The three inner loop if's below are not 100% properly instrumented by WMC tool */ + // if ( st1_mse_ptr_fx[j_full] < st1_mse_pair_fx[p_max] ) /* L_sub */ + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( st1_mse_ptr_fx[j_full], st1_mse_ptr_e[j_full], st1_mse_pair_fx[p_max], st1_mse_pair_e[p_max] ), -1 ) ) /* L_sub */ + { + st1_idx_pair[p_max] = j_full; /* move16, single BASOP */ + move16(); + } /* BASOP 2 ops */ + + IF( EQ_16( st1_idx_pair[p_max], j_full ) ) + { /* idx updated --> also update mse */ + st1_mse_pair_fx[p_max] = st1_mse_ptr_fx[j_full]; /* move32(), single BASOP */ + move32(); + st1_mse_pair_e[p_max] = st1_mse_ptr_e[j_full]; /* move32(), single BASOP */ + move16(); + } /* BASOP 3 ops */ + + /* avoid WC costly candidate list management by always updating p_max, + as we have only a pair in each segment to maintain */ + p_max = 0; + move16(); + if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( st1_mse_pair_fx[0], st1_mse_pair_e[0], st1_mse_pair_fx[1], st1_mse_pair_e[1] ), -1 ) ) /* L_sub()*/ + { + p_max = 1; /* move16() */ + move16(); + } /* BASOP 3 ops ,Note 2 ops possible in BASOP with L_sub and L_lshr */ + + /* Note: logical shift right not available in ANSI-C */ + /* p_max = (st1_mse_pair[0] - st1_mse_pair[1]) ">>>" 31; */ + /* in java logical shift right is available as >>> , in BASOP it is available as L_lshr */ + + /* Cost: weighted sum with cond moves ('if') => 8 in float , 7 in BASOP with L_lshr */ + } /* j in section */ + + st1_mse_pair_fx += 2; /* req. ptr init */ + st1_mse_pair_e += 2; /* req. ptr init */ + st1_idx_pair += 2; /* req. ptr init */ + + } /* next segment */ + + tmp_e = 0; + move16(); + FOR( j = 0; j < maxC_st1; j++ ) + { + /* compute_full mse using stored DCT24 domain MSE's */ + /* calculate MSE from stage1 inner using existing inner DCT domain variables */ + tmp_e = s_max( dist1_ptr_e_buf[j], tmp_e ); + } + + FOR( j = 0; j < maxC_st1; j++ ) + { + /* compute_full mse using stored DCT24 domain MSE's */ + /* calculate MSE from stage1 inner using existing inner DCT domain variables */ + dist1_ptr_fx[j] = L_shr( dist1_ptr_fx[j], sub( tmp_e, dist1_ptr_e_buf[j] ) ); + move32(); + *dist1_ptr_e = tmp_e; + move16(); + } + + + assert( ( maxC_st1 >= 3 ) ); + assert( ( maxC_st1 <= 8 ) ); + + p_max = maximum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* establish current worst candidate for MSVQ stage#2 among all maxC_st1 candidates so far */ + + p_mins[0] = minimum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* find best entry among all maxC_pre */ + move16(); + tmp_fx = dist1_ptr_fx[p_mins[0]]; + move32(); + dist1_ptr_fx[p_mins[0]] = MAX_32; /* exclude 1st */ + move32(); + + p_mins[1] = minimum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* find 2nd best entry */ + move16(); + tmp2_fx = dist1_ptr_fx[p_mins[1]]; + move32(); + dist1_ptr_fx[p_mins[1]] = MAX_32; /* exclude 2nd */ + move32(); + + dist1_ptr_fx[p_mins[0]] = tmp_fx; /* restore 1st */ + move32(); + dist1_ptr_fx[p_mins[1]] = tmp2_fx; /* restore 2nd */ + move32(); + + idx_min[0] = indices_st1_local[p_mins[0]]; + move16(); + idx_min[1] = indices_st1_local[p_mins[1]]; + move16(); + + + /* use global exclusion list to never reselect the two (best) global MSE values sofar */ + st1_mse_ptr_fx[idx_min[0]] = MAX_32; /* move32() */ + move32(); + st1_mse_ptr_e[idx_min[0]] = MAX_16; + move16(); + st1_mse_ptr_fx[idx_min[1]] = MAX_32; /* move32() */ + move32(); + st1_mse_ptr_e[idx_min[1]] = MAX_16; + move16(); + + /* circular MSE-neigbour list in use to potentially replace some segment search candidates */ + /* using both 1st and 2nd best neighbours in fwd and rev directions */ + check_ind[0] = segm_neighbour_fwd[idx_min[0]]; + move16(); + check_ind[1] = segm_neighbour_rev[idx_min[0]]; + move16(); + + check_ind[2] = segm_neighbour_fwd[idx_min[1]]; + move16(); + check_ind[3] = segm_neighbour_rev[idx_min[1]]; + move16(); + + check_ind[4] = segm_neighbour_fwd[check_ind[0]]; + move16(); + check_ind[5] = segm_neighbour_rev[check_ind[1]]; + move16(); + + check_ind[6] = segm_neighbour_fwd[check_ind[2]]; + move16(); + check_ind[FDCNG_VQ_DCT_NPOST - 1] = segm_neighbour_rev[check_ind[3]]; + move16(); + + FOR( i = 0; i < npost_check; i++ ) + { + /* move MSE from DCT-inner loop search to input synthesis domain */ + /* multiplication by fdcng_dct_scaleF[2] to get the float outer loop scale correct in IDCT synthesis domain */ + check_mse = st1_mse_ptr_fx[check_ind[i]]; + move32(); + check_mse_e = st1_mse_ptr_e[check_ind[i]]; + move16(); + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( check_mse, check_mse_e, dist1_ptr_fx[p_max], *dist1_ptr_e ), -1 ) ) + { /* new winner , replace worst */ + dist1_ptr_fx[p_max] = L_shl( check_mse, sub( check_mse_e, *dist1_ptr_e ) ); + move32(); + indices_st1_local[p_max] = check_ind[i]; + move16(); + st1_mse_ptr_fx[check_ind[i]] = MAX_32; /* exclude, BASOP: move32() */ + move32(); + st1_mse_ptr_e[check_ind[i]] = MAX_16; + move16(); + p_max = maximum_32_fx( dist1_ptr_fx, maxC_st1, NULL ); /* establish a new current worst candidate among all maxC */ + } + } + + /* extract the selected stage one vectors in DCT_N domain , apply IDCT_N and scale up */ + /* always extract full length signal(e.g. 24) to be able to update WB(e.g. N_in==21) candidate MSE values */ + /* in the case that only a part of the IDCT N vector is in final use */ + + /* note: synthesis not yet fully parameterized/generalized for other IDCT lengths */ + assert( N == 24 ); + { + FOR( c = 0; c < maxC_st1; c++ ) + { + dec_FDCNG_MSVQ_stage1_fx( indices_st1_local[c], N, invTrfMatrix_fx, dcttype + 1, &( st1_syn_vec_ptr_fx[c * N] ), NULL ); // Q11 : output + scale_sig32( &( st1_syn_vec_ptr_fx[c * N] ), N, sub( 11, s_max( u_e, 12 ) ) ); + } + } + + return p_max; /*ptr to worst performing candidate */ +} +#endif + int16_t msvq_stage1_dct_search( const float *u, /* i : target */ const int16_t N, /* i : target length and IDCT synthesis length */ @@ -304,6 +599,74 @@ int16_t msvq_stage1_dct_recalc_candidates_fdcng_wb( return p_max_local; } +#ifdef IVAS_FLOAT_FIXED +Word16 msvq_stage1_dct_recalc_candidates_fdcng_wb_fx( + const Word32 *st1_syn_vec_ptr_fx, /* i : IDCT24 synthesis vectors */ + const Word16 st1_syn_vec_e, /* i : exp for IDCT24 synthesis vectors */ + const Word32 *u_fx, /* i : target signal */ + const Word16 u_e, /* i : exp for target signal */ + const int16_t maxC_st1, /* i : number of candidates in stage1 */ + Word32 *dist_ptr_fx, /* i/o: updated MSE vector for stage1 */ + Word16 *dist_ptr_e /* i/o: exp for updated MSE vector for stage1 */ +) +{ + Word16 i; + Word16 p_max_local, c; + const Word32 *p2_fx; + Word16 tmp_e; + Word32 res24_fx, high_diff_fx[FDCNG_VQ_MAX_LEN - FDCNG_VQ_MAX_LEN_WB]; + Word64 acc; + Word16 res24_e[FD_CNG_maxC_37bits]; + Word16 dist_e; + + dist_e = *dist_ptr_e; + move16(); + FOR( c = 0; c < maxC_st1; c++ ) + { /* point to extended synthesis part */ + p2_fx = (const Word32 *) &( st1_syn_vec_ptr_fx[c * FDCNG_VQ_MAX_LEN + FDCNG_VQ_MAX_LEN_WB] ); /* ptr init to synthesis candidate c */ + tmp_e = s_max( st1_syn_vec_e, u_e ); + tmp_e = add( tmp_e, 1 ); + /* for stage#1 use "u" instead of the shortened resid[0], to access the extended/extrapolated input target */ + FOR( i = 0; i < FDCNG_VQ_MAX_LEN - FDCNG_VQ_MAX_LEN_WB; i++ ) + { + high_diff_fx[i] = L_sub( L_shr( p2_fx[i], sub( tmp_e, st1_syn_vec_e ) ), L_shr( u_fx[FDCNG_VQ_MAX_LEN_WB + i], sub( tmp_e, u_e ) ) ); + move32(); + } + acc = 0; + move64(); + FOR( i = 0; i < FDCNG_VQ_MAX_LEN - FDCNG_VQ_MAX_LEN_WB; i++ ) + { + acc = W_mac_32_32( acc, high_diff_fx[i], high_diff_fx[i] ); + } + res24_e[c] = tmp_e; + move16(); + tmp_e = W_norm( acc ); + res24_fx = W_extract_h( W_shl( acc, tmp_e ) ); + + res24_e[c] = sub( shl( res24_e[c], 1 ), tmp_e ); + move16(); + + dist_ptr_fx[c] = BASOP_Util_Add_Mant32Exp( dist_ptr_fx[c], *dist_ptr_e, L_negate( res24_fx ), res24_e[c], &res24_e[c] ); /* remove DCT24 high band error contribution */ + move32(); + dist_e = s_max( dist_e, res24_e[c] ); + move16(); + } + + + FOR( c = 0; c < maxC_st1; c++ ) + { + dist_ptr_fx[c] = L_shl( dist_ptr_fx[c], sub( res24_e[c], dist_e ) ); + move32(); + } + *dist_ptr_e = dist_e; + move16(); + /* finally update p_max, as it may potentially change, + due to the core DCT24 search originally optimizing over the longer basis vectors than DCT21 */ + p_max_local = maximum_32_fx( dist_ptr_fx, maxC_st1, NULL ); + + return p_max_local; +} +#endif /*--------------------------------------------------------------------------* @@ -592,6 +955,364 @@ void msvq_enc( return; } +#ifdef IVAS_FLOAT_FIXED +void msvq_enc_ivas_fx( + const Word16 *const *cb, /* i : Codebook (indexed cb[*stages][levels][p]) Q_cb */ + const Word16 Q_cb, /* i : Codebook Q */ + const Word16 dims[], /* i : Dimension of each codebook stage (NULL: full dim.) */ + const Word16 offs[], /* i : Starting dimension of each codebook stage (NULL: 0) */ + const Word32 u_fx[], /* i : Vector to be encoded (prediction and mean removed) (exp : u_e) */ + const Word16 u_e, /* i : Exponent for Vector to be encoded */ + const Word16 *levels, /* i : Number of levels in each stage */ + const Word16 maxC, /* i : Tree search size (number of candidates kept from from one stage to the next == M-best) */ + const Word16 stages, /* i : Number of stages */ + const Word16 w[], /* i : Weights Q8 */ + const Word16 N, /* i : Vector dimension */ + const Word16 maxN, /* i : Codebook dimension */ + const Word16 applyDCT_flag, /* i : applyDCT flag */ + Word32 *invTrfMatrix_fx, /* i/o: synthesis matrix Q31 */ + Word16 Idx[] /* o : Indices */ +) +{ + Word16 j; + const Word16 *cbp, *cb_stage; + Word32 resid_buf_fx[2 * LSFMBEST_MAX * M_MAX], *resid_fx[2]; + Word32 *pTmp, *p1, *p2; + Word16 pTmp_e; + Word16 *indices[2], m, s, c, c2, p_max, i; + Word16 idx_buf[2 * LSFMBEST_MAX * MAX_VQ_STAGES_USED], parents[LSFMBEST_MAX]; + Word32 dist_buf_fx[2 * LSFMBEST_MAX], *dist_fx[2], tmp, en, ss2, Tmp[M_MAX]; + Word16 dist_buf_e[2 * LSFMBEST_MAX], *dist_e[2]; + Word16 tmp_e, tmp_n, en_e; + Word16 resid_e; + Word16 n, maxn, start; + Word64 W_acc; /*64 bit accumulator*/ + + Word32 *st1_syn_vec_ptr_fx = &( resid_buf_fx[1 * LSFMBEST_MAX * M_MAX] ) - FDCNG_VQ_MAX_LEN * maxC; + Word32 *st1_mse_ptr_fx = &( resid_buf_fx[1 * LSFMBEST_MAX * M_MAX] ) - ( levels[0] ); + Word16 indices_st1_local[FDCNG_VQ_DCT_NSEGM * 2]; + + /*----------------------------------------------------------------* + * Allocate memory for previous (parent) and current nodes. + * Parent node is indexed [0], current node is indexed [1]. + *----------------------------------------------------------------*/ + indices[0] = idx_buf; + indices[1] = idx_buf + maxC * stages; /*move16();*/ + /*vr_iset(0, idx_buf, 2*stages*maxC);*/ + set16_fx( idx_buf, 0, (Word16) ( 2 * stages * maxC ) ); + + resid_fx[0] = resid_buf_fx; + resid_fx[1] = resid_buf_fx + maxC * N; /*move16();*/ + + dist_fx[0] = dist_buf_fx; + dist_e[0] = dist_buf_e; + dist_fx[1] = dist_buf_fx + maxC; + dist_e[1] = dist_buf_e + maxC; + + /*vr_iset(0, parents, maxC);*/ + set16_fx( parents, 0, maxC ); + + /*----------------------------------------------------------------* + * LSF weights are normalized, so it is always better to multiply it first + * Set up inital distance vector + *----------------------------------------------------------------*/ + W_acc = W_mult_32_32( Mpy_32_16_1( u_fx[0], shl( w[0], 2 ) ), u_fx[0] ); // 2*Qu - 6 + 1 + FOR( j = 1; j < N; j++ ) + { + W_acc = W_mac_32_32( W_acc, Mpy_32_16_1( u_fx[j], shl( w[j], 2 ) ), u_fx[j] ); // 2*Qu - 6 + 1 + } + + tmp_n = W_norm( W_acc ); + ss2 = W_extract_h( W_shl( W_acc, tmp_n ) ); + tmp_e = sub( add( shl( u_e, 1 ), 5 ), tmp_n ); + + /* Set up inital error (residual) vectors */ + pTmp = resid_fx[1]; /*move16();*/ + resid_e = add( u_e, 1 ); + move16(); + IF( applyDCT_flag != 0 ) + { + resid_e = s_max( u_e, 12 ); + } + FOR( c = 0; c < maxC; c++ ) + { + Copy32( u_fx, pTmp + c * N, N ); + test(); + IF( applyDCT_flag != 0 && LT_16( u_e, 12 ) ) + { + scale_sig32( pTmp + c * N, N, sub( u_e, resid_e ) ); + } + ELSE + { + scale_sig32( pTmp + c * N, N, -1 ); + } + dist_fx[1][c] = ss2; + move32(); + dist_e[1][c] = tmp_e; + move16(); + } + + /* Loop over all stages */ + m = 1; + move16(); + FOR( s = 0; s < stages; s++ ) + { + /* codebook pointer is set to point to first stage */ + cbp = cb[s]; /*Q_cb*/ + cb_stage = cbp; + + /* Set up pointers to parent and current nodes */ + swap( indices[0], indices[1], Word16 * ); + move16(); + move16(); + move16(); + swap( resid_fx[0], resid_fx[1], Word32 * ); + move32(); + move32(); + move32(); + swap( dist_fx[0], dist_fx[1], Word32 * ); + swap( dist_e[0], dist_e[1], Word16 * ); + move32(); + move32(); + move32(); + move16(); + move16(); + move16(); + + /* p_max points to maximum distortion node (worst of best) */ + p_max = 0; + move16(); + + n = N; + move16(); + maxn = maxN; + move16(); + if ( dims ) + { + n = dims[s]; + move16(); + } + if ( dims ) + { + maxn = n; + move16(); + } + + assert( ( maxn % 4 ) == 0 ); + + start = 0; + move16(); + if ( offs ) + { + start = offs[s]; + move16(); + } + + set32_fx( Tmp, 0, start ); + set32_fx( Tmp + start + n, 0, sub( N, add( start, n ) ) ); + + /* Set distortions to a large value */ + FOR( j = 0; j < maxC; j++ ) + { + dist_fx[1][j] = MAX_32; + move32(); + dist_e[1][j] = MAX_16 / 2; + move16(); + } + + test(); + IF( !s && applyDCT_flag != 0 ) /* means: m==1 */ + { + /* stage 1 candidates search in truncated dct24 domain without any weights */ + assert( N == FDCNG_VQ_MAX_LEN || N == FDCNG_VQ_MAX_LEN_WB ); /* 21 and 24 allowed */ + assert( maxC == 2 * FDCNG_VQ_DCT_NSEGM ); + p_max = msvq_stage1_dct_search_fx( u_fx, u_e, FDCNG_VQ_MAX_LEN, maxC, DCT_T2_24_XX, FDCNG_VQ_DCT_MAXTRUNC, (Word32 *) invTrfMatrix_fx, cdk1r_tr_midQ_truncQ_fx, fdcng_dct_scaleF_fx, FDCNG_VQ_DCT_NSEGM, + cdk1_ivas_cols_per_segment, cdk1_ivas_trunc_dct_cols_per_segment, cdk1_ivas_entries_per_segment, cdk1_ivas_cum_entries_per_segment, cdk_37bits_ivas_stage1_W8Qx_dct_sections, + stage1_dct_col_syn_shift, cdk1_ivas_segm_neighbour_fwd, cdk1_ivas_segm_neighbour_rev, FDCNG_VQ_DCT_NPOST, st1_mse_ptr_fx, indices_st1_local, st1_syn_vec_ptr_fx, dist_fx[1], &dist_e[1][0] ); + + /* move established stage#1 indices to the global MSVQ list structure */ + set16_fx( dist_e[1], dist_e[1][0], maxC ); + FOR( c = 0; c < maxC; c++ ) + { + indices[1][c * stages] = indices_st1_local[c]; + move16(); + } + } + ELSE + { + FOR( j = 0; j < levels[s]; j++ ) + { + /* Compute weighted codebook element and its energy */ + en = 0; + move32(); + en_e = 0; + move16(); + W_acc = 0; + move64(); + FOR( c2 = 0; c2 < n; c2++ ) + { + Tmp[start + c2] = L_mult0( shl( w[start + c2], 2 ), cbp[c2] ); + move32(); + W_acc = W_mac_32_16( W_acc, Tmp[start + c2], cbp[c2] ); + } + + tmp_n = W_norm( W_acc ); + + en = W_extract_h( W_shl( W_acc, tmp_n ) ); + en_e = sub( sub( 52, shl( Q_cb, 1 ) ), tmp_n ); + + cbp += maxn; /* pointer is incremented */ + + /* Iterate over all parent nodes */ + FOR( c = 0; c < m; c++ ) + { + pTmp = &resid_fx[0][c * N]; + pTmp_e = resid_e; + move16(); + /*tmp = (*pTmp++) * Tmp[0];*/ + W_acc = W_mult_32_32( pTmp[0], Tmp[0] ); + + FOR( i = 1; i < N; i++ ) + { + W_acc = W_mac_32_32( W_acc, pTmp[i], Tmp[i] ); + } + tmp_n = W_norm( W_acc ); + tmp = W_extract_h( W_shl( W_acc, tmp_n ) ); + tmp_e = sub( add( pTmp_e, sub( Q31 - Q10, Q_cb ) ), tmp_n ); + + + tmp_n = s_max( tmp_e, en_e ); + tmp_n = s_max( dist_e[0][c], tmp_n ); + + IF( NE_16( dist_e[0][c], MAX_16 / 2 ) ) + { + tmp_n = add( tmp_n, 2 ); + tmp = L_sub( L_shl( en, sub( en_e, tmp_n ) ), L_shl( tmp, add( sub( tmp_e, tmp_n ), 1 ) ) ); + tmp = L_add( tmp, L_shl( dist_fx[0][c], sub( dist_e[0][c], tmp_n ) ) ); + } + ELSE + { + tmp = MAX_32 - 1; + move32(); + tmp_n = MAX_16 / 2; + move32(); + } + + IF( EQ_16( BASOP_Util_Cmp_Mant32Exp( tmp, tmp_n, dist_fx[1][p_max], dist_e[1][p_max] ), -1 ) ) + { + /* Replace worst */ + dist_fx[1][p_max] = tmp; + move32(); + dist_e[1][p_max] = tmp_n; + move16(); + indices[1][p_max * stages + s] = j; + move16(); + parents[p_max] = c; + move16(); + + p_max = 0; + move16(); + tmp_e = p_max; + move16(); + + tmp_n = dist_e[1][0]; + move16(); + FOR( c2 = 1; c2 < maxC; c2++ ) + { + if ( EQ_16( BASOP_Util_Cmp_Mant32Exp( dist_fx[1][c2], dist_e[1][c2], dist_fx[1][p_max], dist_e[1][p_max] ), 1 ) ) + { + p_max = c2; + move16(); + } + test(); + if ( GT_16( dist_e[1][c2], tmp_n ) && NE_16( dist_e[1][c2], MAX_16 / 2 ) ) + { + tmp_n = dist_e[1][c2]; + move16(); + } + } + FOR( c2 = 0; c2 < maxC; c2++ ) + { + IF( NE_16( dist_e[1][c2], MAX_16 / 2 ) ) + { + dist_fx[1][c2] = L_shl( dist_fx[1][c2], sub( dist_e[1][c2], tmp_n ) ); + move32(); + dist_e[1][c2] = tmp_n; + move16(); + } + } + } /*IF (L_sub(tmp,dist[1][p_max]) < 0) */ + } /* FOR (c=0; ctc_cnt >= 1 || LE_32( st->last_core_brate, SID_2k40 ) || ( EQ_16( st->next_force_safety_net_fx, 1 ) ) ) + IF( st->tc_cnt >= 1 || LE_32( st->last_core_brate, SID_2k40 ) || ( EQ_16( st->next_force_safety_net, 1 ) ) ) { force_sf = 1; move16(); - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; move16(); } test(); - IF( EQ_16( st->next_force_safety_net_fx, 1 ) && EQ_16( st->Opt_RF_ON, 1 ) ) + IF( EQ_16( st->next_force_safety_net, 1 ) && EQ_16( st->Opt_RF_ON, 1 ) ) { force_sf = 1; - st->next_force_safety_net_fx = 0; + st->next_force_safety_net = 0; } test(); @@ -146,7 +146,7 @@ void lpc_quantization_fx( IF( LT_16( stab, add( STAB_FAC_LIMIT_FX, 6553 /* =0.2 in Q15*/ ) ) && ( EQ_16( coder_type, VOICED ) || EQ_16( coder_type, GENERIC ) ) && EQ_16( st->Opt_RF_ON, 1 ) ) { - st->next_force_safety_net_fx = 1; + st->next_force_safety_net = 1; } lsf2lsp_fx( lsf_q, lsp_q, M, st->sr_core ); @@ -201,6 +201,170 @@ void lpc_quantization_fx( return; } +#ifdef IVAS_FLOAT_FIXED +void lpc_quantization_ivas_fx( + Encoder_State *st, + const Word16 lsp[], /* Q15 */ + const Word16 lspmid[], /* Q15 */ + Word16 lsp_q[], /* Q15 */ + Word16 lsf_q[], /* 14Q1*1.28 */ + Word16 lspmid_q[], /* Q15 */ + const Word16 coder_type, + const Word16 acelp_midLpc, + Word16 param_lpc[], + Word16 nbits_lpc[], + Word16 *bits_param_lpc, + Word16 *no_param_lpc, + const Word16 Q_ener ) +{ + Word16 nb_indices; + Word16 lsfmid_q[M]; /* 14Q1*1.28 */ + Word16 lsfmid_idx; + Word16 i, force_sf; + Word16 lsf[M], lsfmid[M]; + Word16 fec_lsf[M], stab; + + nb_indices = 0; + move16(); + + /****** High-rate LPC quantizer *******/ + + IF( st->lpcQuantization == 0 ) + { + E_LPC_lsp_lsf_conversion( lsp, lsf, M ); + + IF( ( EQ_16( st->core, TCX_10_CORE ) ) ) + { + E_LPC_lsp_lsf_conversion( lspmid, lsfmid, M ); + } + + /* LPC quantizer */ + qlpc_avq_fx( lsf, lsfmid, lsf_q, lsfmid_q, param_lpc, &nb_indices, nbits_lpc, st->core, st->sr_core ); + + E_LPC_lsf_lsp_conversion( lsf_q, lsp_q, M ); + + IF( EQ_16( st->core, TCX_10_CORE ) ) + { + E_LPC_lsf_lsp_conversion( lsfmid_q, lspmid_q, M ); + } + + assert( nb_indices <= NPRM_LPC_NEW ); + } + + /****** Low-rate LPC quantizer *******/ + + ELSE IF( EQ_16( st->lpcQuantization, 1 ) ) + { + + lsp2lsf_fx( lsp, lsf, M, extract_l( st->sr_core ) ); + + force_sf = 0; + move16(); + /*Force safety net when possible in case of transitions*/ + test(); + test(); + IF( st->tc_cnt >= 1 || LE_32( st->last_core_brate, SID_2k40 ) || ( EQ_16( st->next_force_safety_net, 1 ) ) ) + { + force_sf = 1; + move16(); + st->next_force_safety_net = 0; + move16(); + } + + test(); + IF( EQ_16( st->next_force_safety_net, 1 ) && EQ_16( st->Opt_RF_ON, 1 ) ) + { + force_sf = 1; + st->next_force_safety_net = 0; + move16(); + move16(); + } + + test(); + IF( EQ_32( st->sr_core, INT_FS_16k ) && EQ_16( coder_type, UNVOICED ) ) + { + lsf_end_enc_ivas_fx( st, lsf, lsf_q, ENDLSF_NBITS, GENERIC, Q_ener, + force_sf, param_lpc, no_param_lpc, bits_param_lpc, GENERIC, NULL ); + + nb_indices = *no_param_lpc; + move16(); + } + ELSE + { + lsf_end_enc_ivas_fx( st, lsf, lsf_q, ENDLSF_NBITS, coder_type, Q_ener, + force_sf, param_lpc, no_param_lpc, bits_param_lpc, coder_type, NULL ); + + nb_indices = *no_param_lpc; + move16(); + } + + + FEC_lsf_estim_enc_fx( st, fec_lsf ); + + /* FEC - calculate LSF stability */ + stab = lsf_stab_fx( lsf_q, fec_lsf, 0, st->L_frame ); /*Q15*/ + + + test(); + test(); + test(); + IF( LT_16( stab, add( STAB_FAC_LIMIT_FX, 6553 /* =0.2 in Q15*/ ) ) && + ( EQ_16( coder_type, VOICED ) || EQ_16( coder_type, GENERIC ) ) && EQ_16( st->Opt_RF_ON, 1 ) ) + { + st->next_force_safety_net = 1; + move16(); + } + + lsf2lsp_fx( lsf_q, lsp_q, M, st->sr_core ); + + *nbits_lpc = ENDLSF_NBITS; + move16(); + } + ELSE + { + assert( 0 ); + } + + st->seed_acelp = 0; + move16(); + FOR( i = nb_indices - 1; i >= 0; i-- ) + { + st->seed_acelp = extract_l( L_mac0( L_mac0( 13849, shr( st->seed_acelp, 1 ), 31821 ), param_lpc[i], 31821 ) ); + move16(); + } + + /* Mid-frame LPC quantization */ + + test(); + IF( st->lpcQuantization && acelp_midLpc ) + { + + IF( st->rate_switching_reset == 0 ) + { + lsp2lsf_fx( lspmid, lsfmid, M, extract_l( st->sr_core ) ); + + midlsf_enc_fx( st->lsf_old_fx, lsf_q, lsfmid, &lsfmid_idx, M, st->Bin_E_old_fx, Q_ener, (Word8) st->narrowBand, st->sr_core, coder_type ); + param_lpc[nb_indices] = lsfmid_idx; + move16(); + nb_indices = add( nb_indices, 1 ); + midlsf_dec( st->lsf_old_fx, lsf_q, lsfmid_idx, lsfmid_q, coder_type, NULL, 0, 1 ); + + reorder_lsf_fx( lsfmid_q, LSF_GAP_MID_FX, M, st->sr_core ); + lsf2lsp_fx( lsfmid_q, lspmid_q, M, st->sr_core ); + } + ELSE + { + param_lpc[nb_indices] = 0; + move16(); + nb_indices = add( nb_indices, 1 ); + } + } + + + return; +} +#endif + /*-------------------------------------------------------------------* * Unified_weighting() diff --git a/lib_enc/stat_enc.h b/lib_enc/stat_enc.h index 9c25e47114933744f6a482eab23cca3373505dca..74d248f1c25e800e9844df4758ef63dc8df2cfb6 100644 --- a/lib_enc/stat_enc.h +++ b/lib_enc/stat_enc.h @@ -1266,19 +1266,24 @@ typedef struct sc_vbr_enc_structure int16_t pattern_m; int16_t patterncount; int16_t Last_Resort; - int16_t numactive; /* keep the count of the frames inside current 600 frame block */ - float sum_of_rates; /* sum of the rates of past 600 active frames */ - float global_avr_rate; /* global rate up to current time. recorded a (rate in kbps) * 6000 */ - Word32 sum_of_rates_fx; /* sum of the rates of past 600 active frames*/ - Word32 global_avr_rate_fx; /* global rate upto current time. recorded a (rate in kbps) *6000*/ - int16_t global_frame_cnt; /* 600 active frame block count. Used to update the global rate */ + int16_t numactive; /* keep the count of the frames inside current 600 frame block */ +#ifndef IVAS_FLOAT_FIXED + float sum_of_rates; /* sum of the rates of past 600 active frames */ + float global_avr_rate; /* global rate up to current time. recorded a (rate in kbps) * 6000 */ +#else + Word32 sum_of_rates_fx; /*Q=13 sum of the rates of past 600 active frames*/ + Word32 global_avr_rate_fx; /*Q=13 global rate upto current time. recorded a (rate in kbps) *6000*/ +#endif + int16_t global_frame_cnt; /* 600 active frame block count. Used to update the global rate */ int16_t set_ppp_generic; int16_t avoid_HQ_VBR_NB; int16_t vbr_generic_ho; int16_t Local_VAD; int16_t last_7k2_coder_type; - Word16 frame_cnt_ratewin_fx; /* keep count of how many ratewin (600) windows */ +#if 0 + Word16 frame_cnt_ratewin_fx; /* keep count of how many ratewin (600) windows. global_frame_cnt is used instead */ +#endif } SC_VBR_ENC_DATA, *SC_VBR_ENC_HANDLE; @@ -1328,7 +1333,7 @@ typedef struct td_bwe_enc_structure Word16 cldfbHBLT; /* states for the filters used in generating SHB excitation from WB excitation*/ float mem_csfilt[2]; - Word32 mem_csfilt_fx[2]; + Word32 mem_csfilt_fx[2]; /* Q(prev_Q_bwe_exc) */ float mem_shb_res[MAX_LEN_MA_FILTER]; /* old SHB residual signal */ float old_EnvSHBres[L_FRAME4k]; /* old TD envelope of the SHB residual signal */ float old_mean_EnvSHBres; /* energy of the last subframe of the SHB residual signal from previous frame */ @@ -1341,10 +1346,10 @@ typedef struct td_bwe_enc_structure /* states for the filters used in generating SHB signal from SHB excitation*/ float state_syn_shbexc[L_SHB_LAHEAD]; float state_lpc_syn[LPC_SHB_ORDER]; - float old_bwe_exc[PIT16k_MAX * 2]; /* old excitation */ - Word16 state_syn_shbexc_fx[L_SHB_LAHEAD]; - Word16 state_lpc_syn_fx[LPC_SHB_ORDER]; - Word16 old_bwe_exc_fx[PIT16k_MAX * 2]; /*Q_exc*/ + float old_bwe_exc[PIT16k_MAX * 2]; /* old excitation */ + Word16 state_syn_shbexc_fx[L_SHB_LAHEAD]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 state_lpc_syn_fx[LPC_SHB_ORDER]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 old_bwe_exc_fx[PIT16k_MAX * 2]; /*Q_exc*/ int16_t bwe_seed[2]; float bwe_non_lin_prev_scale; float old_bwe_exc_extended[NL_BUFF_OFFSET]; @@ -1354,14 +1359,14 @@ typedef struct td_bwe_enc_structure float mem_genSHBexc_filt_down_wb2[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; float mem_genSHBexc_filt_down_wb3[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; float mem_genSHBexc_filt_down_shb[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word32 bwe_non_lin_prev_scale_fx; /*Q30*/ - Word16 old_bwe_exc_extended_fx[NL_BUFF_OFFSET]; - Word16 syn_overlap_fx[L_SHB_LAHEAD]; - Word16 decim_state1_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 decim_state2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 mem_genSHBexc_filt_down_wb2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 mem_genSHBexc_filt_down_wb3_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; - Word16 mem_genSHBexc_filt_down_shb_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; + Word32 bwe_non_lin_prev_scale_fx; /* Q30 */ + Word16 old_bwe_exc_extended_fx[NL_BUFF_OFFSET]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 syn_overlap_fx[L_SHB_LAHEAD]; /* Q0 not sure */ + Word16 decim_state1_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(-1) */ + Word16 decim_state2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(-1) */ + Word16 mem_genSHBexc_filt_down_wb2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 mem_genSHBexc_filt_down_wb3_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(prev_Q_bwe_exc - 16) */ + Word16 mem_genSHBexc_filt_down_shb_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; /* Q(prev_Q_bwe_exc - 16) */ float elliptic_bpf_2_48k_mem[4][4]; float prev_fb_energy; @@ -1388,7 +1393,7 @@ typedef struct td_bwe_enc_structure float fb_state_lpc_syn[LPC_SHB_ORDER]; float fb_tbe_demph; float tilt_mem; - Word16 prev_wb_GainShape; + Word16 prev_wb_GainShape; /* Q15 */ Word16 swb_lsp_prev_interp_fx[LPC_SHB_ORDER]; Word16 fb_state_lpc_syn_fx[LPC_SHB_ORDER]; Word16 prev_Q_bwe_exc_fb; @@ -1453,14 +1458,14 @@ typedef struct fd_bwe_enc_structure float mem_deemph_old_syn; Word16 new_input_hp_fx[NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS )]; Word16 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS )]; - Word16 old_input_wb_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS )]; + Word16 old_input_wb_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS )]; /* Q(-1) */ Word16 old_input_lp_fx[NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_NS )]; Word16 old_syn_12k8_16k_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS )]; Word16 old_fdbwe_speech_fx[L_FRAME48k]; Word16 mem_deemph_old_syn_fx; int16_t prev_mode; float old_wtda_swb[L_FRAME48k]; - Word16 L_old_wtda_swb_fx[L_FRAME48k]; + Word16 L_old_wtda_swb_fx[L_FRAME48k]; /* Q(Q_old_wtda) */ Word16 prev_Q_input_lp; int16_t prev_L_swb_norm1; float prev_global_gain; @@ -1469,6 +1474,7 @@ typedef struct fd_bwe_enc_structure float EnergyLF; Word32 EnergyLF_fx; float mem_old_wtda_swb; + Word16 mem_old_wtda_swb_fx; /* Q(-1) */ } FD_BWE_ENC_DATA, *FD_BWE_ENC_HANDLE; @@ -1839,7 +1845,7 @@ typedef struct enc_core_structure Word16 lsp_old1_fx[M]; /* old unquantized LSP vector at the end of the frame */ Word16 lsf_old1_fx[M]; /* old LSF vector at the end of the frame */ Word16 lsp_old_fx[M]; /* old LSP vector at the end of the frame */ // Q15 - Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame */ + Word16 lsf_old_fx[M]; /* old LSF vector at the end of the frame Qlog2(2.56) */ Word16 lsp_old16k_fx[M]; /* old LSP vector at the end of the frame @16kHz */ Word16 lspold_enc_fx[M]; /* old LSP vector at the end of the frame @16kHz */ @@ -1886,15 +1892,15 @@ typedef struct enc_core_structure int16_t GSC_IVAS_mode; GSC_ENC_HANDLE hGSCEnc; - int16_t Last_pulse_pos; /* FEC - last position of the first glottal pulse in the frame */ - float lsfoldbfi0[M]; /* FEC - LSF vector of the previous frame */ - float lsfoldbfi1[M]; /* FEC - LSF vector of the past previous frame */ - float lsf_adaptive_mean[M]; /* FEC - adaptive mean LSF vector for FEC */ - Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame */ - Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame */ - Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC */ - int16_t next_force_safety_net; /* FEC - flag to force safety net in next frame */ - Word16 next_force_safety_net_fx; /* FEC - flag to force safety net in next frame */ + int16_t Last_pulse_pos; /* FEC - last position of the first glottal pulse in the frame */ + float lsfoldbfi0[M]; /* FEC - LSF vector of the previous frame */ + float lsfoldbfi1[M]; /* FEC - LSF vector of the past previous frame */ + float lsf_adaptive_mean[M]; /* FEC - adaptive mean LSF vector for FEC */ + Word16 lsfoldbfi0_fx[M]; /* FEC - LSF vector of the previous frame */ + Word16 lsfoldbfi1_fx[M]; /* FEC - LSF vector of the past previous frame */ + Word16 lsf_adaptive_mean_fx[M]; /* FEC - adaptive mean LSF vector for FEC */ + int16_t next_force_safety_net; /* FEC - flag to force safety net in next frame */ + // Word16 next_force_safety_net_fx; /* FEC - flag to force safety net in next frame */ int16_t uv_count; /* Stationary noise UV modification - unvoiced counter */ int16_t act_count; /* Stationary noise UV modification - activation counter */ diff --git a/lib_enc/stat_noise_uv_enc_fx.c b/lib_enc/stat_noise_uv_enc_fx.c index 809f4e5b36359234c5c2e6b69e177474a796050b..e741149c28c8bb9d188f776ac2ed4d2089ff8f59 100644 --- a/lib_enc/stat_noise_uv_enc_fx.c +++ b/lib_enc/stat_noise_uv_enc_fx.c @@ -11,6 +11,10 @@ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ +#ifdef IVAS_FLOAT_FIXED +#include "prot.h" +#endif + /*======================================================================*/ /* FUNCTION : stat_noise_uv_enc_fx */ /*----------------------------------------------------------------------*/ @@ -116,3 +120,88 @@ void stat_noise_uv_enc_fx( return; } + + +void stat_noise_uv_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: state structure */ + const Word32 *LepsP, /* i : LP prediction errors Q=Qx*/ + const Word16 *isp_new, /* i : immittance spectral pairs at 4th sfr Q=15*/ + const Word16 *isp_mid, /* i : immittance spectral pairs at 2nd sfr Q=15*/ + Word16 *Aq, /* i : A(z) quantized for the 4 subframes Q=12 */ + Word16 *exc2, /* i/o: excitation buffer Q=Q_stat_noise */ + const Word16 uc_two_stage_flag, /* o : flag undicating two-stage UC */ + Word16 Q_new ) +{ + Word16 noisiness = 0; + move16(); + Word16 num, den, expn, expd; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + test(); + test(); + test(); + IF( ( EQ_16( st_fx->coder_type, UNVOICED ) && uc_two_stage_flag == 0 ) || ( EQ_16( st_fx->coder_type, INACTIVE ) && LE_32( st_fx->core_brate, ACELP_9k60 ) ) ) + { + + /*-----------------------------------------------------------------* + * Calculate and write the noisiness parameter + *-----------------------------------------------------------------*/ + /* epsP[2] is located in LepsP[0] and epsP[16] in LepsP[1] */ + expn = sub( norm_l( LepsP[0] ), 1 ); +#ifdef BASOP_NOGLOB + num = extract_h( L_shl_o( LepsP[0], expn, &Overflow ) ); /*expn-16*/ +#else + num = extract_h( L_shl( LepsP[0], expn ) ); /*expn-16*/ +#endif + expd = norm_l( LepsP[1] ); +#ifdef BASOP_NOGLOB + den = extract_h( L_shl_o( LepsP[1], expd, &Overflow ) ); /*expd-16*/ +#else + den = extract_h( L_shl( LepsP[1], expd ) ); /*expd-16*/ +#endif + num = div_s( num, den ); /*expn-expd+15*/ +#ifdef BASOP_NOGLOB + num = shr_o( num, add( sub( expn, expd ), 5 ), &Overflow ); /*Q10*/ +#else + num = shr( num, add( sub( expn, expd ), 5 ) ); /*Q10*/ +#endif + num = sub( num, 1024 ); /*num - 1*/ + + test(); + IF( NE_16( st_fx->bwidth, NB ) ) + { + /* WB case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*2 * 32);*/ + noisiness = shr( num, 4 ); /*Q10 x64 -> Q0 */ + } + ELSE IF( EQ_16( st_fx->coder_type, INACTIVE ) && EQ_16( st_fx->bwidth, NB ) ) + { + /* NB GSC case */ + /* noisiness = (Word16)(((epsP[2] / epsP[16]) - 1)*.25f * 32);*/ + noisiness = shr( num, 4 + 3 ); /*Q10 x8 -> Q0 */ + } + ELSE + { + /* NB case */ + noisiness = shr( num, 4 + 2 ); /*Q16 x16 -> Q0 */ + } + + noisiness = s_max( noisiness, 0 ); + noisiness = s_min( noisiness, 31 ); + + push_indice( st_fx->hBstr, IND_NOISINESS, noisiness, 5 ); + } + + /*-----------------------------------------------------------------* + * Modify the stationary noise excitation signal + *-----------------------------------------------------------------*/ + + stat_noise_uv_mod_ivas_fx( st_fx->coder_type, noisiness, st_fx->lsp_old_fx, isp_new, isp_mid, Aq, exc2, Q_new, 0, &st_fx->ge_sm_fx, &st_fx->uv_count, &st_fx->act_count, + st_fx->lspold_s_fx, &st_fx->noimix_seed, &st_fx->min_alpha_fx, &st_fx->exc_pe_fx, + st_fx->core_brate, st_fx->bwidth, &st_fx->Q_stat_noise, &st_fx->Q_stat_noise_ge ); + + + return; +} diff --git a/lib_enc/swb_bwe_enc_fx.c b/lib_enc/swb_bwe_enc_fx.c index 1167ad1afcbf48c6f7539e48a46a6cbb5a5d2b55..d3e56a079a50715e772235e8c98709c1d1024735 100644 --- a/lib_enc/swb_bwe_enc_fx.c +++ b/lib_enc/swb_bwe_enc_fx.c @@ -34,6 +34,21 @@ static Word16 SWB_BWE_encoding_fx( Word16 Q_synth, Word16 Q_synth_lf ); +static Word16 SWB_BWE_encoding_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i/o: delayed original input signal at 32kHz (might be rescaled)*/ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf ); + static void delay_input_signal_fx( Word16 *old_sig, Word16 *cur_sig, @@ -109,6 +124,7 @@ static void delay_input_signal_fx( * * WB BWE encoder *-------------------------------------------------------------------*/ + void wb_bwe_enc_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ const Word16 *new_wb_speech_fx, /* i : original input signal at 16kHz */ @@ -180,19 +196,98 @@ void wb_bwe_enc_fx( return; } +/*-------------------------------------------------------------------* + * wb_bwe_enc_ivas_fx() + * + * WB BWE encoder + *-------------------------------------------------------------------*/ + +void wb_bwe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *new_wb_speech_fx /* i : original input signal at 16kHz */ +) +{ + Word16 mode = 0; + Word16 Sample_Delay_WB_BWE; + Word16 old_input_fx[NS2SA( 16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME16k]; + Word32 yorig_32[L_FRAME16k]; + Word16 yorig_fx[L_FRAME16k]; + Word32 L_wtda_synth_fx[2 * L_FRAME16k]; + Word16 *new_input_fx; /* pointer to original input signal */ + Word16 scl, new_input_fx_exp; + Word16 Q_synth; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + Word16 WB_fenv_fx[SWB_FENV]; + move16(); + + IF( GT_32( st_fx->extl_brate, 0 ) ) + { + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + set16_fx( old_input_fx, 0, NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME16k ); + Sample_Delay_WB_BWE = NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + + new_input_fx = old_input_fx + Sample_Delay_WB_BWE; + Copy( hBWE_FD->old_input_wb_fx, old_input_fx, Sample_Delay_WB_BWE ); + Copy( new_wb_speech_fx, new_input_fx, L_FRAME16k ); + Copy( old_input_fx + L_FRAME16k, hBWE_FD->old_input_wb_fx, Sample_Delay_WB_BWE ); + + /*---------------------------------------------------------------------*/ + /* WB BWE encoding */ + + + /* MDCT of the core synthesis signal */ + /*---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + move16(); + + wtda_fx( old_input_fx, &new_input_fx_exp, L_wtda_synth_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + L_FRAME16k ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx( L_wtda_synth_fx, yorig_32, 0, L_FRAME16k, &new_input_fx_exp, st_fx->element_mode ); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub( 16 + 8 /*MAX_Q_NEW_INPUT*/, new_input_fx_exp ); + /* Possible to Upscale? */ + IF( scl > 0 ) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32( yorig_32, L_FRAME16k ); + + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min( Q_synth, scl ); + } + Copy_Scale_sig32_16( yorig_32, yorig_fx, L_FRAME16k, scl ); + Q_synth = add( sub( new_input_fx_exp, 16 ), scl ) - 1; + + mode = WB_BWE_encoding_ivas_fx( st_fx, yorig_fx, WB_fenv_fx, Q_synth, Q_synth ); + push_indice( st_fx->hBstr, IND_WB_CLASS, mode - 2, 1 ); + } + + hBWE_FD->prev_mode = mode; + move16(); + + return; +} + /*-------------------------------------------------------------------* * swb_bwe_enc() * * SWB BWE encoder (only for 32kHz signals) *-------------------------------------------------------------------*/ -void swb_bwe_enc_fx( +void swb_bwe_enc_ivas_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ + const int16_t last_element_mode, /* i : last element mode */ Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ - const Word16 coder_type, /* i : coding type */ Word16 Q_shb_speech, Word16 Q_slb_speech ) { @@ -215,19 +310,23 @@ void swb_bwe_enc_fx( Word16 Sample_Delay_HP; Word16 Sample_Delay_LP; Word16 idxGain = 0; - + move16(); Word16 Q_synth_hf, Q_synth, Q_shb; Word16 tilt_nb_fx; Word16 SWB_fenv_fx[SWB_FENV]; Word32 ener_low_fx; - Word32 energy_fbe_fb_fx = 0; + Word32 energy_fbe_fb_fx; Word16 fb_ener_adjust_fx; Word16 ener_adjust_quan_fx = 0; + move16(); #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + Word16 fb_band_begin; FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; /*---------------------------------------------------------------------* @@ -236,12 +335,16 @@ void swb_bwe_enc_fx( IF( EQ_16( st_fx->extl, FB_BWE ) ) { inner_frame = L_FRAME48k; + move16(); inner_Fs = 48000; + move16(); } ELSE { inner_frame = L_FRAME32k; + move16(); inner_Fs = 32000; + move16(); } set16_fx( old_input_fx, 0, add( NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ), inner_frame ) ); @@ -250,17 +353,50 @@ void swb_bwe_enc_fx( { Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS - L_MEM_RECALC_TBE_NS ); + } Sample_Delay_LP = NS2SA( 12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ); - delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_12k8_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + IF( st_fx->element_mode > EVS_MONO ) + { + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA( inner_Fs, DELAY_FIR_RESAMPL_NS ) ); + Sample_Delay_HP = sub( Sample_Delay_HP, NS2SA( 16000, DELAY_FIR_RESAMPL_NS ) ); + + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + Copy( old_input_12k8_fx + L_INP_MEM - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); + Copy( hBWE_TD->old_speech_shb_fx + L_LOOK_16k + L_SUBFR16k - Sample_Delay_HP, new_input_hp_fx, Sample_Delay_HP ); + } + } + Copy( hBWE_FD->old_input_lp_fx, old_input_lp_fx, Sample_Delay_LP ); + Copy( old_input_12k8_fx + L_INP_MEM, &old_input_lp_fx[Sample_Delay_LP], L_FRAME - Sample_Delay_LP ); + Copy( old_input_12k8_fx + L_INP_MEM + L_FRAME - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); } ELSE { Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS - L_MEM_RECALC_TBE_NS ); + } Sample_Delay_LP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ); + IF( st_fx->element_mode > EVS_MONO ) + { + Sample_Delay_SWB_BWE = sub( Sample_Delay_SWB_BWE, NS2SA( inner_Fs, DELAY_FIR_RESAMPL_NS ) ); + Sample_Delay_HP = sub( Sample_Delay_HP, NS2SA( 16000, DELAY_FIR_RESAMPL_NS ) ); - delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_16k_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME16k, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + Copy( old_input_16k_fx + L_INP_MEM - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); + Copy( hBWE_TD->old_speech_shb_fx + L_LOOK_16k + L_SUBFR16k - Sample_Delay_HP, new_input_hp_fx, Sample_Delay_HP ); + } + } + Copy( hBWE_FD->old_input_lp_fx, old_input_lp_fx, Sample_Delay_LP ); + Copy( old_input_16k_fx + L_INP_MEM, &old_input_lp_fx[Sample_Delay_LP], L_FRAME16k - Sample_Delay_LP ); + Copy( old_input_16k_fx + L_INP_MEM + L_FRAME16k - Sample_Delay_LP, hBWE_FD->old_input_lp_fx, Sample_Delay_LP ); } Copy( hBWE_FD->new_input_hp_fx, new_input_hp_fx, Sample_Delay_HP ); @@ -285,13 +421,29 @@ void swb_bwe_enc_fx( * FB BWE encoding *---------------------------------------------------------------------*/ new_input_fx_exp = 0; + move16(); + test(); + IF( ( EQ_16( st_fx->idchan, 1 ) ) && ( EQ_16( last_element_mode, IVAS_CPE_DFT ) ) ) + { + FOR( i = 0; i < inner_frame; i++ ) + { + hBWE_FD->L_old_wtda_swb_fx[i] = mult_r( hBWE_FD->L_old_wtda_swb_fx[i], div_s( i, inner_frame ) ); + move16(); + } + } /* MDCT of the core synthesis signal */ wtda_fx( old_input_fx, &new_input_fx_exp, L_old_input_fx, hBWE_FD->L_old_wtda_swb_fx, &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ inner_frame ); /* DCT of the ACELP core synthesis */ - direct_transform_fx( L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp, /*st_fx->element_mode*/ EVS_MONO ); + direct_transform_fx( L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp, st_fx->element_mode ); + + /* high-band gain control in case of BWS */ + IF( st_fx->bwidth_sw_cnt > 0 ) + { + v_multc_fixed_16( &yorig_32[L_FRAME16k], div_s( st_fx->bwidth_sw_cnt, BWS_TRAN_PERIOD ), &yorig_32[L_FRAME16k], sub( inner_frame, L_FRAME16k ) ); + } /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ scl = sub( 16 + 8, new_input_fx_exp ); @@ -306,7 +458,6 @@ void swb_bwe_enc_fx( } Copy_Scale_sig32_16( yorig_32, yorig_fx, inner_frame, scl ); Q_synth = add( sub( new_input_fx_exp, 16 ), scl ); - max = 0; move16(); Q_synth_hf = 0; @@ -335,25 +486,27 @@ void swb_bwe_enc_fx( { exp = norm_s( max ); } - Copy_Scale_sig( &yorig_fx[scl], &yorig_fx[scl], sub( inner_frame, scl ), exp ); Q_synth_hf = add( exp, Q_synth ); + test(); IF( EQ_16( st_fx->last_extl, SWB_BWE ) || EQ_16( st_fx->last_extl, FB_BWE ) ) { exp = norm_l( st_fx->EnergyLT_fx ); - IF( add( st_fx->EnergyLT_fx_exp, exp ) > shl( sub( Q_synth_hf, 4 ), 1 ) ) + IF( GT_16( add( st_fx->EnergyLT_fx_exp, exp ), shl( sub( Q_synth_hf, 4 ), 1 ) ) ) { Q_shb = sub( Q_synth_hf, 4 ); st_fx->EnergyLT_fx = L_shr( st_fx->EnergyLT_fx, sub( st_fx->EnergyLT_fx_exp, shl( Q_shb, 1 ) ) ); + move32(); } ELSE { Q_shb = shr( add( st_fx->EnergyLT_fx_exp, exp ), 1 ); - IF( s_and( exp, 0x0001 ) == 1 ) + IF( EQ_16( s_and( exp, 0x0001 ), 1 ) ) { exp = sub( exp, 1 ); } st_fx->EnergyLT_fx = L_shl( st_fx->EnergyLT_fx, exp ); + move32(); } } ELSE @@ -361,30 +514,26 @@ void swb_bwe_enc_fx( Q_shb = sub( Q_synth_hf, 4 ); } Copy_Scale_sig( new_input_hp_fx, new_input_hp_fx, L_FRAME16k, sub( Q_shb, Q_shb_speech ) ); - /* SWB BWE encoding */ - IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) - { - SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, - SWB_fenv_fx, tilt_nb_fx, 80, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); - } - ELSE - { - SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, - SWB_fenv_fx, tilt_nb_fx, 6, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); - } /* FB BWE encoding */ IF( EQ_16( st_fx->extl, FB_BWE ) ) { + fb_band_begin = FB_BAND_BEGIN; + move16(); + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + fb_band_begin = FB_BAND_BEGIN_12k8; + move16(); + } energy_fbe_fb_fx = L_deposit_l( 0 ); - FOR( i = FB_BAND_BEGIN; i < FB_BAND_END; i++ ) + FOR( i = fb_band_begin; i < FB_BAND_END; i++ ) { tmp = shr( yorig_fx[i], 4 ); energy_fbe_fb_fx = L_mac0( energy_fbe_fb_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ } ener_low_fx = 0; move16(); - FOR( i = FB_BAND_BEGIN - FB_BAND_WIDTH; i < FB_BAND_BEGIN; i++ ) + FOR( i = fb_band_begin - FB_BAND_WIDTH; i < fb_band_begin; i++ ) { tmp = shr( yorig_fx[i], 4 ); ener_low_fx = L_mac0( ener_low_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ @@ -398,7 +547,7 @@ void swb_bwe_enc_fx( L_tmp = Mult_32_16( ener_low_fx, tmp ); /*45-(exp+2*(Q_synth_hf-4)) + 2*(Q_synth_hf-4) - 15 = 30-exp */ exp1 = norm_l( L_tmp ); L_tmp = L_shl( L_tmp, exp1 ); - exp = 31 - exp1 - ( 30 - exp ); + exp = sub( sub( 31, exp1 ), sub( 30, exp ) ); L_tmp = Isqrt_lc( L_tmp, &exp ); /*31-exp */ #ifdef BASOP_NOGLOB fb_ener_adjust_fx = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /*Q15 */ @@ -416,1493 +565,2398 @@ void swb_bwe_enc_fx( idxGain = usquant_fx( fb_ener_adjust_fx, &ener_adjust_quan_fx, 0, 512, shl( 1, NUM_BITS_FB_FRAMEGAIN ) ); } + /* SWB BWE encoding */ + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + SWB_BWE_encoding_ivas_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 80, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + ELSE + { + SWB_BWE_encoding_ivas_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 6, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + + /* write FB BWE frame gain to the bitstream */ IF( EQ_16( st_fx->extl, FB_BWE ) ) { - push_indice_fx( st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + push_indice( st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); } return; } -/*==========================================================================*/ -/* FUNCTION : static Word16 WB_BWE_fenv_q_fx() */ -/*--------------------------------------------------------------------------*/ -/* PURPOSE : Scalar quantizer routine */ -/*--------------------------------------------------------------------------*/ -/* INPUT ARGUMENTS : */ -/* Word16 *cb i: quantizer codebook Q10 */ -/* Word16 cb_length i: length of codebook */ -/* Word16 cb_dim i: dimension of codebook */ -/*--------------------------------------------------------------------------*/ -/* OUTPUT ARGUMENTS : */ -/*--------------------------------------------------------------------------*/ -/* INPUT/OUTPUT ARGUMENTS : */ -/* Word16 *x i/o: energy of WB envelop Q10 */ -/*--------------------------------------------------------------------------*/ -/* RETURN ARGUMENTS : */ -/* _ None */ -/*--------------------------------------------------------------------------*/ -/* */ -/*==========================================================================*/ -static Word16 WB_BWE_fenv_q_fx( /* o: quantized gain index */ - Word16 *x, /* i/o: energy of WB envelop Q10*/ - const Word16 *cb, /* i: quantizer codebook Q10 */ - const Word16 cb_length, /* i: length of codebook */ - const Word16 cb_dim /* i: dimension of codebook */ -) + +/*-------------------------------------------------------------------* + * swb_bwe_enc() + * + * SWB BWE encoder (only for 32kHz signals) + *-------------------------------------------------------------------*/ +void swb_bwe_enc_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *old_input_12k8_fx, /* i : input signal @12.8kHz for SWB BWE */ + Word16 *old_input_16k_fx, /* i : input signal @16kHz for SWB BWE */ + const Word16 *old_syn_12k8_16k_fx, /* i : ACELP core synthesis at 12.8kHz or 16kHz */ + const Word16 *new_swb_speech_fx, /* i : original input signal at 32kHz */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_shb_speech, + Word16 Q_slb_speech ) { - Word16 i, j, indx = 0; - Word32 dist, min_dist; - const Word16 *pit = cb; /*Q10 */ - Word16 tmp; + Word16 i; + Word16 *new_input_fx; + Word16 tmp, exp, exp1; + Word16 frac; Word32 L_tmp; + Word16 inner_frame; + Word32 inner_Fs; + Word32 L_old_input_fx[2 * L_FRAME48k]; + Word32 yorig_32[L_FRAME48k]; + Word16 old_input_fx[NS2SA( 48000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + L_FRAME48k]; + Word16 old_input_lp_fx[L_FRAME16k]; + Word16 new_input_hp_fx[L_FRAME16k]; + Word16 yorig_fx[L_FRAME48k]; + Word16 scl, new_input_fx_exp; + Word16 max; + Word16 Sample_Delay_SWB_BWE; + Word16 Sample_Delay_HP; + Word16 Sample_Delay_LP; + Word16 idxGain = 0; - min_dist = L_add( MAX_32, 0 ); - FOR( i = 0; i < cb_length; i++ ) - { - dist = L_deposit_l( 0 ); - FOR( j = 0; j < cb_dim; j++ ) - { -#ifdef BASOP_NOGLOB - tmp = sub_sat( x[j], *pit ); /*Q10 */ - L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ - dist = L_add_sat( dist, L_tmp ); -#else - tmp = sub( x[j], *pit ); /*Q10 */ - L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ - dist = L_add( dist, L_tmp ); + Word16 Q_synth_hf, Q_synth, Q_shb; + Word16 tilt_nb_fx; + Word16 SWB_fenv_fx[SWB_FENV]; + Word32 ener_low_fx; + Word32 energy_fbe_fb_fx = 0; + Word16 fb_ener_adjust_fx; + Word16 ener_adjust_quan_fx = 0; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; #endif - pit++; - } - IF( LT_32( dist, min_dist ) ) - { - min_dist = L_add( dist, 0 ); - indx = i; - move16(); - } - } + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - FOR( j = 0; j < cb_dim; j++ ) - { - x[j] = cb[cb_dim * indx + j]; - move16(); - } + + /*---------------------------------------------------------------------* + * Delay the original input signal to be synchronized with ACELP core synthesis + *---------------------------------------------------------------------*/ + IF( EQ_16( st_fx->extl, FB_BWE ) ) + { + inner_frame = L_FRAME48k; + inner_Fs = 48000; + } + ELSE + { + inner_frame = L_FRAME32k; + inner_Fs = 32000; + } + + set16_fx( old_input_fx, 0, add( NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ), inner_frame ) ); + + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + Sample_Delay_LP = NS2SA( 12800, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_12k8_NS ); + + delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_12k8_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + } + ELSE + { + Sample_Delay_SWB_BWE = NS2SA( inner_Fs, DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS ); + Sample_Delay_HP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS + DELAY_FIR_RESAMPL_NS - DELAY_CLDFB_NS ); + Sample_Delay_LP = NS2SA( 16000, ACELP_LOOK_NS + DELAY_FD_BWE_ENC_16k_NS ); + + delay_input_signal_fx( hBWE_FD->old_input_lp_fx, old_input_lp_fx, &old_input_16k_fx[L_INP_MEM], Sample_Delay_LP, L_FRAME16k, &hBWE_FD->prev_Q_input_lp, &Q_slb_speech ); + } + + Copy( hBWE_FD->new_input_hp_fx, new_input_hp_fx, Sample_Delay_HP ); + Copy( shb_speech_fx, &new_input_hp_fx[Sample_Delay_HP], L_FRAME16k - Sample_Delay_HP ); + Copy( shb_speech_fx + L_FRAME16k - Sample_Delay_HP, hBWE_FD->new_input_hp_fx, Sample_Delay_HP ); + new_input_fx = old_input_fx + Sample_Delay_SWB_BWE; + Copy( hBWE_FD->old_input_fx, old_input_fx, Sample_Delay_SWB_BWE ); + Copy( new_swb_speech_fx, new_input_fx, inner_frame ); + Copy( old_input_fx + inner_frame, hBWE_FD->old_input_fx, Sample_Delay_SWB_BWE ); + /*----------------------------------------------------------------------* + * Calculate tilt of the input signal and the ACELP core synthesis + *----------------------------------------------------------------------*/ + + /* tilt returned in Q24 goto to Q11 */ +#ifdef BASOP_NOGLOB + tilt_nb_fx = round_fx_o( L_shl_o( calc_tilt_bwe_fx( old_input_lp_fx, Q_slb_speech, st_fx->L_frame ), 3, &Overflow ), &Overflow ); +#else + tilt_nb_fx = round_fx( L_shl( calc_tilt_bwe_fx( old_input_lp_fx, Q_slb_speech, st_fx->L_frame ), 3 ) ); +#endif + /*---------------------------------------------------------------------* + * SWB BWE encoding + * FB BWE encoding + *---------------------------------------------------------------------*/ + new_input_fx_exp = 0; + /* MDCT of the core synthesis signal */ + wtda_fx( old_input_fx, &new_input_fx_exp, L_old_input_fx, hBWE_FD->L_old_wtda_swb_fx, + &st_fx->Q_old_wtda, ALDO_WINDOW, ALDO_WINDOW, /* window overlap of current frame (0: full, 2: none, or 3: half) */ + inner_frame ); + + /* DCT of the ACELP core synthesis */ + direct_transform_fx( L_old_input_fx, yorig_32, 0, inner_frame, &new_input_fx_exp, /*st_fx->element_mode*/ EVS_MONO ); + + /* Convert to 16 Bits (Calc Shift Required to Stay within MAX_Q_NEW_INPUT) */ + scl = sub( 16 + 8, new_input_fx_exp ); + /* Possible to Upscale? */ + IF( scl > 0 ) + { + /* Yes */ + /* Calc Room to Upscale */ + Q_synth = Find_Max_Norm32( yorig_32, inner_frame ); + /* Stay within MAX_Q_NEW_INPUT */ + scl = s_min( Q_synth, scl ); + } + Copy_Scale_sig32_16( yorig_32, yorig_fx, inner_frame, scl ); + Q_synth = add( sub( new_input_fx_exp, 16 ), scl ); + + max = 0; + move16(); + Q_synth_hf = 0; + move16(); + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + scl = 300; + move16(); + } + ELSE + { + scl = 240; + move16(); + } + FOR( i = scl; i < inner_frame; i++ ) + { + max = s_max( max, abs_s( yorig_fx[i] ) ); + } + + IF( max == 0 ) + { + exp = 15; + move16(); + } + ELSE + { + exp = norm_s( max ); + } + + Copy_Scale_sig( &yorig_fx[scl], &yorig_fx[scl], sub( inner_frame, scl ), exp ); + Q_synth_hf = add( exp, Q_synth ); + IF( EQ_16( st_fx->last_extl, SWB_BWE ) || EQ_16( st_fx->last_extl, FB_BWE ) ) + { + exp = norm_l( st_fx->EnergyLT_fx ); + IF( add( st_fx->EnergyLT_fx_exp, exp ) > shl( sub( Q_synth_hf, 4 ), 1 ) ) + { + Q_shb = sub( Q_synth_hf, 4 ); + st_fx->EnergyLT_fx = L_shr( st_fx->EnergyLT_fx, sub( st_fx->EnergyLT_fx_exp, shl( Q_shb, 1 ) ) ); + } + ELSE + { + Q_shb = shr( add( st_fx->EnergyLT_fx_exp, exp ), 1 ); + IF( s_and( exp, 0x0001 ) == 1 ) + { + exp = sub( exp, 1 ); + } + st_fx->EnergyLT_fx = L_shl( st_fx->EnergyLT_fx, exp ); + } + } + ELSE + { + Q_shb = sub( Q_synth_hf, 4 ); + } + Copy_Scale_sig( new_input_hp_fx, new_input_hp_fx, L_FRAME16k, sub( Q_shb, Q_shb_speech ) ); + /* SWB BWE encoding */ + IF( EQ_16( st_fx->L_frame, L_FRAME16k ) ) + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 80, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + ELSE + { + SWB_BWE_encoding_fx( st_fx, old_input_fx, old_input_lp_fx, new_input_hp_fx, old_syn_12k8_16k_fx, yorig_fx, + SWB_fenv_fx, tilt_nb_fx, 6, coder_type, Q_slb_speech, Q_shb, Q_synth_hf, Q_synth ); + } + + /* FB BWE encoding */ + IF( EQ_16( st_fx->extl, FB_BWE ) ) + { + energy_fbe_fb_fx = L_deposit_l( 0 ); + FOR( i = FB_BAND_BEGIN; i < FB_BAND_END; i++ ) + { + tmp = shr( yorig_fx[i], 4 ); + energy_fbe_fb_fx = L_mac0( energy_fbe_fb_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ + } + ener_low_fx = 0; + move16(); + FOR( i = FB_BAND_BEGIN - FB_BAND_WIDTH; i < FB_BAND_BEGIN; i++ ) + { + tmp = shr( yorig_fx[i], 4 ); + ener_low_fx = L_mac0( ener_low_fx, tmp, tmp ); /*2*(Q_synth_hf-4) */ + } + + IF( energy_fbe_fb_fx != 0 ) + { + exp = norm_l( energy_fbe_fb_fx ); + frac = extract_h( L_shl( energy_fbe_fb_fx, exp ) ); + tmp = div_s( 16384, frac ); /*15+14-(exp+2*(Q_synth_hf-4)-16) -->45-(exp+2*(Q_synth_hf-4)) */ + L_tmp = Mult_32_16( ener_low_fx, tmp ); /*45-(exp+2*(Q_synth_hf-4)) + 2*(Q_synth_hf-4) - 15 = 30-exp */ + exp1 = norm_l( L_tmp ); + L_tmp = L_shl( L_tmp, exp1 ); + exp = 31 - exp1 - ( 30 - exp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); /*31-exp */ +#ifdef BASOP_NOGLOB + fb_ener_adjust_fx = round_fx_o( L_shl_o( L_tmp, exp, &Overflow ), &Overflow ); /*Q15 */ +#else + fb_ener_adjust_fx = round_fx( L_shl( L_tmp, exp ) ); /*Q15 */ +#endif + } + ELSE + { + fb_ener_adjust_fx = 0; + move16(); + } + + fb_ener_adjust_fx = s_min( fb_ener_adjust_fx, 16384 ); /*Q15 */ + idxGain = usquant_fx( fb_ener_adjust_fx, &ener_adjust_quan_fx, 0, 512, shl( 1, NUM_BITS_FB_FRAMEGAIN ) ); + } + + /* write FB BWE frame gain to the bitstream */ + IF( EQ_16( st_fx->extl, FB_BWE ) ) + { + push_indice_fx( st_fx->hBstr, IND_FB_SLOPE, idxGain, NUM_BITS_FB_FRAMEGAIN ); + } + + return; +} +/*==========================================================================*/ +/* FUNCTION : static Word16 WB_BWE_fenv_q_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : Scalar quantizer routine */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 *cb i: quantizer codebook Q10 */ +/* Word16 cb_length i: length of codebook */ +/* Word16 cb_dim i: dimension of codebook */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word16 *x i/o: energy of WB envelop Q10 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ +static Word16 WB_BWE_fenv_q_fx( /* o: quantized gain index */ + Word16 *x, /* i/o: energy of WB envelop Q10*/ + const Word16 *cb, /* i: quantizer codebook Q10 */ + const Word16 cb_length, /* i: length of codebook */ + const Word16 cb_dim /* i: dimension of codebook */ +) +{ + Word16 i, j, indx = 0; + Word32 dist, min_dist; + const Word16 *pit = cb; /*Q10 */ + Word16 tmp; + Word32 L_tmp; + + min_dist = MAX_32; + move32(); + FOR( i = 0; i < cb_length; i++ ) + { + dist = L_deposit_l( 0 ); + FOR( j = 0; j < cb_dim; j++ ) + { +#ifdef BASOP_NOGLOB + tmp = sub_sat( x[j], *pit ); /*Q10 */ + L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ + dist = L_add_sat( dist, L_tmp ); +#else + tmp = sub( x[j], *pit ); /*Q10 */ + L_tmp = L_mult0( tmp, tmp ); /*Q(10+10)->Q20 */ + dist = L_add( dist, L_tmp ); +#endif + pit++; + } + + IF( LT_32( dist, min_dist ) ) + { + min_dist = dist; + move32(); + indx = i; + move16(); + } + } + + FOR( j = 0; j < cb_dim; j++ ) + { + x[j] = cb[cb_dim * indx + j]; + move16(); + } return ( indx ); } -static void get_normalize_spec_fx( - const Word16 core, /* i : core selected */ - const Word16 extl, /* i : extension layer selected */ - const Word16 mode, /* i : SHB BWE class */ - const Word16 core_type, /* i : coding type */ - const Word16 *org_fx, /* i : input spectrum */ - Word16 *SWB_signal, /* o : output spectrum */ - Word16 *prev_L_swb_norm, /* i : previous norm. len */ - const Word16 offset, /* i : frequency offset */ - Word16 Q_new_lf ) -{ - Word16 n_freq, L_swb_norm; - Word32 envelope[L_FRAME32k]; - Word16 frq_end; - Word16 tmp; - Word16 exp; - Word32 L_tmp_m; +static void get_normalize_spec_fx( + const Word16 core, /* i : core selected */ + const Word16 extl, /* i : extension layer selected */ + const Word16 mode, /* i : SHB BWE class */ + const Word16 core_type, /* i : coding type */ + const Word16 *org_fx, /* i : input spectrum */ + Word16 *SWB_signal, /* o : output spectrum */ + Word16 *prev_L_swb_norm, /* i : previous norm. len */ + const Word16 offset, /* i : frequency offset */ + Word16 Q_new_lf ) +{ + Word16 n_freq, L_swb_norm; + Word32 envelope[L_FRAME32k]; + Word16 frq_end; + Word16 tmp; + Word16 exp; + Word32 L_tmp_m; + + set16_fx( SWB_signal, 0, add( HQ_GENERIC_HIGH0, offset ) ); + calc_normal_length_fx( core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm, Q_new_lf ); + test(); + IF( EQ_16( extl, SWB_BWE ) || EQ_16( extl, FB_BWE ) ) + { + IF( EQ_16( mode, HARMONIC ) ) + { + Copy( org_fx, &SWB_signal[add( 240, offset )], 240 ); + Copy( &org_fx[128], &SWB_signal[add( 480, offset )], 80 ); + } + ELSE + { + Copy( &org_fx[112], &SWB_signal[add( 240, offset )], 128 ); + Copy( &org_fx[112], &SWB_signal[add( 368, offset )], 128 ); + Copy( &org_fx[176], &SWB_signal[add( 496, offset )], 64 ); + } + frq_end = add( 560, offset ); + } + ELSE IF( EQ_16( extl, WB_BWE ) ) + { + IF( core_type == 0 ) + { + Copy( &org_fx[160], &SWB_signal[240], 80 ); + } + ELSE + { + Copy( &org_fx[80], &SWB_signal[240], 80 ); + } + frq_end = L_FRAME16k; + move16(); + } + ELSE + { + Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH0, offset ), HQ_GENERIC_LEN0 ); + Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH1, offset ), HQ_GENERIC_LEN0 ); + IF( EQ_16( offset, HQ_GENERIC_FOFFSET_24K4 ) ) + { + Copy( org_fx + HQ_GENERIC_LOW0, SWB_signal + add( HQ_GENERIC_HIGH2, offset ), sub( HQ_GENERIC_END_FREQ, HQ_GENERIC_HIGH2 ) ); + } + frq_end = sub( L_FRAME32k, offset ); + } + + /* calculate envelope */ + calc_norm_envelop_fx( SWB_signal, envelope, L_swb_norm, sub( frq_end, offset ), offset ); + + /* Normalize with envelope */ + FOR( n_freq = add( swb_bwe_subband[0], offset ); n_freq < frq_end; n_freq++ ) + { + IF( envelope[n_freq] != 0 ) + { + exp = norm_l( envelope[n_freq] ); + tmp = extract_h( L_shl( envelope[n_freq], exp ) ); + exp = sub( sub( 30, exp ), Q_new_lf ); + tmp = div_s( 16384, tmp ); /*Q(15+exp) */ + L_tmp_m = L_shr( L_mult0( SWB_signal[n_freq], tmp ), add( exp, Q_new_lf ) ); /*Q15 */ + SWB_signal[n_freq] = extract_l( L_tmp_m ); /*Q15 */ + move16(); + } + ELSE + { + SWB_signal[n_freq] = 1; + move16(); + } + } + + return; +} + +/*-------------------------------------------------------------------* + * FD_BWE_class() + * + * classify signal of above 6.4kHz, can be used for WB/SWB switch + *-------------------------------------------------------------------*/ + +static Word16 FD_BWE_class_fx( /* o : FD BWE class */ + const Word16 *fSpectrum, /* i : input spectrum */ + const Word32 fGain, /* i : global gain */ + const Word16 tilt_nb, /* i : BWE tilt */ + Word16 Q_syn, + Word16 Q_shb, + Encoder_State *st_fx /* i/o: Encoder structure */ +) +{ + Word16 i, j, k, noise, sharpMod = 0; + Word16 peak, mag; + Word32 mean[20]; + Word16 sharpPeak; + const Word16 *input_hi = 0; + Word16 sharp; + Word16 gain_tmp = 0; + Word16 mode; + Word32 L_meanH, L_mean_d, L_tmp; + Word16 sharplimit; + Word16 numsharp, num, den; + Word16 numharmonic, tmp, expn, expd, scale; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + move16(); + + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + mode = NORMAL; + move16(); + k = 0; + move16(); + noise = 0; + move16(); + sharpPeak = 0; + move16(); + numsharp = 0; + move16(); + numharmonic = 4; + move16(); + sharplimit = 10; + move16(); + + L_mean_d = 0L; /* to avoid compilation warnings */ + move32(); + + test(); + IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) + { + input_hi = &fSpectrum[256]; + move16(); + numsharp = NUM_SHARP; + move16(); + + test(); + test(); + test(); + IF( ( EQ_16( st_fx->last_extl, SWB_BWE ) && EQ_16( st_fx->extl, SWB_BWE ) ) || ( EQ_16( st_fx->last_extl, FB_BWE ) && EQ_16( st_fx->extl, FB_BWE ) ) ) + { + IF( hBWE_FD->prev_global_gain_fx == 0 ) + { +#ifdef BASOP_NOGLOB + gain_tmp = round_fx_o( L_shl_o( fGain, 30, &Overflow ), &Overflow ); /*Q14 */ +#else + gain_tmp = round_fx( L_shl( fGain, 30 ) ); /*Q14 */ +#endif + } + ELSE + { + expn = norm_l( fGain ); +#ifdef BASOP_NOGLOB + num = extract_h( L_shl_o( fGain, expn, &Overflow ) ); +#else + num = extract_h( L_shl( fGain, expn ) ); +#endif + expn = sub( sub( 30, expn ), shl( Q_shb, 1 ) ); + + expd = norm_l( hBWE_FD->prev_global_gain_fx ); +#ifdef BASOP_NOGLOB + den = extract_h( L_shl_o( hBWE_FD->prev_global_gain_fx, expd, &Overflow ) ); +#else + den = extract_h( L_shl( hBWE_FD->prev_global_gain_fx, expd ) ); +#endif + expd = sub( sub( 30, expd ), shl( st_fx->prev_Q_shb, 1 ) ); + + scale = shr( sub( den, num ), 15 ); +#ifdef BASOP_NOGLOB + num = shl_o( num, scale, &Overflow ); +#else + num = shl( num, scale ); +#endif + expn = sub( expn, scale ); + + tmp = div_s( num, den ); + expn = sub( expn, expd ); +#ifdef BASOP_NOGLOB + gain_tmp = shl_o( tmp, sub( expn, 1 ), &Overflow ); /*Q14 */ +#else + gain_tmp = shl( tmp, sub( expn, 1 ) ); /*Q14 */ +#endif + } + test(); + IF( EQ_16( hBWE_FD->prev_mode, TRANSIENT ) ) + { + numharmonic = shl( numharmonic, 1 ); + } + ELSE IF( EQ_16( hBWE_FD->prev_mode, NORMAL ) || EQ_16( hBWE_FD->prev_mode, NOISE ) ) + { + numharmonic = add( shr( numharmonic, 1 ), numharmonic ); + } + } + ELSE + { + gain_tmp = 16384; + move16(); + IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + { + numharmonic = shr( numharmonic, 1 ); + sharplimit = shr( sharplimit, 1 ); + } + ELSE + { + numharmonic = shl( numharmonic, 1 ); + sharplimit = shl( sharplimit, 1 ); + } + } + } + ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) + { + input_hi = &fSpectrum[224]; + move16(); + numsharp = 3; + move16(); + + IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + { + numharmonic = shr( numharmonic, 2 ); + } + ELSE + { + numharmonic = shr( numharmonic, 1 ); + } + IF( NE_16( st_fx->last_extl, WB_BWE ) ) + { + IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + { + sharplimit = shr( sharplimit, 1 ); + } + ELSE + { + sharplimit = shl( sharplimit, 1 ); + } + } + } - set16_fx( SWB_signal, 0, add( HQ_GENERIC_HIGH0, offset ) ); - calc_normal_length_fx( core, org_fx, mode, extl, &L_swb_norm, prev_L_swb_norm, Q_new_lf ); + L_meanH = L_deposit_l( 0 ); + FOR( i = 0; i < numsharp; i++ ) + { + peak = 0; + move16(); + mean[i] = L_deposit_l( 0 ); + move32(); + + FOR( j = 0; j < SHARP_WIDTH; j++ ) + { + mag = abs_s( *input_hi ); + IF( GT_16( mag, peak ) ) + { + peak = mag; + move16(); /*Q_syn */ + } + mean[i] = L_add( mean[i], mag ); + move32(); /*Q_syn */ + input_hi++; + } + + L_meanH = L_add( L_meanH, mean[i] ); /*Q_syn */ + + IF( NE_32( mean[i], L_deposit_l( peak ) ) ) + { + L_tmp = L_sub( mean[i], peak ); /*Q_syn */ + L_tmp = Mpy_32_16_1( L_tmp, 16913 ); /* 1/31->Q19 -> Q_syn+19-15 */ + den = extract_l( L_shr( L_tmp, 4 ) ); /*Q_syn */ + IF( den == 0 ) + { + den = 1; + move16(); + } + expd = norm_s( den ); + tmp = div_s( shl( 1, sub( 14, expd ) ), den ); /*Q(29-expd-Q_syn) */ + L_tmp = L_mult( tmp, peak ); /*Q(30-expd) */ +#ifdef BASOP_NOGLOB + sharp = round_fx_o( L_shl_o( L_tmp, sub( expd, 4 ), &Overflow ), &Overflow ); /*Q10 */ +#else + sharp = round_fx( L_shl( L_tmp, sub( expd, 4 ) ) ); /*Q10 */ +#endif + } + ELSE + { + sharp = 0; + move16(); + } + + test(); +#ifdef BASOP_NOGLOB + IF( GT_16( sharp, 4608 ) && GT_16( peak, shl_o( 1, add( Q_syn, 3 ), &Overflow ) ) ) +#else + IF( GT_16( sharp, 4608 ) && GT_16( peak, shl( 1, add( Q_syn, 3 ) ) ) ) +#endif + { + k = add( k, 1 ); + move16(); + } + ELSE IF( LT_16( sharp, 3072 ) ) + { + noise = add( noise, 1 ); + move16(); + } + + IF( GT_16( sharp, sharpPeak ) ) + { + sharpPeak = sharp; + move16(); + } + } test(); - IF( EQ_16( extl, SWB_BWE ) || EQ_16( extl, FB_BWE ) ) + IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) { - IF( EQ_16( mode, HARMONIC ) ) + test(); + test(); + test(); + IF( GE_16( k, numharmonic ) && GT_16( gain_tmp, 8192 ) && LT_16( gain_tmp, 29491 ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) { - Copy( org_fx, &SWB_signal[add( 240, offset )], 240 ); - Copy( &org_fx[128], &SWB_signal[add( 480, offset )], 80 ); + sharpMod = 1; + move16(); } ELSE { - Copy( &org_fx[112], &SWB_signal[add( 240, offset )], 128 ); - Copy( &org_fx[112], &SWB_signal[add( 368, offset )], 128 ); - Copy( &org_fx[176], &SWB_signal[add( 496, offset )], 64 ); + sharpMod = 0; + move16(); + } + + L_meanH = Mpy_32_16_1( L_meanH, 29127 ); /*Q_syn+8 */ + L_mean_d = 0; + move16(); + FOR( i = 0; i < NUM_SHARP; i++ ) + { + L_tmp = L_sub( L_shl( mean[i], 8 - 5 ), L_meanH ); /*Q_syn+8 */ + L_mean_d = L_add( L_mean_d, L_abs( L_tmp ) ); /*Q_syn+8 */ } - frq_end = add( 560, offset ); } - ELSE IF( EQ_16( extl, WB_BWE ) ) + ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) { - IF( core_type == 0 ) + test(); + IF( GE_16( k, numharmonic ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) { - Copy( &org_fx[160], &SWB_signal[240], 80 ); + sharpMod = 1; + move16(); } ELSE { - Copy( &org_fx[80], &SWB_signal[240], 80 ); + sharpMod = 0; + move16(); } - frq_end = L_FRAME16k; + } + + test(); + test(); + IF( sharpMod && LT_16( hBWE_FD->modeCount, 12 ) ) + { + hBWE_FD->modeCount = add( hBWE_FD->modeCount, 1 ); move16(); } - ELSE + ELSE IF( sharpMod == 0 && hBWE_FD->modeCount > 0 ) { - Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH0, offset ), HQ_GENERIC_LEN0 ); - Copy( org_fx + HQ_GENERIC_OFFSET, SWB_signal + add( HQ_GENERIC_HIGH1, offset ), HQ_GENERIC_LEN0 ); - IF( EQ_16( offset, HQ_GENERIC_FOFFSET_24K4 ) ) + hBWE_FD->modeCount = sub( hBWE_FD->modeCount, 1 ); + move16(); + } + + IF( GE_16( hBWE_FD->modeCount, 2 ) ) + { + sharpMod = 1; + move16(); + } + + test(); + IF( sharpMod ) + { + mode = HARMONIC; + move16(); + } + ELSE IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) + { + L_tmp = Mpy_32_16_1( L_mean_d, 6827 ); /*Q_syn+8 ; 1/4.8 in Q15 */ + + test(); + test(); + test(); + IF( GT_16( noise, 4 ) && ( LT_32( L_tmp, L_meanH ) || L_meanH == 0 ) && LT_16( tilt_nb, 10240 ) ) { - Copy( org_fx + HQ_GENERIC_LOW0, SWB_signal + add( HQ_GENERIC_HIGH2, offset ), sub( HQ_GENERIC_END_FREQ, HQ_GENERIC_HIGH2 ) ); + mode = NOISE; + move16(); } - frq_end = sub( L_FRAME32k, offset ); } - /* calculate envelope */ - calc_norm_envelop_fx( SWB_signal, envelope, L_swb_norm, sub( frq_end, offset ), offset ); - - /* Normalize with envelope */ - FOR( n_freq = add( swb_bwe_subband[0], offset ); n_freq < frq_end; n_freq++ ) + return ( mode ); +} + +/*-------------------------------------------------------------------* + * freq_weights_fx() + * + *-------------------------------------------------------------------*/ +static void freq_weights_fx( + const Word16 Band_Ener[], /* i : Band energy Q8 */ + const Word16 f_weighting[], /* i : weigting coefs. Q15 */ + Word16 w_env[], /* o : Freq. weighting Q13 */ + const Word16 Nbands /* i : Number of bands */ +) +{ + Word16 i; + Word16 tmp, tmp1, w1[SWB_FENV], w2[SWB_FENV]; + Word16 min_b, max_b; + Word32 L_tmp; + Word16 exp; + + /* Find Max band energy */ + min_b = Band_Ener[0]; + move16(); + max_b = Band_Ener[0]; + move16(); + FOR( i = 1; i < Nbands; i++ ) + { + if ( LT_16( Band_Ener[i], min_b ) ) + { + min_b = Band_Ener[i]; + move16(); /*Q8 */ + } + + if ( GT_16( Band_Ener[i], max_b ) ) + { + max_b = Band_Ener[i]; + move16(); /*Q8 */ + } + } + + /* Find weighting function */ + tmp = sub( max_b, min_b ); /*Q8 */ + IF( tmp != 0 ) + { + exp = norm_s( tmp ); + tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*(21-exp) */ +#ifdef BASOP_NOGLOB + tmp = shl_sat( tmp, sub( exp, 6 ) ); /*Q15 */ +#else + tmp = shl( tmp, sub( exp, 6 ) ); /*Q15 */ +#endif + } + ELSE + { + tmp = 32767; + move16(); + } + + FOR( i = 0; i < Nbands; i++ ) { - IF( envelope[n_freq] != 0 ) - { - exp = norm_l( envelope[n_freq] ); - tmp = extract_h( L_shl( envelope[n_freq], exp ) ); - exp = sub( sub( 30, exp ), Q_new_lf ); - tmp = div_s( 16384, tmp ); /*Q(15+exp) */ - L_tmp_m = L_shr( L_mult0( SWB_signal[n_freq], tmp ), add( exp, Q_new_lf ) ); /*Q15 */ - SWB_signal[n_freq] = extract_l( L_tmp_m ); /*Q15 */ - } - ELSE - { - SWB_signal[n_freq] = 1; - move16(); - } + tmp1 = sub( Band_Ener[i], min_b ); + L_tmp = L_mult( tmp1, tmp ); /*Q24 */ + L_tmp = L_add( L_tmp, 16777216 ); /*Q24 */ + L_tmp = L_shl( L_tmp, 5 ); /*Q29 */ + w1[i] = round_fx( L_tmp ); /*Q13 */ + move16(); + w2[i] = f_weighting[i]; + move16(); /*Q15 */ /*1~0.75*/ + w_env[i] = mult_r( w1[i], w2[i] ); + move16(); /*Q13 */ } return; } /*-------------------------------------------------------------------* - * FD_BWE_class() + * vqWithCand_w_fx() * - * classify signal of above 6.4kHz, can be used for WB/SWB switch *-------------------------------------------------------------------*/ -static Word16 FD_BWE_class_fx( /* o : FD BWE class */ - const Word16 *fSpectrum, /* i : input spectrum */ - const Word32 fGain, /* i : global gain */ - const Word16 tilt_nb, /* i : BWE tilt */ - Word16 Q_syn, - Word16 Q_shb, - Encoder_State *st_fx /* i/o: Encoder structure */ +static void vqWithCand_w_fx( + const Word16 *x, /* i : input vector Q8 */ + const Word16 *E_ROM_dico, /* i : codebook Q8 */ + const Word16 dim, /* i : codebook dimension */ + const Word16 E_ROM_dico_size, /* i : codebook size */ + Word16 *index, /* o : survivors indices */ + const Word16 surv, /* i : survivor number */ + Word32 dist_min[], /* o : minimum distortion Q5 */ + const Word16 *w, /* i : weighting Q13*/ + const Word16 flag /* i : flag indicationg weighted distortion metric */ ) { - Word16 i, j, k, noise, sharpMod = 0; - Word16 peak, mag; - Word32 mean[20]; - Word16 sharpPeak; - const Word16 *input_hi = 0; - Word16 sharp; - Word16 gain_tmp = 0; - Word16 mode; - Word32 L_meanH, L_mean_d, L_tmp; - Word16 sharplimit; - Word16 numsharp, num, den; - Word16 numharmonic, tmp, expn, expd, scale; + Word16 i, j, k, l; + const Word16 *p_E_ROM_dico; + Word16 dist, temp1; + Word32 L_dist, L_tmp; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + IF( flag ) + { + set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ - FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - - mode = NORMAL; - move16(); - k = 0; - move16(); - noise = 0; - move16(); - sharpPeak = 0; - move16(); - numsharp = 0; - move16(); - numharmonic = 4; - move16(); - sharplimit = 10; - move16(); - - L_mean_d = 0L; /* to avoid compilation warnings */ + FOR( i = 0; i < surv; i++ ) + { + index[i] = i; + move16(); + } - test(); - IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) - { - input_hi = &fSpectrum[256]; - move16(); - numsharp = NUM_SHARP; + p_E_ROM_dico = E_ROM_dico; move16(); - test(); - test(); - test(); - IF( ( EQ_16( st_fx->last_extl, SWB_BWE ) && EQ_16( st_fx->extl, SWB_BWE ) ) || ( EQ_16( st_fx->last_extl, FB_BWE ) && EQ_16( st_fx->extl, FB_BWE ) ) ) + FOR( i = 0; i < E_ROM_dico_size; i++ ) { - IF( hBWE_FD->prev_global_gain_fx == 0 ) - { #ifdef BASOP_NOGLOB - gain_tmp = round_fx_o( L_shl_o( fGain, 30, &Overflow ), &Overflow ); /*Q14 */ + dist = sub_o( x[0], *p_E_ROM_dico++, &Overflow ); /*Q8 */ #else - gain_tmp = round_fx( L_shl( fGain, 30 ) ); /*Q14 */ + dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ #endif - } - ELSE + L_dist = L_mult( dist, w[0] ); /*Q22 */ + L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ + L_dist = L_shr( L_dist, 10 ); /*Q5 */ + + FOR( j = 1; j < dim; j++ ) { - expn = norm_l( fGain ); #ifdef BASOP_NOGLOB - num = extract_h( L_shl_o( fGain, expn, &Overflow ) ); + temp1 = sub_o( x[j], *p_E_ROM_dico++, &Overflow ); #else - num = extract_h( L_shl( fGain, expn ) ); + temp1 = sub( x[j], *p_E_ROM_dico++ ); #endif - expn = sub( sub( 30, expn ), shl( Q_shb, 1 ) ); + L_tmp = L_mult( temp1, w[j] ); /*Q22 */ + L_tmp = Mult_32_16( L_tmp, temp1 ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ + } - expd = norm_l( hBWE_FD->prev_global_gain_fx ); -#ifdef BASOP_NOGLOB - den = extract_h( L_shl_o( hBWE_FD->prev_global_gain_fx, expd, &Overflow ) ); -#else - den = extract_h( L_shl( hBWE_FD->prev_global_gain_fx, expd ) ); -#endif - expd = sub( sub( 30, expd ), shl( st_fx->prev_Q_shb, 1 ) ); + FOR( k = 0; k < surv; k++ ) + { + IF( LT_32( L_dist, dist_min[k] ) ) + { + FOR( l = sub( surv, 1 ); l > k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } + } + } + } + ELSE + { + set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ - scale = shr( sub( den, num ), 15 ); -#ifdef BASOP_NOGLOB - num = shl_o( num, scale, &Overflow ); -#else - num = shl( num, scale ); -#endif - expn = sub( expn, scale ); + FOR( i = 0; i < surv; i++ ) + { + index[i] = i; + move16(); + } - tmp = div_s( num, den ); - expn = sub( expn, expd ); + p_E_ROM_dico = E_ROM_dico; + move16(); + + FOR( i = 0; i < E_ROM_dico_size; i++ ) + { #ifdef BASOP_NOGLOB - gain_tmp = shl_o( tmp, sub( expn, 1 ), &Overflow ); /*Q14 */ + dist = sub_sat( x[0], *p_E_ROM_dico++ ); /*Q8 */ #else - gain_tmp = shl( tmp, sub( expn, 1 ) ); /*Q14 */ + dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ #endif - } - test(); - IF( EQ_16( hBWE_FD->prev_mode, TRANSIENT ) ) + L_dist = L_mult( dist, dist ); /*Q17 */ + L_dist = L_shr( L_dist, 12 ); /*Q5 */ + + FOR( j = 1; j < dim; j++ ) { - numharmonic = shl( numharmonic, 1 ); + temp1 = sub( x[j], *p_E_ROM_dico++ ); /*Q8 */ + L_tmp = L_mult( temp1, temp1 ); /*Q17 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ } - ELSE IF( EQ_16( hBWE_FD->prev_mode, NORMAL ) || EQ_16( hBWE_FD->prev_mode, NOISE ) ) + + FOR( k = 0; k < surv; k++ ) { - numharmonic = add( shr( numharmonic, 1 ), numharmonic ); + IF( LT_32( L_dist, dist_min[k] ) ) + { + FOR( l = sub( surv, 1 ); l > k; l-- ) + { + dist_min[l] = dist_min[l - 1]; + move32(); + index[l] = index[l - 1]; + move16(); + } + dist_min[k] = L_dist; + move32(); + index[k] = i; + move16(); + BREAK; + } } } - ELSE + } + + return; +} + +/*-------------------------------------------------------------------* + * vqSimple_w_fx() + * + *-------------------------------------------------------------------*/ + +static Word16 vqSimple_w_fx( + const Word16 *x, /* i : input for quantizer Q8 */ + Word16 *y, /* i : quantized value Q8 */ + const Word16 *cb, /* i : codebooks Q8 */ + const Word16 *w, /* i : weight Q13 */ + const Word16 dim, /* i : dimension */ + const Word16 l, /* i : number of candidates */ + const Word16 flag /* i : flag indicationg weighted distortion metric */ +) +{ + Word16 i, j, index; + const Word16 *cbP; + Word16 dist, temp; + Word32 L_dist, L_tmp, L_dist_min; + + index = 0; + move16(); + L_dist_min = L_add( MAX_32, 0 ); /* FLT_MAX */ + cbP = cb; + move16(); + IF( flag ) + { + FOR( i = 0; i < l; i++ ) { - gain_tmp = 16384; - move16(); - IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + /*dist = x[0] - *cbP++; */ + /*dist *= (dist * w[0]); */ + dist = sub( x[0], *cbP++ ); /*Q8 */ + L_dist = L_mult( dist, w[0] ); /*Q22 */ + L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ + L_dist = L_shr( L_dist, 10 ); /*Q5 */ + + FOR( j = 1; j < dim; j++ ) { - numharmonic = shr( numharmonic, 1 ); - sharplimit = shr( sharplimit, 1 ); + /*temp = x[j] - *cbP++; */ + /*dist += temp * temp * w[j]; */ + temp = sub( x[j], *cbP++ ); + L_tmp = L_mult( temp, w[j] ); /*Q22 */ + L_tmp = Mult_32_16( L_tmp, temp ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ } - ELSE + IF( LT_32( L_dist, L_dist_min ) ) { - numharmonic = shl( numharmonic, 1 ); - sharplimit = shl( sharplimit, 1 ); + L_dist_min = L_add( L_dist, 0 ); /*Q5 */ + index = i; + move16(); } } } - ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) + ELSE { - input_hi = &fSpectrum[224]; - move16(); - numsharp = 3; - move16(); - - IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) - { - numharmonic = shr( numharmonic, 2 ); - } - ELSE - { - numharmonic = shr( numharmonic, 1 ); - } - IF( NE_16( st_fx->last_extl, WB_BWE ) ) + FOR( i = 0; i < l; i++ ) { - IF( EQ_16( hBWE_FD->prev_mode, HARMONIC ) ) + /*dist = x[0] - *cbP++; */ + dist = sub( x[0], *cbP++ ); + /*dist *= dist; */ + L_dist = L_mult( dist, dist ); /*Q17 */ + L_dist = L_shr( L_dist, 12 ); + + FOR( j = 1; j < dim; j++ ) { - sharplimit = shr( sharplimit, 1 ); + /*temp = x[j] - *cbP++; */ + temp = sub( x[j], *cbP++ ); + /*dist += temp * temp; */ + L_tmp = L_mult( temp, temp ); /*Q17 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ } - ELSE + IF( LT_32( L_dist, L_dist_min ) ) { - sharplimit = shl( sharplimit, 1 ); + L_dist_min = L_add( L_dist, 0 ); + index = i; + move16(); } } } - L_meanH = L_deposit_l( 0 ); - FOR( i = 0; i < numsharp; i++ ) + + /* Reading the selected vector */ + Copy( &cb[i_mult( index, dim )], y, dim ); + + return ( index ); +} + + +/*-------------------------------------------------------------------* + * MSVQ_Interpol_Tran_fx() + * + *-------------------------------------------------------------------*/ +static void MSVQ_Interpol_Tran_fx( + Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8 */ + Word16 *indice /* o : quantized index */ +) + +{ + Word16 k, n_band, candInd[N_CAND_TR], ind_tmp[2], tmp; + Word16 env_temp11[SWB_FENV_TRANS / 2], env_temp12[SWB_FENV_TRANS / 2]; + Word16 tmp_q; + Word16 quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; + Word16 quant_select[SWB_FENV_TRANS]; + Word32 L_tmp, L_dist, L_minDist, distCand[N_CAND_TR]; + + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) { - peak = 0; - move16(); - mean[i] = L_deposit_l( 0 ); + env_temp11[n_band] = SWB_env_energy[2 * n_band]; + move16(); /*Q8 */ + env_temp12[n_band] = SWB_env_energy[2 * n_band + 1]; + move16(); /*Q8 */ + } - FOR( j = 0; j < SHARP_WIDTH; j++ ) - { - mag = abs_s( *input_hi ); - IF( GT_16( mag, peak ) ) - { - peak = mag; - move16(); /*Q_syn */ - } - mean[i] = L_add( mean[i], mag ); - move32(); /*Q_syn */ - input_hi++; - } + vqWithCand_w_fx( env_temp11, Env_TR_Cdbk1_fx, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); - L_meanH = L_add( L_meanH, mean[i] ); /*Q_syn */ + L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ - IF( NE_32( mean[i], L_deposit_l( peak ) ) ) + FOR( k = 0; k < N_CAND_TR; k++ ) + { + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) { - L_tmp = L_sub( mean[i], peak ); /*Q_syn */ - L_tmp = Mult_32_16( L_tmp, 16913 ); /* 1/31->Q19 -> Q_syn+19-15 */ - den = extract_l( L_shr( L_tmp, 4 ) ); /*Q_syn */ - IF( den == 0 ) - { - den = 1; - move16(); - } - expd = norm_s( den ); - tmp = div_s( shl( 1, sub( 14, expd ) ), den ); /*Q(29-expd-Q_syn) */ - L_tmp = L_mult( tmp, peak ); /*Q(30-expd) */ -#ifdef BASOP_NOGLOB - sharp = round_fx_o( L_shl_o( L_tmp, sub( expd, 4 ), &Overflow ), &Overflow ); /*Q10 */ -#else - sharp = round_fx( L_shl( L_tmp, sub( expd, 4 ) ) ); /*Q10 */ -#endif + quant_tmp[n_band] = Env_TR_Cdbk1_fx[add( shl( candInd[k], 1 ), n_band )]; + move16(); /*DIM_TR1 == 2*/ } - ELSE + + FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) { - sharp = 0; - move16(); + /*quant_tmp2[n_band] = env_temp12[n_band] - ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f); */ + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ + tmp = shr( tmp, 1 ); + quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); + move16(); /*Q8 */ } + /*quant_tmp2[n_band] = env_temp12[n_band] - quant_tmp[n_band]; */ + quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); + move16(); /*Q8 */ + ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, Env_TR_Cdbk2_fx, NULL, DIM_TR2, N_CB_TR2, 0 ); + move16(); - test(); -#ifdef BASOP_NOGLOB - IF( GT_16( sharp, 4608 ) && GT_16( peak, shl_o( 1, add( Q_syn, 3 ), &Overflow ) ) ) -#else - IF( GT_16( sharp, 4608 ) && GT_16( peak, shl( 1, add( Q_syn, 3 ) ) ) ) -#endif + FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) { - k = add( k, 1 ); + quant_select[n_band * 2] = quant_tmp[n_band]; move16(); } - ELSE IF( LT_16( sharp, 3072 ) ) + + FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) { - noise = add( noise, 1 ); + /*quant_select[n_band*2+1] = ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f) + quant_tmp2[n_band]; */ + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ + tmp = shr( tmp, 1 ); + quant_select[n_band * 2 + 1] = add( tmp, quant_tmp2[n_band] ); move16(); } + /*quant_select[n_band*2+1] = quant_tmp[n_band]+quant_tmp2[n_band]; */ + quant_select[n_band * 2 + 1] = add( quant_tmp[n_band], quant_tmp2[n_band] ); + move16(); - IF( GT_16( sharp, sharpPeak ) ) + L_dist = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) { - sharpPeak = sharp; - move16(); + /*tmp_q = SWB_env_energy[n_band] - quant_select[n_band]; */ + tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); + /*dist += tmp_q*tmp_q; */ + L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ } - } - test(); - IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) - { - test(); - test(); - test(); - IF( GE_16( k, numharmonic ) && GT_16( gain_tmp, 8192 ) && LT_16( gain_tmp, 29491 ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) + + /* Check optimal candidate */ + IF( LT_32( L_dist, L_minDist ) ) { - sharpMod = 1; + L_minDist = L_add( L_dist, 0 ); + indice[0] = candInd[k]; move16(); - } - ELSE - { - sharpMod = 0; + indice[1] = ind_tmp[0]; move16(); } - - L_meanH = Mult_32_16( L_meanH, 29127 ); /*Q_syn+8 */ - L_mean_d = 0; - move16(); - FOR( i = 0; i < NUM_SHARP; i++ ) - { - L_tmp = L_sub( L_shl( mean[i], 8 - 5 ), L_meanH ); /*Q_syn+8 */ - L_mean_d = L_add( L_mean_d, L_abs( L_tmp ) ); /*Q_syn+8 */ - } } - ELSE IF( EQ_16( st_fx->extl, WB_BWE ) ) + return; +} + +/*-------------------------------------------------------------------* + * MSVQ_Interpol_fx() + * + *-------------------------------------------------------------------*/ + +static void msvq_interpol_fx( + Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8*/ + Word16 *w_env, /* i/o : weighting coffecients Q13*/ + Word16 *indice /* o : quantized index */ +) +{ + Word16 k, n_band, n_band2, n_band2p1, candInd[N_CAND], ind_tmp[4]; + Word16 tmp_q; + Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; + Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; + Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2], tmp; + Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; + Word16 synth_energy[SWB_FENV]; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif + + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - test(); - IF( GE_16( k, numharmonic ) && GT_16( sharpPeak, shl( sharplimit, 10 ) ) ) - { - sharpMod = 1; - move16(); - } - ELSE - { - sharpMod = 0; - move16(); - } + n_band2 = shl( n_band, 1 ); + n_band2p1 = add( n_band2, 1 ); + env_temp11[n_band] = SWB_env_energy[n_band2]; + move16(); /*Q8 */ + env_temp12[n_band] = SWB_env_energy[n_band2p1]; + move16(); /*Q8 */ + + w_env11[n_band] = w_env[n_band2]; + move16(); /*Q13 */ + w_env12[n_band] = w_env[n_band2p1]; + move16(); /*Q13 */ } - test(); - test(); - IF( sharpMod && LT_16( hBWE_FD->modeCount, 12 ) ) - { - hBWE_FD->modeCount = add( hBWE_FD->modeCount, 1 ); - } - ELSE IF( sharpMod == 0 && hBWE_FD->modeCount > 0 ) - { - hBWE_FD->modeCount = sub( hBWE_FD->modeCount, 1 ); - } + vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); - IF( GE_16( hBWE_FD->modeCount, 2 ) ) - { - sharpMod = 1; - move16(); - } + L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ - test(); - IF( sharpMod ) - { - mode = HARMONIC; - move16(); - } - ELSE IF( EQ_16( st_fx->extl, SWB_BWE ) || EQ_16( st_fx->extl, FB_BWE ) ) + FOR( k = 0; k < N_CAND; k++ ) { - L_tmp = Mult_32_16( L_mean_d, 6827 ); /*Q_syn+8 ; 1/4.8 in Q15 */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) + { + quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; + move16(); /*Q8 */ + quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); + move16(); /*Q8 */ + } - test(); - test(); - test(); - IF( GT_16( noise, 4 ) && ( LT_32( L_tmp, L_meanH ) || L_meanH == 0 ) && LT_16( tilt_nb, 10240 ) ) + ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); + ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); + + /* Extract vector for odd position */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - mode = NOISE; +#ifdef BASOP_NOGLOB + quant_tmp[n_band] = add_o( quant_tmp1[n_band], quant_tmp2[n_band], &Overflow ); +#else + quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); +#endif move16(); } - } - - return ( mode ); -} -/*-------------------------------------------------------------------* - * freq_weights_fx() - * - *-------------------------------------------------------------------*/ -static void freq_weights_fx( - const Word16 Band_Ener[], /* i : Band energy Q8 */ - const Word16 f_weighting[], /* i : weigting coefs. Q15 */ - Word16 w_env[], /* o : Freq. weighting Q13 */ - const Word16 Nbands /* i : Number of bands */ -) -{ - Word16 i; - Word16 tmp, tmp1, w1[SWB_FENV], w2[SWB_FENV]; - Word16 min_b, max_b; - Word32 L_tmp; - Word16 exp; - /* Find Max band energy */ - min_b = Band_Ener[0]; - move16(); - max_b = Band_Ener[0]; - move16(); - FOR( i = 1; i < Nbands; i++ ) - { - if ( LT_16( Band_Ener[i], min_b ) ) + FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) { - min_b = Band_Ener[i]; +#ifdef BASOP_NOGLOB + tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); /*Q8 */ +#else + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ +#endif + tmp = shr( tmp, 1 ); + quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); move16(); /*Q8 */ } - if ( GT_16( Band_Ener[i], max_b ) ) + /*quant_tmp2[n_band] = env_temp12[n_band]-quant_tmp[n_band]; */ + quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); + move16(); /*Q8 */ + + ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); + move16(); + ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk4th_fx, w_env12 + DIM3RD, DIM4TH, N_CB4TH, 1 ); + move16(); + + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - max_b = Band_Ener[i]; + quant_select[n_band * 2] = quant_tmp[n_band]; move16(); /*Q8 */ } - } - /* Find weighting function */ - tmp = sub( max_b, min_b ); /*Q8 */ - IF( tmp != 0 ) - { - exp = norm_s( tmp ); - tmp = div_s( shl( 1, sub( 14, exp ) ), tmp ); /*(21-exp) */ + FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + { #ifdef BASOP_NOGLOB - tmp = shl_sat( tmp, sub( exp, 6 ) ); /*Q15 */ + tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); #else - tmp = shl( tmp, sub( exp, 6 ) ); /*Q15 */ + tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); #endif - } - ELSE - { - tmp = 32767; - move16(); - } + tmp = shr( tmp, 1 ); + quant_select[add( shl( n_band, 1 ), 1 )] = add( tmp, quant_tmp2[n_band] ); + move16(); /*Q8 */ + } + quant_select[add( shl( n_band, 1 ), 1 )] = add( quant_tmp[n_band], quant_tmp2[n_band] ); + move16(); /*Q8 */ - FOR( i = 0; i < Nbands; i++ ) - { - tmp1 = sub( Band_Ener[i], min_b ); - L_tmp = L_mult( tmp1, tmp ); /*Q24 */ - L_tmp = L_add( L_tmp, 16777216 ); /*Q24 */ - L_tmp = L_shl( L_tmp, 5 ); /*Q29 */ - w1[i] = round_fx( L_tmp ); /*Q13 */ - move16(); - w2[i] = f_weighting[i]; - move16(); /*Q15 */ /*1~0.75*/ - w_env[i] = mult_r( w1[i], w2[i] ); - move16(); /*Q13 */ + L_dist = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) + { + tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); /*Q8 */ + L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ + L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); + } + + /* Check optimal candidate */ + IF( LT_32( L_dist, L_minDist ) ) + { + L_minDist = L_add( L_dist, 0 ); + + Copy( quant_select, synth_energy, SWB_FENV ); + + indice[0] = candInd[k]; + move16(); + indice[1] = ind_tmp[0]; + move16(); + indice[2] = ind_tmp[1]; + move16(); + indice[3] = ind_tmp[2]; + move16(); + indice[4] = ind_tmp[3]; + move16(); + } } + Copy( synth_energy, SWB_env_energy, SWB_FENV ); + return; } /*-------------------------------------------------------------------* - * vqWithCand_w_fx() + * msvq_interpol_2_fx() * *-------------------------------------------------------------------*/ -static void vqWithCand_w_fx( - const Word16 *x, /* i : input vector Q8 */ - const Word16 *E_ROM_dico, /* i : codebook Q8 */ - const Word16 dim, /* i : codebook dimension */ - const Word16 E_ROM_dico_size, /* i : codebook size */ - Word16 *index, /* o : survivors indices */ - const Word16 surv, /* i : survivor number */ - Word32 dist_min[], /* o : minimum distortion Q5 */ - const Word16 *w, /* i : weighting Q13*/ - const Word16 flag /* i : flag indicationg weighted distortion metric */ +static void msvq_interpol_2_fx( + Word16 *hq_generic_fenv, /* i/o: (original/quantized) energy */ + const Word16 *w_env, /* i : weighting coffecients */ + Word16 *indice, /* o : quantized index */ + const Word16 nenv /* i : the number of envelopes */ ) { - Word16 i, j, k, l; - const Word16 *p_E_ROM_dico; - Word16 dist, temp1; - Word32 L_dist, L_tmp; + Word16 k, n_band, n_band2, candInd[N_CAND], ind_tmp[4]; + Word16 tmp_q; + Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; + Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; + Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2]; + Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; + Word16 synth_energy[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; move32(); #endif - IF( flag ) + /* Extract target vector */ + FOR( n_band = 0; n_band < DIM11 - 1; n_band++ ) { - set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ + n_band2 = shl( n_band, 1 ); + env_temp11[n_band] = hq_generic_fenv[n_band2]; + move16(); /*Q8 */ + w_env11[n_band] = w_env[n_band2]; + move16(); /*Q13 */ + } + env_temp11[DIM11 - 1] = hq_generic_fenv[2 * ( DIM11 - 2 ) + 1]; + move16(); /*Q8 */ + w_env11[DIM11 - 1] = w_env[2 * ( DIM11 - 2 ) + 1]; + move16(); /*Q13 */ - FOR( i = 0; i < surv; i++ ) + env_temp12[0] = hq_generic_fenv[0]; + move16(); /*Q8 */ + w_env12[0] = w_env[0]; + move16(); /*Q13 */ + FOR( n_band = 1; n_band < DIM11 - 1; n_band++ ) + { + n_band2 = sub( shl( n_band, 1 ), 1 ); + env_temp12[n_band] = hq_generic_fenv[n_band2 /*2*n_band-1*/]; + move16(); /*Q8 */ + w_env12[n_band] = w_env[n_band2 /*2*n_band-1*/]; + move16(); /*Q13 */ + } + + vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); + + L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ + FOR( k = 0; k < N_CAND; k++ ) + { + FOR( n_band = 0; n_band < DIM11; n_band++ ) { - index[i] = i; + quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; + move16(); /*Q8 */ + quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); + move16(); /*Q8 */ + } + + ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); + move16(); + ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); + move16(); + + /* Extract vector for odd position */ + FOR( n_band = 0; n_band < DIM11; n_band++ ) + { + quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); + move16(); + } + + quant_tmp2[0] = sub( env_temp12[0], quant_tmp[0] ); + move16(); + FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) + { +#ifdef BASOP_NOGLOB + tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); + tmp_q = shr( tmp_q, 1 ); + quant_tmp2[n_band] = sub_o( env_temp12[n_band], tmp_q, &Overflow ); +#else + tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); + tmp_q = shr( tmp_q, 1 ); + quant_tmp2[n_band] = sub( env_temp12[n_band], tmp_q ); +#endif move16(); } - p_E_ROM_dico = E_ROM_dico; + ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); + move16(); + ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk3rd_fx, w_env12 + DIM3RD, DIM3RD, N_CB3RD, 1 ); move16(); - FOR( i = 0; i < E_ROM_dico_size; i++ ) + FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) { -#ifdef BASOP_NOGLOB - dist = sub_o( x[0], *p_E_ROM_dico++, &Overflow ); /*Q8 */ -#else - dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ -#endif - L_dist = L_mult( dist, w[0] ); /*Q22 */ - L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ - L_dist = L_shr( L_dist, 10 ); /*Q5 */ + quant_select[n_band * 2] = quant_tmp[n_band]; + move16(); /*Q8 */ + } + quant_select[11] = quant_tmp[DIM12 - 1]; + move16(); /*Q8 */ - FOR( j = 1; j < dim; j++ ) - { + quant_select[0] = add( quant_select[0], quant_tmp2[0] ); + move16(); /*Q8 */ + FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) + { #ifdef BASOP_NOGLOB - temp1 = sub_o( x[j], *p_E_ROM_dico++, &Overflow ); + tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); + tmp_q = shr( tmp_q, 1 ); + quant_select[sub( shl( n_band, 1 ), 1 )] = add_o( quant_tmp2[n_band], tmp_q, &Overflow ); #else - temp1 = sub( x[j], *p_E_ROM_dico++ ); + tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); + tmp_q = shr( tmp_q, 1 ); + quant_select[sub( shl( n_band, 1 ), 1 )] = add( quant_tmp2[n_band], tmp_q ); #endif - L_tmp = L_mult( temp1, w[j] ); /*Q22 */ - L_tmp = Mult_32_16( L_tmp, temp1 ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ - } - - FOR( k = 0; k < surv; k++ ) - { - IF( LT_32( L_dist, dist_min[k] ) ) - { - FOR( l = sub( surv, 1 ); l > k; l-- ) - { - dist_min[l] = dist_min[l - 1]; - move32(); - index[l] = index[l - 1]; - move16(); - } - dist_min[k] = L_dist; - move32(); - index[k] = i; - move16(); - BREAK; - } - } } - } - ELSE - { - set32_fx( dist_min, MAX_32, surv ); /* FLT_MAX */ - FOR( i = 0; i < surv; i++ ) + L_dist = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV - 2; n_band++ ) { - index[i] = i; - move16(); + tmp_q = sub( hq_generic_fenv[n_band], quant_select[n_band] ); /*Q8 */ + L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ + L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ + L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); } - p_E_ROM_dico = E_ROM_dico; - move16(); - - FOR( i = 0; i < E_ROM_dico_size; i++ ) + /* Check optimal candidate */ + IF( L_dist < L_minDist ) { -#ifdef BASOP_NOGLOB - dist = sub_sat( x[0], *p_E_ROM_dico++ ); /*Q8 */ -#else - dist = sub( x[0], *p_E_ROM_dico++ ); /*Q8 */ -#endif - L_dist = L_mult( dist, dist ); /*Q17 */ - L_dist = L_shr( L_dist, 12 ); /*Q5 */ - - FOR( j = 1; j < dim; j++ ) - { - temp1 = sub( x[j], *p_E_ROM_dico++ ); /*Q8 */ - L_tmp = L_mult( temp1, temp1 ); /*Q17 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ - } + L_minDist = L_add( L_dist, 0 ); + Copy( quant_select, synth_energy, SWB_FENV - 2 ); + synth_energy[SWB_FENV - 2] = 0; + move16(); + synth_energy[SWB_FENV - 1] = 0; + move16(); - FOR( k = 0; k < surv; k++ ) - { - IF( LT_32( L_dist, dist_min[k] ) ) - { - FOR( l = sub( surv, 1 ); l > k; l-- ) - { - dist_min[l] = dist_min[l - 1]; - move32(); - index[l] = index[l - 1]; - move16(); - } - dist_min[k] = L_dist; - move32(); - index[k] = i; - move16(); - BREAK; - } - } + indice[0] = candInd[k]; + move16(); + indice[1] = ind_tmp[0]; + move16(); + indice[2] = ind_tmp[1]; + move16(); + indice[3] = ind_tmp[2]; + move16(); + indice[4] = ind_tmp[3]; + move16(); } } + Copy( synth_energy, hq_generic_fenv, nenv ); + return; } + /*-------------------------------------------------------------------* - * vqSimple_w_fx() + * calculate_Tonality_fx() * + * Calculate tonality *-------------------------------------------------------------------*/ -static Word16 vqSimple_w_fx( - const Word16 *x, /* i : input for quantizer Q8 */ - Word16 *y, /* i : quantized value Q8 */ - const Word16 *cb, /* i : codebooks Q8 */ - const Word16 *w, /* i : weight Q13 */ - const Word16 dim, /* i : dimension */ - const Word16 l, /* i : number of candidates */ - const Word16 flag /* i : flag indicationg weighted distortion metric */ +static void calculate_Tonality_fx( + const Word16 *org, /* i : MDCT coefficients of original Q_new*/ + const Word16 *gen, /* i : MDCT coefficients of generated signal Q15*/ + Word16 *SFM_org, /* o : Spectral Flatness results Q12*/ + Word16 *SFM_gen, /* o : Spectral Flatness results Q12*/ + const Word16 length /* i : length for calculating tonality */ ) { - Word16 i, j, index; - const Word16 *cbP; - Word16 dist, temp; - Word32 L_dist, L_tmp, L_dist_min; + Word16 n_coeff; + Word16 inv_len, max; + Word16 exp, e_tmp, f_tmp; + Word32 L_tmp, L_tmp2, L_am_org, L_am_gen, L_tmp1; + Word16 org_spec[80], gen_spec[80]; + Word32 L_log_gm_org, L_log_gm_gen; + Word16 l_shift; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; + move32(); +#endif - index = 0; + /* to reduce dynamic range of original spectrum */ + max = 0; move16(); - L_dist_min = L_add( MAX_32, 0 ); /* FLT_MAX */ - cbP = cb; + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { + org_spec[n_coeff] = abs_s( org[n_coeff] ); + move16(); /*Q_new */ + /*test(); */ + /*if( sub(max, org_spec[n_coeff]) < 0) */ + /*{ */ + /* max = org_spec[n_coeff];move16();//Q_new */ + /*} */ + max = s_max( max, org_spec[n_coeff] ); + } + l_shift = norm_s( max ); + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { + org_spec[n_coeff] = shl( org_spec[n_coeff], l_shift ); + move16(); + IF( org_spec[n_coeff] == 0 ) + { + org_spec[n_coeff] = shl( 1, l_shift ); + move16(); + } + } + + max = 0; move16(); - IF( flag ) + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) { - FOR( i = 0; i < l; i++ ) + gen_spec[n_coeff] = abs_s( gen[n_coeff] ); + move16(); /*Q15 */ + /*test(); + if( sub(max,gen_spec[n_coeff]) < 0) { - /*dist = x[0] - *cbP++; */ - /*dist *= (dist * w[0]); */ - dist = sub( x[0], *cbP++ ); /*Q8 */ - L_dist = L_mult( dist, w[0] ); /*Q22 */ - L_dist = Mult_32_16( L_dist, dist ); /*Q15 */ - L_dist = L_shr( L_dist, 10 ); /*Q5 */ + max = gen_spec[n_coeff];move16(); + }*/ + max = s_max( max, org_spec[n_coeff] ); + } + l_shift = norm_s( max ); + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { +#ifdef BASOP_NOGLOB + gen_spec[n_coeff] = shl_sat( gen_spec[n_coeff], l_shift ); +#else + gen_spec[n_coeff] = shl( gen_spec[n_coeff], l_shift ); +#endif + move16(); + IF( gen_spec[n_coeff] == 0 ) + { + gen_spec[n_coeff] = shl( 1, l_shift ); + move16(); + } + } - FOR( j = 1; j < dim; j++ ) - { - /*temp = x[j] - *cbP++; */ - /*dist += temp * temp * w[j]; */ - temp = sub( x[j], *cbP++ ); - L_tmp = L_mult( temp, w[j] ); /*Q22 */ - L_tmp = Mult_32_16( L_tmp, temp ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); /*Q5 */ - } - IF( LT_32( L_dist, L_dist_min ) ) - { - L_dist_min = L_add( L_dist, 0 ); /*Q5 */ - index = i; - move16(); - } + exp = norm_s( length ); + inv_len = div_s( shl( 1, exp ), shl( length, exp ) ); /*Q15 */ + + L_am_org = L_deposit_l( 0 ); + L_am_gen = L_deposit_l( 0 ); + L_log_gm_org = 0; + move32(); + L_log_gm_gen = 0; + move32(); + + FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + { + L_am_org = L_add( L_am_org, L_deposit_l( org_spec[n_coeff] ) ); /*Q10 */ + L_am_gen = L_add( L_am_gen, L_deposit_l( gen_spec[n_coeff] ) ); /*Q10 */ + + IF( org_spec[n_coeff] != 0 ) + { + L_tmp = L_deposit_h( org_spec[n_coeff] ); /*Q26 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 26 ); + L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + L_log_gm_org = L_add( L_log_gm_org, L_tmp ); /*Q14 */ } + + IF( gen_spec[n_coeff] != 0 ) + { + L_tmp = L_deposit_h( gen_spec[n_coeff] ); /*Q26 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 26 ); + L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + L_log_gm_gen = L_add( L_log_gm_gen, L_tmp ); /*Q14 */ + } + } + + IF( L_am_org != 0 ) + { + L_tmp = Mpy_32_16_1( L_am_org, inv_len ); /*Q10 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 10 ); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ } ELSE { - FOR( i = 0; i < l; i++ ) - { - /*dist = x[0] - *cbP++; */ - dist = sub( x[0], *cbP++ ); - /*dist *= dist; */ - L_dist = L_mult( dist, dist ); /*Q17 */ - L_dist = L_shr( L_dist, 12 ); + L_tmp1 = L_deposit_l( 0 ); + } - FOR( j = 1; j < dim; j++ ) - { - /*temp = x[j] - *cbP++; */ - temp = sub( x[j], *cbP++ ); - /*dist += temp * temp; */ - L_tmp = L_mult( temp, temp ); /*Q17 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ - } - IF( LT_32( L_dist, L_dist_min ) ) - { - L_dist_min = L_add( L_dist, 0 ); - index = i; - move16(); - } - } + L_tmp2 = Mpy_32_16_1( L_log_gm_org, inv_len ); /* Q14 */ + + L_tmp = L_sub( L_tmp1, L_tmp2 ); +#ifdef BASOP_NOGLOB + *SFM_org = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ +#else + *SFM_org = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ +#endif + move16(); + *SFM_org = s_max( 0, s_min( *SFM_org, 24547 ) ); + move16(); /*0.0001 and 5.993 in Q12 */ + + IF( L_am_gen != 0 ) + { + L_tmp = Mpy_32_16_1( L_am_gen, inv_len ); /*Q10 */ + e_tmp = norm_l( L_tmp ); + f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); + e_tmp = sub( sub( 30, e_tmp ), 10 ); + L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + } + ELSE + { + L_tmp1 = L_deposit_l( 0 ); } + L_tmp2 = Mpy_32_16_1( L_log_gm_gen, inv_len ); /* Q14 */ - /* Reading the selected vector */ - Copy( &cb[i_mult( index, dim )], y, dim ); + L_tmp = L_sub( L_tmp1, L_tmp2 ); +#ifdef BASOP_NOGLOB + *SFM_gen = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ +#else + *SFM_gen = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ +#endif + move16(); + *SFM_gen = s_max( 0, s_min( *SFM_gen, 24547 ) ); + move16(); /*0.0001 and 5.993 in Q12 */ - return ( index ); + return; } - /*-------------------------------------------------------------------* - * MSVQ_Interpol_Tran_fx() + * energy_control_fx() * *-------------------------------------------------------------------*/ -static void MSVQ_Interpol_Tran_fx( - Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8 */ - Word16 *indice /* o : quantized index */ -) +static void energy_control_fx( + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 core, /* i : core */ + const Word16 mode, /* i : SHB BWE class */ + const Word16 coder_type, /* i : coder type */ + const Word16 *org_fx, /* i : input spectrum */ + const Word16 offset, /* i : frequency offset */ + Word16 *energy_factor_fx, /* o : energy factor */ + Word16 Q_new_lf ) { - Word16 k, n_band, candInd[N_CAND_TR], ind_tmp[2], tmp; - Word16 env_temp11[SWB_FENV_TRANS / 2], env_temp12[SWB_FENV_TRANS / 2]; - Word16 tmp_q; - Word16 quant_tmp[SWB_FENV_TRANS], quant_tmp2[SWB_FENV_TRANS]; - Word16 quant_select[SWB_FENV_TRANS]; - Word32 L_tmp, L_dist, L_minDist, distCand[N_CAND_TR]; - - /* Extract target vector */ - FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) - { - env_temp11[n_band] = SWB_env_energy[2 * n_band]; - move16(); /*Q8 */ - env_temp12[n_band] = SWB_env_energy[2 * n_band + 1]; - move16(); /*Q8 */ - } - - vqWithCand_w_fx( env_temp11, Env_TR_Cdbk1_fx, DIM_TR1, N_CB_TR1, candInd, N_CAND_TR, distCand, NULL, 0 ); - - L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ + Word16 n_band, max_band, band_step; + Word16 gamma_fx, core_type; + Word16 SWB_signal_fx[L_FRAME32k], SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - FOR( k = 0; k < N_CAND_TR; k++ ) + IF( EQ_16( core, ACELP_CORE ) ) { - FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) + gamma_fx = 11469; + move16(); /*.35 in Q15 */ + test(); + IF( NE_16( coder_type, AUDIO ) && LT_32( st_fx->total_brate, ACELP_8k85 ) ) { - quant_tmp[n_band] = Env_TR_Cdbk1_fx[add( shl( candInd[k], 1 ), n_band )]; - move16(); /*DIM_TR1 == 2*/ + core_type = 0; + move16(); } - - FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) + ELSE { - /*quant_tmp2[n_band] = env_temp12[n_band] - ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f); */ - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ - tmp = shr( tmp, 1 ); - quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); - move16(); /*Q8 */ + core_type = 1; + move16(); } - /*quant_tmp2[n_band] = env_temp12[n_band] - quant_tmp[n_band]; */ - quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); - move16(); /*Q8 */ - ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, Env_TR_Cdbk2_fx, NULL, DIM_TR2, N_CB_TR2, 0 ); - move16(); + get_normalize_spec_fx( core, st_fx->extl, mode, core_type, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - FOR( n_band = 0; n_band < DIM_TR1; n_band++ ) + IF( EQ_16( st_fx->extl, WB_BWE ) ) { - quant_select[n_band * 2] = quant_tmp[n_band]; + max_band = 4; + move16(); + band_step = 2; move16(); } - - FOR( n_band = 0; n_band < DIM_TR2 - 1; n_band++ ) + ELSE { - /*quant_select[n_band*2+1] = ((quant_tmp[n_band]+quant_tmp[n_band+1])/2.f) + quant_tmp2[n_band]; */ - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ - tmp = shr( tmp, 1 ); - quant_select[n_band * 2 + 1] = add( tmp, quant_tmp2[n_band] ); + max_band = SWB_FENV; + move16(); + band_step = 1; move16(); } - /*quant_select[n_band*2+1] = quant_tmp[n_band]+quant_tmp2[n_band]; */ - quant_select[n_band * 2 + 1] = add( quant_tmp[n_band], quant_tmp2[n_band] ); - move16(); + } + ELSE /* HQ core */ + { + gamma_fx = 18022; + move16(); /*.55 in Q15 */ + get_normalize_spec_fx( core, st_fx->extl, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - L_dist = L_deposit_l( 0 ); - FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) + band_step = 1; + move16(); + IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) { - /*tmp_q = SWB_env_energy[n_band] - quant_select[n_band]; */ - tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); - /*dist += tmp_q*tmp_q; */ - L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 12 ) ); /*Q5 */ + max_band = 12; + move16(); } - - /* Check optimal candidate */ - IF( LT_32( L_dist, L_minDist ) ) + ELSE { - L_minDist = L_add( L_dist, 0 ); - indice[0] = candInd[k]; - move16(); - indice[1] = ind_tmp[0]; + max_band = SWB_FENV; move16(); } } + + FOR( n_band = 0; n_band < max_band; ) + { + calculate_Tonality_fx( org_fx + swb_bwe_subband[n_band] + offset, SWB_signal_fx + swb_bwe_subband[n_band] + offset, + &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[n_band + band_step] - swb_bwe_subband[n_band] ); + + IF( LT_16( SFM_gen_fx[n_band], mult_r( 24576, SFM_org_fx[n_band] ) ) ) + { + energy_factor_fx[n_band] = div_s( SFM_gen_fx[n_band], SFM_org_fx[n_band] ); /*Q15 */ + IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + { + energy_factor_fx[n_band] = gamma_fx; + move16(); + } + } + ELSE + { + energy_factor_fx[n_band] = 32767; + move16(); /* Q15 */ + } + n_band = add( n_band, band_step ); + } return; } /*-------------------------------------------------------------------* - * MSVQ_Interpol_fx() + * energy_control_ivas_fx() * *-------------------------------------------------------------------*/ -static void msvq_interpol_fx( - Word16 *SWB_env_energy, /* i/o : (original/quantized) energy Q8*/ - Word16 *w_env, /* i/o : weighting coffecients Q13*/ - Word16 *indice /* o : quantized index */ -) +static void energy_control_ivas_fx( + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 core, /* i : core */ + const Word16 mode, /* i : SHB BWE class */ + const Word16 coder_type, /* i : coder type */ + const Word16 *org_fx, /* i : input spectrum */ + const Word16 offset, /* i : frequency offset */ + Word16 *energy_factor_fx, /* o : energy factor */ + Word16 Q_new_lf ) { - Word16 k, n_band, n_band2, n_band2p1, candInd[N_CAND], ind_tmp[4]; - Word16 tmp_q; - Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; - Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; - Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2], tmp; - Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; - Word16 synth_energy[SWB_FENV]; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - - /* Extract target vector */ - FOR( n_band = 0; n_band < DIM11; n_band++ ) - { - n_band2 = shl( n_band, 1 ); - n_band2p1 = add( n_band2, 1 ); - env_temp11[n_band] = SWB_env_energy[n_band2]; - move16(); /*Q8 */ - env_temp12[n_band] = SWB_env_energy[n_band2p1]; - move16(); /*Q8 */ - - w_env11[n_band] = w_env[n_band2]; - move16(); /*Q13 */ - w_env12[n_band] = w_env[n_band2p1]; - move16(); /*Q13 */ - } - - vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); - - L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ + Word16 n_band, max_band, band_step; + Word16 gamma_fx, core_type; + Word16 SWB_signal_fx[L_FRAME32k], SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; - FOR( k = 0; k < N_CAND; k++ ) + IF( EQ_16( core, ACELP_CORE ) ) { - FOR( n_band = 0; n_band < DIM11; n_band++ ) + gamma_fx = 11469; + move16(); /*.35 in Q15 */ + test(); + IF( NE_16( coder_type, AUDIO ) && LE_32( st_fx->total_brate, ACELP_8k00 ) ) { - quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; - move16(); /*Q8 */ - quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); - move16(); /*Q8 */ + core_type = 0; + move16(); } - - ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); - ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); - - /* Extract vector for odd position */ - FOR( n_band = 0; n_band < DIM11; n_band++ ) + ELSE { -#ifdef BASOP_NOGLOB - quant_tmp[n_band] = add_o( quant_tmp1[n_band], quant_tmp2[n_band], &Overflow ); -#else - quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); -#endif + core_type = 1; move16(); } + get_normalize_spec_fx( core, st_fx->extl, mode, core_type, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + IF( EQ_16( st_fx->extl, WB_BWE ) ) { -#ifdef BASOP_NOGLOB - tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); /*Q8 */ -#else - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); /*Q8 */ -#endif - tmp = shr( tmp, 1 ); - quant_tmp2[n_band] = sub( env_temp12[n_band], tmp ); - move16(); /*Q8 */ + max_band = 4; + move16(); + band_step = 2; + move16(); } - - /*quant_tmp2[n_band] = env_temp12[n_band]-quant_tmp[n_band]; */ - quant_tmp2[n_band] = sub( env_temp12[n_band], quant_tmp[n_band] ); - move16(); /*Q8 */ - - ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); - move16(); - ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk4th_fx, w_env12 + DIM3RD, DIM4TH, N_CB4TH, 1 ); - move16(); - - FOR( n_band = 0; n_band < DIM11; n_band++ ) + ELSE { - quant_select[n_band * 2] = quant_tmp[n_band]; - move16(); /*Q8 */ + max_band = SWB_FENV; + move16(); + band_step = 1; + move16(); } + } + ELSE /* HQ core */ + { + gamma_fx = 18022; + move16(); /*.55 in Q15 */ + get_normalize_spec_fx( core, st_fx->extl, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + band_step = 1; + move16(); + IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) { -#ifdef BASOP_NOGLOB - tmp = add_o( quant_tmp[n_band], quant_tmp[n_band + 1], &Overflow ); -#else - tmp = add( quant_tmp[n_band], quant_tmp[n_band + 1] ); -#endif - tmp = shr( tmp, 1 ); - quant_select[add( shl( n_band, 1 ), 1 )] = add( tmp, quant_tmp2[n_band] ); - move16(); /*Q8 */ + max_band = 12; + move16(); } - quant_select[add( shl( n_band, 1 ), 1 )] = add( quant_tmp[n_band], quant_tmp2[n_band] ); - move16(); /*Q8 */ - - L_dist = L_deposit_l( 0 ); - FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) + ELSE { - tmp_q = sub( SWB_env_energy[n_band], quant_select[n_band] ); /*Q8 */ - L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ - L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); + max_band = SWB_FENV; + move16(); } + } - /* Check optimal candidate */ - IF( LT_32( L_dist, L_minDist ) ) - { - L_minDist = L_add( L_dist, 0 ); - - Copy( quant_select, synth_energy, SWB_FENV ); + FOR( n_band = 0; n_band < max_band; ) + { + calculate_Tonality_fx( org_fx + swb_bwe_subband[n_band] + offset, SWB_signal_fx + swb_bwe_subband[n_band] + offset, + &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[n_band + band_step] - swb_bwe_subband[n_band] ); - indice[0] = candInd[k]; - move16(); - indice[1] = ind_tmp[0]; - move16(); - indice[2] = ind_tmp[1]; - move16(); - indice[3] = ind_tmp[2]; - move16(); - indice[4] = ind_tmp[3]; + IF( LT_16( SFM_gen_fx[n_band], mult_r( 24576, SFM_org_fx[n_band] ) ) ) + { + energy_factor_fx[n_band] = div_s( SFM_gen_fx[n_band], SFM_org_fx[n_band] ); /*Q15 */ move16(); + IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + { + energy_factor_fx[n_band] = gamma_fx; + move16(); + } + } + ELSE + { + energy_factor_fx[n_band] = 32767; + move16(); /* Q15 */ } + n_band = add( n_band, band_step ); } - - Copy( synth_energy, SWB_env_energy, SWB_FENV ); - return; } /*-------------------------------------------------------------------* - * msvq_interpol_2_fx() + * WB_BWE_encoding() * + * WB BWE main encoder *-------------------------------------------------------------------*/ -static void msvq_interpol_2_fx( - Word16 *hq_generic_fenv, /* i/o: (original/quantized) energy */ - const Word16 *w_env, /* i : weighting coffecients */ - Word16 *indice, /* o : quantized index */ - const Word16 nenv /* i : the number of envelopes */ -) -{ - Word16 k, n_band, n_band2, candInd[N_CAND], ind_tmp[4]; - Word16 tmp_q; - Word16 env_temp11[SWB_FENV / 2], env_temp12[SWB_FENV / 2]; - Word16 quant_tmp[SWB_FENV], quant_tmp1[SWB_FENV], quant_tmp2[SWB_FENV]; - Word16 quant_select[SWB_FENV], w_env11[SWB_FENV / 2], w_env12[SWB_FENV / 2]; - Word32 L_tmp, distCand[N_CAND], L_dist, L_minDist; - Word16 synth_energy[SWB_FENV]; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; - move32(); -#endif - /* Extract target vector */ - FOR( n_band = 0; n_band < DIM11 - 1; n_band++ ) - { - n_band2 = shl( n_band, 1 ); - env_temp11[n_band] = hq_generic_fenv[n_band2]; - move16(); /*Q8 */ - w_env11[n_band] = w_env[n_band2]; - move16(); /*Q13 */ - } - env_temp11[DIM11 - 1] = hq_generic_fenv[2 * ( DIM11 - 2 ) + 1]; - move16(); /*Q8 */ - w_env11[DIM11 - 1] = w_env[2 * ( DIM11 - 2 ) + 1]; - move16(); /*Q13 */ - - env_temp12[0] = hq_generic_fenv[0]; - move16(); /*Q8 */ - w_env12[0] = w_env[0]; - move16(); /*Q13 */ - FOR( n_band = 1; n_band < DIM11 - 1; n_band++ ) - { - n_band2 = sub( shl( n_band, 1 ), 1 ); - env_temp12[n_band] = hq_generic_fenv[n_band2 /*2*n_band-1*/]; - move16(); /*Q8 */ - w_env12[n_band] = w_env[n_band2 /*2*n_band-1*/]; - move16(); /*Q13 */ - } - vqWithCand_w_fx( env_temp11, EnvCdbk11_fx, DIM11, N_CB11, candInd, N_CAND, distCand, w_env11, 1 ); +Word16 WB_BWE_encoding_fx( /* o : classification of wb signal */ + const Word16 coder_type, /* i : coder type */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Encoder_State *st_fx, /* i/o: Encoder structure */ + Word16 Q_synth, + Word16 Q_synth_lf ) +{ + Word16 mode; + Word16 i, n_coeff, n_band; + Word16 index; + Word32 energy_fx; + Word32 L_WB_fenv_fx[2]; + Word16 energy_factor_fx[4]; + Word16 ener_40, exp; + Word32 L_tmp; + Word16 tmp; - L_minDist = L_add( MAX_32, 0 ); /* FLT_MAX */ - FOR( k = 0; k < N_CAND; k++ ) + n_band = 0; + move16(); + FOR( i = 0; i < 2; i++ ) { - FOR( n_band = 0; n_band < DIM11; n_band++ ) + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band + 2]; n_coeff++ ) { - quant_tmp1[n_band] = EnvCdbk11_fx[add( i_mult2( candInd[k], DIM11 ), n_band )]; - move16(); /*Q8 */ - quant_tmp2[n_band] = sub( env_temp11[n_band], quant_tmp1[n_band] ); - move16(); /*Q8 */ + energy_fx = L_add( energy_fx, L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 6 ) ); /*2*Q_synth-6 */ } - ind_tmp[0] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk1st_fx, w_env11, DIM1ST, N_CB1ST, 1 ); - move16(); - ind_tmp[1] = vqSimple_w_fx( quant_tmp2 + DIM1ST, quant_tmp2 + DIM1ST, EnvCdbk2nd_fx, w_env11 + DIM1ST, DIM2ND, N_CB2ND, 1 ); - move16(); - - /* Extract vector for odd position */ - FOR( n_band = 0; n_band < DIM11; n_band++ ) - { - quant_tmp[n_band] = add( quant_tmp1[n_band], quant_tmp2[n_band] ); - move16(); - } + L_WB_fenv_fx[i] = energy_fx; + move32(); /*2*Q_synth-6 */ + n_band = add( n_band, 2 ); + } + mode = FD_BWE_class_fx( yos_fx, 0, 0, Q_synth, 0, st_fx ); - quant_tmp2[0] = sub( env_temp12[0], quant_tmp[0] ); - move16(); - FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) - { -#ifdef BASOP_NOGLOB - tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); - tmp_q = shr( tmp_q, 1 ); - quant_tmp2[n_band] = sub_o( env_temp12[n_band], tmp_q, &Overflow ); -#else - tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); - tmp_q = shr( tmp_q, 1 ); - quant_tmp2[n_band] = sub( env_temp12[n_band], tmp_q ); -#endif - move16(); - } - ind_tmp[2] = vqSimple_w_fx( quant_tmp2, quant_tmp2, EnvCdbk3rd_fx, w_env12, DIM3RD, N_CB3RD, 1 ); - move16(); - ind_tmp[3] = vqSimple_w_fx( quant_tmp2 + DIM3RD, quant_tmp2 + DIM3RD, EnvCdbk3rd_fx, w_env12 + DIM3RD, DIM3RD, N_CB3RD, 1 ); - move16(); + energy_control_fx( st_fx, ACELP_CORE, mode, coder_type, yos_fx, 0, energy_factor_fx, Q_synth_lf ); - FOR( n_band = 0; n_band < DIM12 - 1; n_band++ ) + FOR( i = 0; i < 2; i++ ) + { + ener_40 = mult_r( shr( energy_factor_fx[shl( i, 1 )], 1 ), 26214 ); /*Q19 */ + L_tmp = Mult_32_16( L_WB_fenv_fx[i], ener_40 ); /*2*Q_synth-2 */ + IF( L_tmp ) { - quant_select[n_band * 2] = quant_tmp[n_band]; - move16(); /*Q8 */ + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = 30-exp-(2*Q_synth-2); */ + exp = sub( sub( 30, exp ), ( sub( shl( Q_synth, 1 ), 2 ) ) ); + L_tmp = Mpy_32_16( exp, tmp, 32767 ); /* Q16 */ + WB_fenv_fx[i] = round_fx( L_shl( L_tmp, 10 ) ); /*Q10 */ } - quant_select[11] = quant_tmp[DIM12 - 1]; - move16(); /*Q8 */ - - quant_select[0] = add( quant_select[0], quant_tmp2[0] ); - move16(); /*Q8 */ - FOR( n_band = 1; n_band < DIM12 - 1; n_band++ ) + ELSE { -#ifdef BASOP_NOGLOB - tmp_q = add_o( quant_tmp[n_band - 1], quant_tmp[n_band], &Overflow ); - tmp_q = shr( tmp_q, 1 ); - quant_select[sub( shl( n_band, 1 ), 1 )] = add_o( quant_tmp2[n_band], tmp_q, &Overflow ); -#else - tmp_q = add( quant_tmp[n_band - 1], quant_tmp[n_band] ); - tmp_q = shr( tmp_q, 1 ); - quant_select[sub( shl( n_band, 1 ), 1 )] = add( quant_tmp2[n_band], tmp_q ); -#endif + WB_fenv_fx[i] = 0; + move16(); } + } - L_dist = L_deposit_l( 0 ); - FOR( n_band = 0; n_band < SWB_FENV - 2; n_band++ ) + index = WB_BWE_fenv_q_fx( WB_fenv_fx, F_2_5_fx, 32, 2 ); + + push_indice_fx( st_fx->hBstr, IND_WB_FENV, index, 5 ); + + return ( mode ); +} + +/*-------------------------------------------------------------------* + * WB_BWE_encoding_ivas() + * + * WB BWE main encoder + *-------------------------------------------------------------------*/ + +Word16 WB_BWE_encoding_ivas_fx( /* o : classification of wb signal */ + Encoder_State *st_fx, /* i/o: Encoder structure */ + const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ + Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ + Word16 Q_synth, + Word16 Q_synth_lf ) +{ + Word16 mode; + Word16 i, n_coeff, n_band; + Word16 index; + Word32 energy_fx; + Word32 L_WB_fenv_fx[2]; + Word16 energy_factor_fx[4]; + Word16 ener_40, exp; + Word32 L_tmp; + Word16 tmp; + + n_band = 0; + move16(); + FOR( i = 0; i < 2; i++ ) + { + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band + 2]; n_coeff++ ) { - tmp_q = sub( hq_generic_fenv[n_band], quant_select[n_band] ); /*Q8 */ - L_tmp = L_mult( tmp_q, tmp_q ); /*Q17 */ - L_tmp = Mult_32_16( L_tmp, w_env[n_band] ); /*Q15 */ - L_dist = L_add( L_dist, L_shr( L_tmp, 10 ) ); + energy_fx = L_add( energy_fx, L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 6 ) ); /*2*Q_synth-6 */ } - /* Check optimal candidate */ - IF( L_dist < L_minDist ) - { - L_minDist = L_add( L_dist, 0 ); - Copy( quant_select, synth_energy, SWB_FENV - 2 ); - synth_energy[SWB_FENV - 2] = 0; - move16(); - synth_energy[SWB_FENV - 1] = 0; - move16(); + L_WB_fenv_fx[i] = energy_fx; + move32(); /*2*Q_synth-6 */ + n_band = add( n_band, 2 ); + } + mode = FD_BWE_class_fx( yos_fx, 0, 0, Q_synth, 0, st_fx ); - indice[0] = candInd[k]; - move16(); - indice[1] = ind_tmp[0]; - move16(); - indice[2] = ind_tmp[1]; - move16(); - indice[3] = ind_tmp[2]; + energy_control_ivas_fx( st_fx, ACELP_CORE, mode, st_fx->coder_type, yos_fx, 0, energy_factor_fx, Q_synth_lf ); + + FOR( i = 0; i < 2; i++ ) + { + ener_40 = mult_r( shr( energy_factor_fx[shl( i, 1 )], 1 ), 26214 ); /*Q19 */ + L_tmp = Mpy_32_16_1( L_WB_fenv_fx[i], ener_40 ); /*2*Q_synth-2 */ + IF( L_tmp ) + { + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = 30-exp-(2*Q_synth-2); */ + exp = sub( sub( 30, exp ), ( sub( shl( Q_synth, 1 ), 2 ) ) ); + L_tmp = Mpy_32_16( exp, tmp, 32767 ); /* Q16 */ + WB_fenv_fx[i] = round_fx( L_shl( L_tmp, 10 ) ); /*Q10 */ move16(); - indice[4] = ind_tmp[3]; + } + ELSE + { + WB_fenv_fx[i] = 0; move16(); } } - Copy( synth_energy, hq_generic_fenv, nenv ); + index = WB_BWE_fenv_q_fx( WB_fenv_fx, F_2_5_fx, 32, 2 ); - return; -} + push_indice( st_fx->hBstr, IND_WB_FENV, index, 5 ); + return ( mode ); +} /*-------------------------------------------------------------------* - * calculate_Tonality_fx() + * SWB_BWE_encoding() * - * Calculate tonality + * SWB BWE encoder *-------------------------------------------------------------------*/ - -static void calculate_Tonality_fx( - const Word16 *org, /* i : MDCT coefficients of original Q_new*/ - const Word16 *gen, /* i : MDCT coefficients of generated signal Q15*/ - Word16 *SFM_org, /* o : Spectral Flatness results Q12*/ - Word16 *SFM_gen, /* o : Spectral Flatness results Q12*/ - const Word16 length /* i : length for calculating tonality */ -) +static Word16 SWB_BWE_encoding_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 *insig_fx, /* i : delayed original input signal at 32kHz */ + const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ + const Word16 *insig_hp_fx, /* i : delayed original highband input signal at 32kHz */ + const Word16 *synth_fx, /* i : delayed ACELP core synthesis at 12.8kHz */ + const Word16 *yos_fx, /* i : MDCT coefficients of the windowed original input signal at 32kHz */ + Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ + const Word16 tilt_nb_fx, /* i : SWB tilt */ + const Word16 st_offset, /* i : start frequency offset for BWE envelope */ + const Word16 coder_type, /* i : coding type */ + Word16 Q_insig_lp, + Word16 Q_shb, + Word16 Q_synth, + Word16 Q_synth_lf ) { - Word16 n_coeff; - Word16 inv_len, max; - Word16 exp, e_tmp, f_tmp; - Word32 L_tmp, L_tmp2, L_am_org, L_am_gen, L_tmp1; - Word16 org_spec[80], gen_spec[80]; - Word32 L_log_gm_org, L_log_gm_gen; - Word16 l_shift; + Word16 IsTransient, mode; + Word16 index; + Word16 i, n_coeff, n_band, pos, indice[6]; + Word16 L; + Word16 IsTransient_LF; + + Word16 tmp; + Word32 energy_fx; + Word16 tilt_fx; + Word32 global_gain_fx; + Word32 L_tmp; + Word32 L_SWB_fenv_fx[SWB_FENV]; + Word16 SWB_tenv_fx[SWB_TENV]; + Word32 L_SWB_tenv, WB_tenv_syn_fx, WB_tenv_orig_fx; + Word16 exp, expn, expd; + Word16 num, den; + Word16 scale; + Word16 Rat_tenv_fx; + Word16 SWB_tenv_tmp_fx[SWB_TENV]; + Word16 max_fx; + Word16 energy_factor_fx[SWB_FENV], w_env_fx[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; #endif - /* to reduce dynamic range of original spectrum */ - max = 0; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16( st_fx->L_frame, L_FRAME ) ) + { + L = L_SUBFR; + move16(); + } + ELSE + { + L = L_SUBFR16k; + move16(); + } + + /* HF transient detect */ + IsTransient = detect_transient_fx( insig_hp_fx, L_FRAME16k, Q_shb, st_fx ); + st_fx->EnergyLT_fx_exp = shl( Q_shb, 1 ); + + /* LF transient detect */ + IsTransient_LF = 0; move16(); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + FOR( n_band = 0; n_band < 4; n_band++ ) { - org_spec[n_coeff] = abs_s( org[n_coeff] ); - move16(); /*Q_new */ - /*test(); */ - /*if( sub(max, org_spec[n_coeff]) < 0) */ - /*{ */ - /* max = org_spec[n_coeff];move16();//Q_new */ - /*} */ - max = s_max( max, org_spec[n_coeff] ); + tmp = i_mult2( n_band, L ); + energy_fx = L_deposit_l( 0 ); + FOR( i = 0; i < L; i++ ) + { + energy_fx = L_add( energy_fx, L_shr( L_mult0( insig_lp_fx[i + tmp], insig_lp_fx[i + tmp] ), 7 ) ); /*2*Q_slb_speech - 7 */ + } + + IF( GT_32( Mult_32_16( energy_fx, 5958 ), hBWE_FD->EnergyLF_fx ) ) + { + IsTransient_LF = 1; + move16(); + } + + hBWE_FD->EnergyLF_fx = energy_fx; + move32(); } - l_shift = norm_s( max ); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) + + /* tilt returned in Q24 go to Q11 */ +#ifdef BASOP_NOGLOB + tilt_fx = round_fx_o( L_shl_o( calc_tilt_bwe_fx( insig_fx, 0, L_FRAME32k ), 3, &Overflow ), &Overflow ); +#else + tilt_fx = round_fx( L_shl( calc_tilt_bwe_fx( insig_fx, 0, L_FRAME32k ), 3 ) ); +#endif + test(); + test(); + IF( EQ_16( IsTransient, 1 ) && ( GT_16( tilt_fx, 16384 ) || GT_16( st_fx->clas, 1 ) ) ) { - org_spec[n_coeff] = shl( org_spec[n_coeff], l_shift ); + IsTransient = 0; move16(); - test(); - if ( org_spec[n_coeff] == 0 ) + st_fx->TransientHangOver = 0; + move16(); + } + + IF( EQ_16( IsTransient, 1 ) ) + { + mode = IsTransient; + move16(); + push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) { - org_spec[n_coeff] = shl( 1, l_shift ); + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_trans_subband[n_band] + st_offset; n_coeff < swb_bwe_trans_subband[n_band + 1] + st_offset; n_coeff++ ) + { + L_tmp = L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 7 ); /*2*Q_synth-7 */ + energy_fx = L_add( L_tmp, energy_fx ); /*2*Q_synth-7 */ + } + global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( sub( shl( Q_synth, 1 ), 7 ), shl( Q_shb, 1 ) ) ) ); /*2*Q_shb */ + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + global_gain_fx = L_shr( global_gain_fx, 1 ); /*2*Q_shb */ + + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) + { + expd = norm_s( swb_bwe_trans_subband_width[n_band] ); + tmp = div_s( shl( 1, sub( 14, expd ) ), swb_bwe_trans_subband_width[n_band] ); /*Q(29-expd) */ + L_tmp = Mult_32_16( L_SWB_fenv_fx[n_band], tmp ); /*2*Q_synth-7+29-expd - 15 */ + exp = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); move16(); + exp = sub( sub( 30, exp ), sub( add( shl( Q_synth, 1 ), 7 ), expd ) ); + L_tmp = Mpy_32_16( exp, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + tmp = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + + SWB_fenv_fx[n_band] = sub( tmp, Mean_env_tr_fx[n_band] ); + move16(); /*Q8 */ } - } - max = 0; - move16(); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) - { - gen_spec[n_coeff] = abs_s( gen[n_coeff] ); - move16(); /*Q15 */ - /*test(); - if( sub(max,gen_spec[n_coeff]) < 0) + WB_tenv_orig_fx = L_deposit_l( 0 ); + WB_tenv_syn_fx = L_deposit_l( 1 ); + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) { - max = gen_spec[n_coeff];move16(); - }*/ - max = s_max( max, org_spec[n_coeff] ); - } - l_shift = norm_s( max ); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) - { + tmp = i_mult2( n_band, L_SUBFR16k ); + L_SWB_tenv = L_deposit_l( 0 ); + FOR( i = 0; i < L_SUBFR16k; i++ ) + { #ifdef BASOP_NOGLOB - gen_spec[n_coeff] = shl_sat( gen_spec[n_coeff], l_shift ); + L_SWB_tenv = L_add_sat( L_SWB_tenv, L_mult0( insig_hp_fx[i + tmp], insig_hp_fx[i + tmp] ) ); /*2*Q_shb */ #else - gen_spec[n_coeff] = shl( gen_spec[n_coeff], l_shift ); + L_SWB_tenv = L_add( L_SWB_tenv, L_mult0( insig_hp_fx[i + tmp], insig_hp_fx[i + tmp] ) ); /*2*Q_shb */ #endif - move16(); - test(); - if ( gen_spec[n_coeff] == 0 ) - { - gen_spec[n_coeff] = shl( 1, l_shift ); - move16(); - } - } + } - exp = norm_s( length ); - inv_len = div_s( shl( 1, exp ), shl( length, exp ) ); /*Q15 */ + tmp = i_mult2( n_band, L ); + FOR( i = 0; i < L; i++ ) + { + WB_tenv_syn_fx = L_add( WB_tenv_syn_fx, L_shr( L_mult0( synth_fx[i + tmp], synth_fx[i + tmp] ), 7 ) ); /*2*st_fx->Q_syn2 - 7 */ + WB_tenv_orig_fx = L_add( WB_tenv_orig_fx, L_shr( L_mult0( insig_lp_fx[i + tmp], insig_lp_fx[i + tmp] ), 7 ) ); /*2*Q_insig_lp - 7 */ + } - L_am_org = L_deposit_l( 0 ); - L_am_gen = L_deposit_l( 0 ); - L_log_gm_org = 0; - move16(); - L_log_gm_gen = 0; - move16(); + L_tmp = Mult_32_16( L_SWB_tenv, INV_L_SUBFR16k_FX ); /*2*Q_shb */ + SWB_tenv_fx[n_band] = 0; + move16(); + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( exp, sub( 30, 2 * Q_shb ) ); - FOR( n_coeff = 0; n_coeff < length; n_coeff++ ) - { - L_am_org = L_add( L_am_org, L_deposit_l( org_spec[n_coeff] ) ); /*Q10 */ - L_am_gen = L_add( L_am_gen, L_deposit_l( gen_spec[n_coeff] ) ); /*Q10 */ + tmp = div_s( 16384, tmp ); + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &exp ); /*Q(31-exp) */ - IF( org_spec[n_coeff] != 0 ) - { - L_tmp = L_deposit_h( org_spec[n_coeff] ); /*Q26 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 26 ); - L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - L_log_gm_org = L_add( L_log_gm_org, L_tmp ); /*Q14 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[n_band] = round_fx_sat( L_shl_sat( L_tmp, sub( exp, 12 ) ) ); /*Q3 */ +#else + SWB_tenv_fx[n_band] = round_fx( L_shl( L_tmp, sub( exp, 12 ) ) ); /*Q3 */ +#endif + } } - IF( gen_spec[n_coeff] != 0 ) + IF( WB_tenv_orig_fx != 0 ) { - L_tmp = L_deposit_h( gen_spec[n_coeff] ); /*Q26 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 26 ); - L_tmp = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - L_log_gm_gen = L_add( L_log_gm_gen, L_tmp ); /*Q14 */ - } - } + expn = norm_l( WB_tenv_orig_fx ); + num = extract_h( L_shl( WB_tenv_orig_fx, expn ) ); + expn = sub( sub( 30, expn ), sub( shl( Q_insig_lp, 1 ), 7 ) ); - IF( L_am_org != 0 ) - { - L_tmp = Mult_32_16( L_am_org, inv_len ); /*Q10 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 10 ); - L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - } - ELSE - { - L_tmp1 = L_deposit_l( 0 ); - } + expd = norm_l( WB_tenv_syn_fx ); + den = round_fx( L_shl( WB_tenv_syn_fx, expd ) ); + expd = sub( sub( 30, expd ), sub( shl( st_fx->Q_syn2, 1 ), 7 ) ); - L_tmp2 = Mult_32_16( L_log_gm_org, inv_len ); /* Q14 */ + scale = shr( sub( den, num ), 15 ); + num = shl( num, scale ); + expn = sub( expn, scale ); + + tmp = div_s( num, den ); + expn = sub( expn, expd ); + + L_tmp = L_deposit_h( tmp ); + L_tmp = Isqrt_lc( L_tmp, &expn ); /*31-expn */ - L_tmp = L_sub( L_tmp1, L_tmp2 ); - move16(); /*Q14 */ #ifdef BASOP_NOGLOB - *SFM_org = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ + Rat_tenv_fx = round_fx_o( L_shl_o( L_tmp, sub( expn, 1 ), &Overflow ), &Overflow ); /*Q14 */ #else - *SFM_org = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ + Rat_tenv_fx = round_fx( L_shl( L_tmp, sub( expn, 1 ) ) ); /*Q14 */ #endif - *SFM_org = s_max( 0, s_min( *SFM_org, 24547 ) ); - move16(); /*0.0001 and 5.993 in Q12 */ - - IF( L_am_gen != 0 ) - { - L_tmp = Mult_32_16( L_am_gen, inv_len ); /*Q10 */ - e_tmp = norm_l( L_tmp ); - f_tmp = Log2_norm_lc( L_shl( L_tmp, e_tmp ) ); - e_tmp = sub( sub( 30, e_tmp ), 10 ); - L_tmp1 = Mpy_32_16( e_tmp, f_tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ - } - ELSE - { - L_tmp1 = L_deposit_l( 0 ); - } - - L_tmp2 = Mult_32_16( L_log_gm_gen, inv_len ); /* Q14 */ + } + ELSE + { + Rat_tenv_fx = 16384; + move16(); + } - L_tmp = L_sub( L_tmp1, L_tmp2 ); - move16(); /*Q14 */ + IF( LT_16( Rat_tenv_fx, 8192 ) ) + { + L_tmp = L_mult( Rat_tenv_fx, 19661 ); /*Q29 */ #ifdef BASOP_NOGLOB - *SFM_gen = round_fx_o( L_shl_o( L_tmp, 14, &Overflow ), &Overflow ); /*Q12 */ + Rat_tenv_fx = round_fx_o( L_shl_o( L_tmp, 2, &Overflow ), &Overflow ); /*Q15 */ #else - *SFM_gen = round_fx( L_shl( L_tmp, 14 ) ); /*Q12 */ + Rat_tenv_fx = round_fx( L_shl( L_tmp, 2 ) ); /*Q15 */ #endif - *SFM_gen = s_max( 0, s_min( *SFM_gen, 24547 ) ); - move16(); /*0.0001 and 5.993 in Q12 */ - - return; -} - -/*-------------------------------------------------------------------* - * energy_control_fx() - * - *-------------------------------------------------------------------*/ + } + ELSE IF( GT_16( Rat_tenv_fx, 16384 ) ) + { + Rat_tenv_fx = 32767; + move16(); + } -static void energy_control_fx( - Encoder_State *st_fx, /* i/o: Encoder structure */ - const Word16 core, /* i : core */ - const Word16 mode, /* i : SHB BWE class */ - const Word16 coder_type, /* i : coder type */ - const Word16 *org_fx, /* i : input spectrum */ - const Word16 offset, /* i : frequency offset */ - Word16 *energy_factor_fx, /* o : energy factor */ - Word16 Q_new_lf ) -{ - Word16 n_band, max_band, band_step; - Word16 gamma_fx, core_type; - Word16 SWB_signal_fx[L_FRAME32k], SFM_org_fx[SWB_FENV], SFM_gen_fx[SWB_FENV]; - FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], Rat_tenv_fx ); + move16(); /*Q3 */ + } - IF( EQ_16( core, ACELP_CORE ) ) - { - gamma_fx = 11469; - move16(); /*.35 in Q15 */ - test(); - IF( NE_16( coder_type, AUDIO ) && LT_32( st_fx->total_brate, ACELP_8k85 ) ) + max_fx = SWB_tenv_fx[0]; + move16(); + pos = 0; + move16(); + FOR( n_band = 1; n_band < SWB_TENV; n_band++ ) { - core_type = 0; - move16(); + IF( GT_16( SWB_tenv_fx[n_band], max_fx ) ) + { + max_fx = SWB_tenv_fx[n_band]; + move16(); + pos = n_band; + move16(); + } } - ELSE + + max_fx = SWB_tenv_fx[0]; + move16(); + FOR( n_band = 1; n_band < SWB_TENV; n_band++ ) { - core_type = 1; - move16(); + tmp = sub( mult_r( SWB_tenv_fx[n_band], 6554 ), SWB_tenv_fx[n_band - 1] ); + IF( tmp > 0 ) + { + BREAK; + } } - get_normalize_spec_fx( core, st_fx->extl, mode, core_type, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - IF( EQ_16( st_fx->extl, WB_BWE ) ) + IF( n_band < SWB_TENV ) { - max_band = 4; - move16(); - band_step = 2; - move16(); + energy_fx = L_deposit_l( 0 ); + FOR( n_band = ( pos + 1 ); n_band < SWB_TENV; n_band++ ) + { + energy_fx = L_add( energy_fx, SWB_tenv_fx[n_band] ); /*Q3 */ + } + + IF( pos == sub( SWB_TENV, 1 ) ) + { + energy_fx = L_deposit_l( 0 ); + } + ELSE + { + tmp = sub( SWB_TENV, pos + 1 ); + tmp = div_s( 1, tmp ); /*Q15 */ + energy_fx = Mult_32_16( energy_fx, tmp ); /*Q3 */ + } + + FOR( n_band = 0; n_band < pos; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 16384 ); + move16(); + } + + /*SWB_tenv_fx[pos] = add(SWB_tenv_fx[pos], mult_r(SWB_tenv_fx[pos], 164)); move16();//Q3 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[pos] = round_fx_sat( L_mac_sat( L_mult_sat( SWB_tenv_fx[pos], 32767 ), SWB_tenv_fx[pos], 164 ) ); /*Q3 */ +#else + SWB_tenv_fx[pos] = round_fx( L_mac( L_mult( SWB_tenv_fx[pos], 32767 ), SWB_tenv_fx[pos], 164 ) ); /*Q3 */ +#endif + + IF( LT_32( energy_fx, SWB_tenv_fx[pos] ) ) + { + FOR( n_band = pos + 1; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 29491 ); + move16(); /*Q3 */ + } + } } ELSE { - max_band = SWB_FENV; - move16(); - band_step = 1; - move16(); + FOR( n_band = 1; n_band < SWB_TENV; n_band++ ) + { + IF( GT_16( SWB_tenv_fx[n_band - 1], SWB_tenv_fx[n_band] ) ) + { + /*SWB_tenv_fx[n_band-1] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[n_band - 1] = round_fx_sat( L_mac_sat( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#else + SWB_tenv_fx[n_band - 1] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#endif + } + ELSE + { + /*SWB_tenv_fx[n_band] = add(mult_r(SWB_tenv_fx[n_band-1], 16384), mult_r(SWB_tenv_fx[n_band], 16384)); move16();//Q3 */ +#ifdef BASOP_NOGLOB + SWB_tenv_fx[n_band] = round_fx_sat( L_mac_sat( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#else + SWB_tenv_fx[n_band] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ +#endif + } + } + + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 29491 ); + move16(); /*Q3 */ + } } - } - ELSE /* HQ core */ - { - gamma_fx = 18022; - move16(); /*.55 in Q15 */ - get_normalize_spec_fx( core, st_fx->extl, mode, -1, org_fx, SWB_signal_fx, &( hBWE_FD->prev_L_swb_norm1 ), offset, Q_new_lf ); - band_step = 1; - move16(); - IF( EQ_16( offset, HQ_GENERIC_FOFFSET_32K ) ) + test(); + test(); + IF( IsTransient_LF == 0 && EQ_16( coder_type, INACTIVE ) && EQ_16( st_fx->TransientHangOver, 1 ) ) { - max_band = 12; - move16(); + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) + { + SWB_tenv_fx[n_band] = mult_r( SWB_tenv_fx[n_band], 16384 ); + move16(); + } + FOR( n_band = 0; n_band < SWB_FENV_TRANS; n_band++ ) + { + SWB_fenv_fx[n_band] = mult_r( SWB_fenv_fx[n_band], 1638 ); + move16(); + } } ELSE { - max_band = SWB_FENV; + SWB_fenv_fx[2] = mult_r( SWB_fenv_fx[2], 3277 ); + move16(); + SWB_fenv_fx[3] = mult_r( SWB_fenv_fx[3], 1638 ); move16(); } - } - - FOR( n_band = 0; n_band < max_band; ) - { - calculate_Tonality_fx( org_fx + swb_bwe_subband[n_band] + offset, SWB_signal_fx + swb_bwe_subband[n_band] + offset, - &SFM_org_fx[n_band], &SFM_gen_fx[n_band], swb_bwe_subband[n_band + band_step] - swb_bwe_subband[n_band] ); - IF( LT_16( SFM_gen_fx[n_band], mult_r( 24576, SFM_org_fx[n_band] ) ) ) + FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) { - energy_factor_fx[n_band] = div_s( SFM_gen_fx[n_band], SFM_org_fx[n_band] ); /*Q15 */ - IF( LT_16( energy_factor_fx[n_band], gamma_fx ) ) + IF( SWB_tenv_fx[n_band] == 0 ) { - energy_factor_fx[n_band] = gamma_fx; + SWB_tenv_tmp_fx[n_band] = -32768; + move16(); /*-16 in Q11 */ + } + ELSE + { + L_tmp = L_deposit_h( SWB_tenv_fx[n_band] ); /*Q19 */ + expn = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, expn ) ); + expn = sub( sub( 30, expn ), 19 ); + L_tmp = Mpy_32_16( expn, tmp, 32767 ); /* Q16 */ /*1 in Q15 */ + SWB_tenv_tmp_fx[n_band] = round_fx( L_shl( L_tmp, 11 ) ); /* Q11 */ + } + + IF( GT_16( SWB_tenv_tmp_fx[n_band], 30720 ) ) + { + index = 15; move16(); } + ELSE IF( SWB_tenv_tmp_fx[n_band] < 0 ) + { + index = 0; + move16(); + } + ELSE + { + index = shr( add( SWB_tenv_tmp_fx[n_band], 1024 ), 11 ); + } + + push_indice_fx( hBstr, IND_SWB_TENV, index, 4 ); } - ELSE - { - energy_factor_fx[n_band] = 32767; - move16(); /* Q15 */ - } - n_band = add( n_band, band_step ); - } - return; -} -/*-------------------------------------------------------------------* - * WB_BWE_encoding() - * - * WB BWE main encoder - *-------------------------------------------------------------------*/ -Word16 WB_BWE_encoding_fx( /* o : classification of wb signal */ - const Word16 coder_type, /* i : coder type */ - const Word16 *yos_fx, /* i : MDCT coefficients of weighted original */ - Word16 *WB_fenv_fx, /* i/o: energy of WB envelope */ - Encoder_State *st_fx, /* i/o: Encoder structure */ - Word16 Q_synth, - Word16 Q_synth_lf ) -{ - Word16 mode; - Word16 i, n_coeff, n_band; - Word16 index; - Word32 energy_fx; - Word32 L_WB_fenv_fx[2]; - Word16 energy_factor_fx[4]; - Word16 ener_40, exp; - Word32 L_tmp; - Word16 tmp; + MSVQ_Interpol_Tran_fx( SWB_fenv_fx, indice ); - n_band = 0; - move16(); - FOR( i = 0; i < 2; i++ ) + push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 6 ); + } + ELSE { - energy_fx = L_deposit_l( 0 ); - FOR( n_coeff = swb_bwe_subband[n_band]; n_coeff < swb_bwe_subband[n_band + 2]; n_coeff++ ) + /* Energy for the different bands and global energies */ + global_gain_fx = L_deposit_l( 0 ); + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { - energy_fx = L_add( energy_fx, L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 6 ) ); /*2*Q_synth-6 */ - } + energy_fx = L_deposit_l( 0 ); + FOR( n_coeff = swb_bwe_subband[n_band] + st_offset; n_coeff < swb_bwe_subband[n_band + 1] + st_offset; n_coeff++ ) + { + L_tmp = L_shr( L_mult0( yos_fx[n_coeff], yos_fx[n_coeff] ), 5 ); /*2*Q_synth-5 */ + energy_fx = L_add( L_tmp, energy_fx ); /*2*Q_synth-5 */ + } - L_WB_fenv_fx[i] = energy_fx; - move32(); /*2*Q_synth-6 */ - n_band = add( n_band, 2 ); - } - mode = FD_BWE_class_fx( yos_fx, 0, 0, Q_synth, 0, st_fx ); + IF( LT_16( n_band, sub( SWB_FENV, 2 ) ) ) + { + global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( 2 * Q_synth - 5, 2 * Q_shb ) ) ); /*2*Q_shb */ + } + L_SWB_fenv_fx[n_band] = energy_fx; + move32(); + } + global_gain_fx = L_shr( global_gain_fx, 1 ); /*2*Q_shb */ + mode = FD_BWE_class_fx( yos_fx, global_gain_fx, tilt_nb_fx, Q_synth, Q_shb, st_fx ); + push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); - energy_control_fx( st_fx, ACELP_CORE, mode, coder_type, yos_fx, 0, energy_factor_fx, Q_synth_lf ); + energy_control_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); - FOR( i = 0; i < 2; i++ ) - { - ener_40 = mult_r( shr( energy_factor_fx[shl( i, 1 )], 1 ), 26214 ); /*Q19 */ - L_tmp = Mult_32_16( L_WB_fenv_fx[i], ener_40 ); /*2*Q_synth-2 */ - IF( L_tmp ) + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { - exp = norm_l( L_tmp ); - tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); - /*exp = 30-exp-(2*Q_synth-2); */ - exp = sub( sub( 30, exp ), ( sub( shl( Q_synth, 1 ), 2 ) ) ); - L_tmp = Mpy_32_16( exp, tmp, 32767 ); /* Q16 */ - WB_fenv_fx[i] = round_fx( L_shl( L_tmp, 10 ) ); /*Q10 */ + L_tmp = Mult_32_16( L_SWB_fenv_fx[n_band], energy_factor_fx[n_band] ); /*2*Q_synth-5 */ + L_tmp = Mult_32_16( L_tmp, swb_inv_bwe_subband_width_fx[n_band] ); /*2*Q_synth-5 */ + + IF( L_tmp != 0 ) + { + expn = norm_l( L_tmp ); + tmp = Log2_norm_lc( L_shl( L_tmp, expn ) ); + expn = sub( 30, add( expn, sub( shl( Q_synth, 1 ), 5 ) ) ); + L_tmp = Mpy_32_16( expn, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ + SWB_fenv_fx[n_band] = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + } + ELSE + { + SWB_fenv_fx[n_band] = -24576; + move16(); + } } - ELSE + freq_weights_fx( SWB_fenv_fx, w_NOR_fx, w_env_fx, SWB_FENV ); + + FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { - WB_fenv_fx[i] = 0; + SWB_fenv_fx[n_band] = sub( SWB_fenv_fx[n_band], Mean_env_fx[n_band] ); move16(); } - } - index = WB_BWE_fenv_q_fx( WB_fenv_fx, F_2_5_fx, 32, 2 ); + /* Energy VQ */ + msvq_interpol_fx( SWB_fenv_fx, w_env_fx, indice ); - push_indice_fx( st_fx->hBstr, IND_WB_FENV, index, 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 7 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[2], 6 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[3], 5 ); + push_indice_fx( hBstr, IND_SWB_FENV, indice[4], 6 ); + } + hBWE_FD->prev_mode = mode; + move16(); + hBWE_FD->prev_global_gain_fx = global_gain_fx; + move32(); + st_fx->prev_Q_shb = Q_shb; + move16(); - return ( mode ); + return mode; } /*-------------------------------------------------------------------* @@ -1910,7 +2964,7 @@ Word16 WB_BWE_encoding_fx( /* o : classification of wb * * SWB BWE encoder *-------------------------------------------------------------------*/ -static Word16 SWB_BWE_encoding_fx( +static Word16 SWB_BWE_encoding_ivas_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ Word16 *insig_fx, /* i : delayed original input signal at 32kHz */ const Word16 *insig_lp_fx, /* i : delayed original lowband input signal at 32kHz */ @@ -1920,7 +2974,6 @@ static Word16 SWB_BWE_encoding_fx( Word16 *SWB_fenv_fx, /* o : frequency-domain quantized BWE envelope */ const Word16 tilt_nb_fx, /* i : SWB tilt */ const Word16 st_offset, /* i : start frequency offset for BWE envelope */ - const Word16 coder_type, /* i : coding type */ Word16 Q_insig_lp, Word16 Q_shb, Word16 Q_synth, @@ -1949,6 +3002,7 @@ static Word16 SWB_BWE_encoding_fx( Word16 energy_factor_fx[SWB_FENV], w_env_fx[SWB_FENV]; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; @@ -1968,6 +3022,7 @@ static Word16 SWB_BWE_encoding_fx( /* HF transient detect */ IsTransient = detect_transient_fx( insig_hp_fx, L_FRAME16k, Q_shb, st_fx ); st_fx->EnergyLT_fx_exp = shl( Q_shb, 1 ); + move16(); /* LF transient detect */ IsTransient_LF = 0; @@ -2011,7 +3066,7 @@ static Word16 SWB_BWE_encoding_fx( { mode = IsTransient; move16(); - push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + push_indice( hBstr, IND_SWB_CLASS, mode, 2 ); /* Energy for the different bands and global energies */ global_gain_fx = L_deposit_l( 0 ); @@ -2036,7 +3091,6 @@ static Word16 SWB_BWE_encoding_fx( L_tmp = Mult_32_16( L_SWB_fenv_fx[n_band], tmp ); /*2*Q_synth-7+29-expd - 15 */ exp = norm_l( L_tmp ); tmp = Log2_norm_lc( L_shl( L_tmp, exp ) ); - move16(); exp = sub( sub( 30, exp ), sub( add( shl( Q_synth, 1 ), 7 ), expd ) ); L_tmp = Mpy_32_16( exp, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ tmp = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ @@ -2074,7 +3128,7 @@ static Word16 SWB_BWE_encoding_fx( { exp = norm_l( L_tmp ); tmp = extract_h( L_shl( L_tmp, exp ) ); - exp = sub( exp, sub( 30, 2 * Q_shb ) ); + exp = sub( exp, sub( 30, shl( Q_shb, 1 ) ) ); tmp = div_s( 16384, tmp ); L_tmp = L_deposit_h( tmp ); @@ -2085,6 +3139,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[n_band] = round_fx( L_shl( L_tmp, sub( exp, 12 ) ) ); /*Q3 */ #endif + move16(); } } @@ -2167,7 +3222,7 @@ static Word16 SWB_BWE_encoding_fx( } } - IF( n_band < SWB_TENV ) + IF( LT_16( n_band, SWB_TENV ) ) { energy_fx = L_deposit_l( 0 ); FOR( n_band = ( pos + 1 ); n_band < SWB_TENV; n_band++ ) @@ -2175,13 +3230,13 @@ static Word16 SWB_BWE_encoding_fx( energy_fx = L_add( energy_fx, SWB_tenv_fx[n_band] ); /*Q3 */ } - IF( pos == sub( SWB_TENV, 1 ) ) + IF( EQ_16( pos, sub( SWB_TENV, 1 ) ) ) { energy_fx = L_deposit_l( 0 ); } ELSE { - tmp = sub( SWB_TENV, pos + 1 ); + tmp = sub( SWB_TENV, add( pos, 1 ) ); tmp = div_s( 1, tmp ); /*Q15 */ energy_fx = Mult_32_16( energy_fx, tmp ); /*Q3 */ } @@ -2198,6 +3253,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[pos] = round_fx( L_mac( L_mult( SWB_tenv_fx[pos], 32767 ), SWB_tenv_fx[pos], 164 ) ); /*Q3 */ #endif + move16(); IF( LT_32( energy_fx, SWB_tenv_fx[pos] ) ) { @@ -2220,6 +3276,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[n_band - 1] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ #endif + move16(); } ELSE { @@ -2229,6 +3286,7 @@ static Word16 SWB_BWE_encoding_fx( #else SWB_tenv_fx[n_band] = round_fx( L_mac( L_mult( SWB_tenv_fx[n_band - 1], 16384 ), SWB_tenv_fx[n_band], 16384 ) ); /*Q3 */ #endif + move16(); } } @@ -2241,7 +3299,7 @@ static Word16 SWB_BWE_encoding_fx( test(); test(); - IF( IsTransient_LF == 0 && EQ_16( coder_type, INACTIVE ) && EQ_16( st_fx->TransientHangOver, 1 ) ) + IF( IsTransient_LF == 0 && st_fx->coder_type == INACTIVE && EQ_16( st_fx->TransientHangOver, 1 ) ) { FOR( n_band = 0; n_band < SWB_TENV; n_band++ ) { @@ -2277,6 +3335,7 @@ static Word16 SWB_BWE_encoding_fx( expn = sub( sub( 30, expn ), 19 ); L_tmp = Mpy_32_16( expn, tmp, 32767 ); /* Q16 */ /*1 in Q15 */ SWB_tenv_tmp_fx[n_band] = round_fx( L_shl( L_tmp, 11 ) ); /* Q11 */ + move16(); } IF( GT_16( SWB_tenv_tmp_fx[n_band], 30720 ) ) @@ -2294,13 +3353,13 @@ static Word16 SWB_BWE_encoding_fx( index = shr( add( SWB_tenv_tmp_fx[n_band], 1024 ), 11 ); } - push_indice_fx( hBstr, IND_SWB_TENV, index, 4 ); + push_indice( hBstr, IND_SWB_TENV, index, 4 ); } MSVQ_Interpol_Tran_fx( SWB_fenv_fx, indice ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 7 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 6 ); + push_indice( hBstr, IND_SWB_FENV, indice[0], 7 ); + push_indice( hBstr, IND_SWB_FENV, indice[1], 6 ); } ELSE { @@ -2315,9 +3374,9 @@ static Word16 SWB_BWE_encoding_fx( energy_fx = L_add( L_tmp, energy_fx ); /*2*Q_synth-5 */ } - IF( LT_16( n_band, sub( SWB_FENV, 2 ) ) ) + IF( LT_16( n_band, SWB_FENV - 2 ) ) { - global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( 2 * Q_synth - 5, 2 * Q_shb ) ) ); /*2*Q_shb */ + global_gain_fx = L_add( global_gain_fx, L_shr( energy_fx, sub( sub( shl( Q_synth, 1 ), 5 ), shl( Q_shb, 1 ) ) ) ); /*2*Q_shb */ } L_SWB_fenv_fx[n_band] = energy_fx; move32(); @@ -2325,9 +3384,9 @@ static Word16 SWB_BWE_encoding_fx( global_gain_fx = L_shr( global_gain_fx, 1 ); /*2*Q_shb */ mode = FD_BWE_class_fx( yos_fx, global_gain_fx, tilt_nb_fx, Q_synth, Q_shb, st_fx ); - push_indice_fx( hBstr, IND_SWB_CLASS, mode, 2 ); + push_indice( hBstr, IND_SWB_CLASS, mode, 2 ); - energy_control_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); + energy_control_ivas_fx( st_fx, ACELP_CORE, mode, -1, yos_fx, st_offset, energy_factor_fx, Q_synth_lf ); FOR( n_band = 0; n_band < SWB_FENV; n_band++ ) { @@ -2341,6 +3400,7 @@ static Word16 SWB_BWE_encoding_fx( expn = sub( 30, add( expn, sub( shl( Q_synth, 1 ), 5 ) ) ); L_tmp = Mpy_32_16( expn, tmp, 24660 ); /* Q14 */ /*10log10(2) in Q13 */ SWB_fenv_fx[n_band] = round_fx( L_shl( L_tmp, 10 ) ); /* Q8 */ + move16(); } ELSE { @@ -2359,11 +3419,11 @@ static Word16 SWB_BWE_encoding_fx( /* Energy VQ */ msvq_interpol_fx( SWB_fenv_fx, w_env_fx, indice ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[0], 5 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[1], 7 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[2], 6 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[3], 5 ); - push_indice_fx( hBstr, IND_SWB_FENV, indice[4], 6 ); + push_indice( hBstr, IND_SWB_FENV, indice[0], 5 ); + push_indice( hBstr, IND_SWB_FENV, indice[1], 7 ); + push_indice( hBstr, IND_SWB_FENV, indice[2], 6 ); + push_indice( hBstr, IND_SWB_FENV, indice[3], 5 ); + push_indice( hBstr, IND_SWB_FENV, indice[4], 6 ); } hBWE_FD->prev_mode = mode; move16(); @@ -2374,7 +3434,6 @@ static Word16 SWB_BWE_encoding_fx( return mode; } - /*-------------------------------------------------------------------* * get_normalize_spec_fx_32() * diff --git a/lib_enc/swb_pre_proc_fx.c b/lib_enc/swb_pre_proc_fx.c index dbd41484e6713567f3b4b55e0652eb40a0b88da8..9a60072c3c4d412e58421a3d4cf616c2fd815854 100644 --- a/lib_enc/swb_pre_proc_fx.c +++ b/lib_enc/swb_pre_proc_fx.c @@ -164,6 +164,299 @@ void wb_pre_proc_fx( } +/*========================================================================*/ +/* FUNCTION : wb_pre_proc_ivas_fx() */ +/*------------------------------------------------------------------------*/ +/* PURPOSE : Resampling of input signal when input signal sample rate */ +/* is above 16kHz */ +/*------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Encoder_State *st_fx : Encoder State Structure */ +/* _ (Word16*) input : original input signal */ +/*------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _None */ +/*------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ (Word16*) new_wb_speech : original input signal at 16kHz Q-1 */ +/*------------------------------------------------------------------------*/ + +/* st_fx->old_wtda_wb_fx */ +/*------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*========================================================================*/ + +void wb_pre_proc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 last_element_mode, /* i : last element mode */ + const Word16 *new_inp_resamp16k, /* i : original input signal in Q-1 */ + Word16 *hb_speech /* o : HB target signal (6-8kHz) at 16kHz in Q-1 */ +) +{ + Word16 Sample_Delay_WB_BWE; + Word16 ramp_flag; + Word16 decim_state1_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )], decim_state2_fx[( 2 * ALLPASSSECTIONS_STEEP + 1 )]; + Word16 old_input[NS2SA( 16000, DELAY_FD_BWE_ENC_NS + DELAY_FIR_RESAMPL_NS ) + STEREO_DFT_OVL_16k + L_FRAME16k]; + Word16 *highband_new_speech; + Word16 highband_old_speech[( L_LOOK_12k8 + L_SUBFR + L_FRAME ) * 5 / 16]; + Word16 temp_buf[320]; + Word16 Q_wb_sp, i, max_wb; + Word16 fSwitchFromIO = 0; + Word16 ppp_mode; + Word32 temp1 = 0; + Word32 temp2 = 0; + move16(); + move32(); + move32(); + + + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + FD_BWE_ENC_HANDLE hBWE_FD = st_fx->hBWE_FD; + + IF( st_fx->Opt_SC_VBR ) + { + ppp_mode = st_fx->hSC_VBR->ppp_mode; + move16(); + } + ELSE + { + ppp_mode = 0; + move16(); + } + + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( EQ_32( st_fx->last_total_brate, ACELP_6k60 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_8k85 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_12k65 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_14k25 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_15k85 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_18k25 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_19k85 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_23k05 ) ) || + ( EQ_32( st_fx->last_total_brate, ACELP_23k85 ) ) ) + { + fSwitchFromIO = 1; + move16(); + } + + set16_fx( old_input, 0, NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS + DELAY_FIR_RESAMPL_NS ) + STEREO_DFT_OVL_16k + L_FRAME16k ); + + max_wb = 1; + move16(); + FOR( i = 0; i < L_FRAME16k; i++ ) + { + max_wb = s_max( max_wb, abs_s( new_inp_resamp16k[i] ) ); + } + Q_wb_sp = norm_s( max_wb ); + + Copy_Scale_sig( new_inp_resamp16k, temp_buf, L_FRAME16k, -3 ); + temp1 = L_mac0( temp1, temp_buf[0], temp_buf[0] ); + FOR( i = 1; i < L_FRAME16k; i++ ) + { + temp1 = L_mac0( temp1, temp_buf[i], temp_buf[i] ); + temp2 = L_mac0( temp2, temp_buf[i - 1], temp_buf[i] ); + } + + if ( LT_32( temp2, Mpy_32_16_1( temp1, 31129 /*0.95f*/ ) ) ) + { + Q_wb_sp = sub( Q_wb_sp, 3 ); /* leave 3 bit headroom */ + } + Copy_Scale_sig( new_inp_resamp16k, temp_buf, L_FRAME16k, Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), Q_wb_sp ); + /* temp_buf, and the memory states are in Q_wb_sp */ + + test(); + test(); + IF( EQ_16( st_fx->extl, WB_BWE ) || EQ_16( st_fx->extl, WB_TBE ) || st_fx->igf ) + { + ramp_flag = 0; + move16(); + + test(); + test(); + test(); + test(); + IF( ( NE_16( st_fx->last_extl, WB_TBE ) && NE_16( st_fx->last_extl, WB_BWE ) && !st_fx->igf ) || + ( st_fx->igf && fSwitchFromIO ) ) + { + ramp_flag = 1; + move16(); + } + + IF( !ppp_mode ) + { + /* temp_buf is in Q_wb_sp + hb_speech and the two decimator memories are in Q_wb_sp */ + IF( EQ_16( st_fx->element_mode, IVAS_CPE_DFT ) ) + { + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + move16(); + + IF( EQ_16( last_element_mode, IVAS_CPE_TD ) ) + { + set16_fx( hBWE_TD->decim_state1_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->decim_state2_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + ramp_flag = 1; + move16(); + } + + /*Get past signal*/ + Copy_Scale_sig( hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - STEREO_DFT_OVL_16k, old_input, STEREO_DFT_OVL_16k, Q_wb_sp ); + Copy_Scale_sig( hBWE_FD->old_input_wb_fx, old_input + STEREO_DFT_OVL_16k, Sample_Delay_WB_BWE, Q_wb_sp ); + + /*Get new signal*/ + Copy( temp_buf, &old_input[Sample_Delay_WB_BWE + STEREO_DFT_OVL_16k], L_FRAME16k ); + + /*compute hb_speech on delayed input*/ + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /*Update memory*/ + Copy_Scale_sig( hb_speech, hBWE_TD->old_speech_wb_fx + ( L_SUBFR * 5 / 16 ), STEREO_DFT_OVL_16k / 4, -Q_wb_sp ); + Copy( hb_speech + STEREO_DFT_OVL_16k / 4, hb_speech, ( L_FRAME16k - STEREO_DFT_OVL_16k ) / 4 ); + + /*rest without memory update*/ + Copy( hBWE_TD->decim_state1_fx, decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + Copy( hBWE_TD->decim_state2_fx, decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE + L_FRAME16k, hb_speech + ( L_FRAME16k - STEREO_DFT_OVL_16k ) / 4, STEREO_DFT_OVL_16k, decim_state1_fx, decim_state2_fx, 0 ); + } + ELSE IF( EQ_16( st_fx->element_mode, IVAS_CPE_TD ) ) + { + Word16 l_recalc_16k = L_MEM_RECALC_16K + L_FILT16k + 1; /* Note: "+1" is used because L_FILT16k is not divisible by 4 */ + Word16 l_recalc_4k = ( L_MEM_RECALC_16K + L_FILT16k + 1 ) / 4; + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + IF( EQ_16( last_element_mode, IVAS_CPE_DFT ) ) + { + set16_fx( hBWE_TD->decim_state1_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->decim_state2_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + ramp_flag = 1; + move16(); + } + + /*Get past signal*/ + Copy_Scale_sig( hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - l_recalc_16k, old_input, l_recalc_16k, Q_wb_sp ); + Copy_Scale_sig( hBWE_FD->old_input_wb_fx, old_input + l_recalc_16k, Sample_Delay_WB_BWE, Q_wb_sp ); + + /* Saturation added to prevent the crash. Needs further review */ + old_input[Sample_Delay_WB_BWE] = shl_sat( hBWE_FD->mem_old_wtda_swb_fx, Q_wb_sp ); + + /*Get new signal*/ + Copy( temp_buf, old_input + Sample_Delay_WB_BWE + l_recalc_16k, L_FRAME16k ); + + /*compute hb_speech on delayed input*/ + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /*Update memory*/ + Copy_Scale_sig( hb_speech, hBWE_TD->old_speech_wb_fx + ( ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ) - l_recalc_4k, l_recalc_4k, -Q_wb_sp ); + Copy( hb_speech + l_recalc_4k, hb_speech, ( L_FRAME16k / 4 ) - l_recalc_4k ); + + /*rest without memory update*/ + Copy( hBWE_TD->decim_state1_fx, decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + Copy( hBWE_TD->decim_state2_fx, decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE + L_FRAME16k, hb_speech + ( L_FRAME16k / 4 ) - l_recalc_4k, l_recalc_16k, decim_state1_fx, decim_state2_fx, 0 ); + } + ELSE IF( EQ_16( st_fx->element_mode, IVAS_SCE ) ) + { + IF( EQ_32( st_fx->input_Fs, 16000 ) ) + { + flip_spectrum_and_decimby4_fx( new_inp_resamp16k, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + } + ELSE + { + Word16 l_recalc_16k = L_FILT16k + 1; /* Note: "+1" is used because L_FILT16k is not divisible by 4 */ + Word16 l_recalc_4k = ( L_FILT16k + 1 ) / 4; + + Sample_Delay_WB_BWE = NS2SA( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + /*Get past signal*/ + Copy_Scale_sig( hBWE_FD->L_old_wtda_swb_fx + L_FRAME16k - l_recalc_16k, old_input, l_recalc_16k, Q_wb_sp ); + Copy_Scale_sig( hBWE_FD->old_input_wb_fx, old_input + l_recalc_16k, Sample_Delay_WB_BWE, Q_wb_sp ); + + /*Get new signal*/ + Copy( temp_buf, old_input + Sample_Delay_WB_BWE + l_recalc_16k, L_FRAME16k ); + + /*compute hb_speech on delayed input*/ + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + + /* update hBWE_TD->old_speech_wb memory */ + Copy_Scale_sig( hb_speech, hBWE_TD->old_speech_wb_fx + ( ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ) - l_recalc_4k, l_recalc_4k, -Q_wb_sp ); + Copy( hb_speech + l_recalc_4k, hb_speech, ( L_FRAME16k / 4 ) - l_recalc_4k ); + + /*rest without memory update*/ + Copy( hBWE_TD->decim_state1_fx, decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + Copy( hBWE_TD->decim_state2_fx, decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + + flip_spectrum_and_decimby4_fx( old_input + Sample_Delay_WB_BWE + L_FRAME16k, hb_speech + ( L_FRAME16k / 4 ) - l_recalc_4k, l_recalc_16k, decim_state1_fx, decim_state2_fx, 0 ); + } + } + ELSE + { + flip_spectrum_and_decimby4_fx( temp_buf, hb_speech, L_FRAME16k, hBWE_TD->decim_state1_fx, hBWE_TD->decim_state2_fx, ramp_flag ); + } + + /* rescale the hb_speech and memories back to Q-1 to keep the downstream BWE coding unaffected */ + Scale_sig( hb_speech, L_FRAME16k / 4, -Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state1_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), -Q_wb_sp ); + Scale_sig( hBWE_TD->decim_state2_fx, ( 2 * ALLPASSSECTIONS_STEEP + 1 ), -Q_wb_sp ); + + IF( NE_16( st_fx->extl, WB_TBE ) ) + { + /* Update the previous wideband speech buffer in case of a WB_BWE frame */ + Sample_Delay_WB_BWE = ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16; + + highband_new_speech = highband_old_speech + Sample_Delay_WB_BWE; + Copy( hb_speech, highband_new_speech, L_FRAME16k / 4 ); + Copy( highband_old_speech + L_FRAME16k / 4, hBWE_TD->old_speech_wb_fx, Sample_Delay_WB_BWE ); + } + } + } + ELSE + { + set16_fx( hBWE_TD->decim_state1_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->decim_state2_fx, 0, ( 2 * ALLPASSSECTIONS_STEEP + 1 ) ); + set16_fx( hBWE_TD->old_speech_wb_fx, 0, ( L_LOOK_12k8 + L_SUBFR ) * 5 / 16 ); + } + + if ( hBWE_FD != NULL ) + { + hBWE_FD->mem_old_wtda_swb_fx = new_inp_resamp16k[L_FRAME16k - L_MEM_RECALC_16K - L_FILT16k - 1]; + move16(); + } + + /* st->old_input_wb and st->old_wtda_wb must be updated each frame, or there are often some clicks during WB TBE <-> WB BWE switching */ + test(); + test(); + test(); + IF( ( NE_16( st_fx->extl, WB_BWE ) || ( EQ_16( st_fx->extl, WB_BWE ) && EQ_32( st_fx->total_brate, 0 ) ) ) && !ppp_mode ) + { + Sample_Delay_WB_BWE = NS2SA_FX2( 16000, DELAY_FD_BWE_ENC_12k8_NS ); + + Copy( new_inp_resamp16k, &old_input[Sample_Delay_WB_BWE], L_FRAME16k ); + Copy( hBWE_FD->old_input_wb_fx, old_input, Sample_Delay_WB_BWE ); + Copy( new_inp_resamp16k + L_FRAME16k - Sample_Delay_WB_BWE, hBWE_FD->old_input_wb_fx, Sample_Delay_WB_BWE ); + test(); + IF( NE_16( st_fx->extl, SWB_BWE ) && NE_16( st_fx->extl, FB_BWE ) ) + { + Copy( old_input, hBWE_FD->L_old_wtda_swb_fx, L_FRAME16k ); + st_fx->Q_old_wtda = -1; + move16(); + } + } + return; +} + + /*========================================================================*/ /* FUNCTION : swb_pre_proc_fx() */ /*------------------------------------------------------------------------*/ diff --git a/lib_enc/swb_tbe_enc_fx.c b/lib_enc/swb_tbe_enc_fx.c index 5eb1d275a4b05b4d40890ae75a8ad1c104d1cf3a..de765d5a01b6569e292998fba1c5607273af7263 100644 --- a/lib_enc/swb_tbe_enc_fx.c +++ b/lib_enc/swb_tbe_enc_fx.c @@ -9,6 +9,7 @@ //#include "prot_fx.h" #include "rom_com_fx.h" #include "rom_com.h" +#include "prot.h" /* Function prototypes */ #include "prot_fx.h" /* Function prototypes */ #include "prot_fx_enc.h" /* Function prototypes */ #include "stl.h" @@ -30,9 +31,12 @@ static void determine_gain_weights_fx( const Word32 *gain, Word16 *weights, cons static void QuantizeSHBsubgains_fx( Encoder_State *st_fx, Word16 *subgains, const Word16 extl ); +static void QuantizeSHBsubgains_ivas_fx( Encoder_State *st_fx, Word16 subgains[], const Word16 extl ); static void QuantizeSHBframegain_fx( Encoder_State *st_fx, Word32 *GainFrame, const Word16 extl, Word32 extl_brate, Word16 *rf_gainFrame_ind ); +static void QuantizeSHBframegain_ivas_fx( Encoder_State *st_fx, Word32 *GainFrame, const Word16 extl, Word32 extl_brate, Word16 *rf_gainFrame_ind, const Word16 flag_conservative ); + static Word16 closest_centroid_fx( const Word16 *data, const Word16 *weights, const Word16 *quantizer, const Word16 centroids, const Word16 length ); static Word16 closest_centroid_lc_fx( const Word16 *data, const Word16 *quantizer, const Word16 centroids ); @@ -61,6 +65,8 @@ static void EstimateSHBGainShape_fx( const Word16 length, static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ); +static Word32 pow_off_pk_corrected_fx( Word16 a[], Word16 len, Word16 step ); + static void find_max_mem_enc( Encoder_State *st_fx, Word16 *n_mem, Word16 *n_mem2 ); static void rescale_genSHB_mem_enc( Encoder_State *st_fx, Word16 sf ); static void find_max_mem_wb_enc( Encoder_State *st_fx, Word16 *n_mem ); @@ -238,57 +244,59 @@ void find_max_mem_wb_enc( Encoder_State *st_fx, Word16 *n_mem ) { Word16 i; Word16 n_mem_32; - Word16 max = 0; + Word16 max_16 = 0; Word32 Lmax = 0; TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + move16(); + move32(); FOR( i = 0; i < NL_BUFF_OFFSET; i++ ) - max = s_max( max, abs_s( hBWE_TD->old_bwe_exc_extended_fx[i] ) ); + max_16 = s_max( max_16, abs_s( hBWE_TD->old_bwe_exc_extended_fx[i] ) ); FOR( i = 0; i < 7; i++ ) { - IF( abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ) > max ) - max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_shb_fx[i] ); } FOR( i = 0; i < 7; i++ ) { - IF( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ) > max ) - max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb2_fx[i] ); } FOR( i = 0; i < 7; i++ ) { - IF( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ) > max ) - max = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->mem_genSHBexc_filt_down_wb3_fx[i] ); } FOR( i = 0; i < 10; i++ ) { - IF( abs_s( hBWE_TD->state_lpc_syn_fx[i] ) > max ) - max = abs_s( hBWE_TD->state_lpc_syn_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->state_lpc_syn_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->state_lpc_syn_fx[i] ); } FOR( i = 0; i < 5; i++ ) { - IF( abs_s( hBWE_TD->state_syn_shbexc_fx[i] ) > max ) - max = abs_s( hBWE_TD->state_syn_shbexc_fx[i] ); + IF( GT_16( abs_s( hBWE_TD->state_syn_shbexc_fx[i] ), max_16 ) ) + max_16 = abs_s( hBWE_TD->state_syn_shbexc_fx[i] ); } - IF( max == 0 ) + IF( max_16 == 0 ) { *n_mem = 15; move16(); } ELSE { - *n_mem = norm_s( max ); + *n_mem = norm_s( max_16 ); move16(); } FOR( i = 0; i < 2; i++ ) { - IF( L_abs( hBWE_TD->mem_csfilt_fx[i] ) > Lmax ) + IF( GT_32( L_abs( hBWE_TD->mem_csfilt_fx[i] ), Lmax ) ) Lmax = L_abs( hBWE_TD->mem_csfilt_fx[i] ); } @@ -306,6 +314,7 @@ void find_max_mem_wb_enc( Encoder_State *st_fx, Word16 *n_mem ) *n_mem = sub( s_min( *n_mem, n_mem_32 ), 1 ); move16(); *n_mem = s_max( *n_mem, 0 ); + move16(); } void rescale_genWB_mem_enc( Encoder_State *st_fx, Word16 sf ) @@ -1063,7 +1072,7 @@ void wb_tbe_enc_fx( tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */ #else /* BASOP_NOGLOB */ L_tmp = L_shl( L_tmp, add( exp, 10 ) ); - tmp = round_fx( L_tmp ); /* Q15 */ + tmp = round_fx( L_tmp ); /* Q15 */ #endif } @@ -1118,209 +1127,829 @@ void wb_tbe_enc_fx( } -void fb_tbe_reset_enc_fx( - Word32 elliptic_bpf_2_48k_mem_fx[][4], - Word32 *prev_fb_energy_fx, - Word16 elliptic_bpf_2_48k_mem_fx_Q[], - Word16 *prev_fb_energy_fx_Q ) -{ - set32_fx( elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); - set32_fx( elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); - set32_fx( elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); - set32_fx( elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); - *prev_fb_energy_fx = 0; - move16(); - set16_fx( elliptic_bpf_2_48k_mem_fx_Q, 0, 4 ); - *prev_fb_energy_fx_Q = 0; - move16(); - - return; -} -/*======================================================================================*/ -/* FUNCTION : void swb_tbe_enc_fx () */ -/*--------------------------------------------------------------------------------------*/ -/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ -/*--------------------------------------------------------------------------------------*/ +/*==========================================================================*/ +/* FUNCTION : void wb_tbe_enc_ivas_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : WB TBE encoder, 6 - 8 kHz band encoding module */ +/*--------------------------------------------------------------------------*/ /* INPUT ARGUMENTS : */ -/* _(Word16) coder_type : coding type */ -/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ -/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ -/* _(Word16[]) voice_factors :voicing factors Q15 */ -/* _(Word16*) Q_white_exc :Q Format of White Exc */ -/*--------------------------------------------------------------------------------------*/ +/* Word16 *new_speech i : original input signal Q(-1) */ +/* Word32 *bwe_exc_extended i : bandwidth extended exciatation Q(2*Q_new) */ +/* Word16 voice_factors[] i : voicing factors Q15 */ +/* Word16 pitch_buf[] i : pitch for each subframe Q6 */ +/*--------------------------------------------------------------------------*/ /* OUTPUT ARGUMENTS : */ -/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ -/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ -/*--------------------------------------------------------------------------------------*/ +/* Word16 *synth o : WB SHB final synthesis */ +/*--------------------------------------------------------------------------*/ /* INPUT/OUTPUT ARGUMENTS : */ -/* _ Encoder_State *st_fx: : Encoder state structure */ -/*--------------------------------------------------------------------------------------*/ +/* Encoder_State *st_fx i/o: encoder state structure */ +/*--------------------------------------------------------------------------*/ /* RETURN ARGUMENTS : */ /* _ None */ -/*--------------------------------------------------------------------------------------*/ -/* CALLED FROM : TX */ -/*======================================================================================*/ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ -void swb_tbe_enc_fx( - Encoder_State *st_fx, /* i/o: encoder state structure */ - const Word16 coder_type, /* i : coding type */ - Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb*/ - Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_new*/ - const Word16 voice_factors_fx[], /* i : voicing factors Q15*/ - Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc*/ - Word16 *Q_white_exc, - Word16 Q_new, - Word16 Q_shb, - Word16 *voicing, /* i : OL maximum normalized correlation */ - const Word16 pitch_buf[] /* i : subframe pitch Q6*/ +void wb_tbe_enc_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 *hb_speech, /* i : HB target signal (6-8kHz) at 16kHz Q(-1) */ + const Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation Q(2*Q_new) */ + const Word16 Q_new, /* i : input HB speech Q factor */ + const Word16 voice_factors[], /* i : voicing factors Q15 */ + const Word16 pitch_buf[] /* i : pitch for each subframe Q6 */ ) { - Word16 i, j; - - Word16 shb_old_speech_fx[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + Word16 i, j, k; + Word16 hb_old_speech[( L_LOOK_12k8 + L_SUBFR + L_FRAME ) * 5 / 16]; Word16 bwe_exc_extended_16[L_FRAME32k + NL_BUFF_OFFSET]; - Word16 shaped_shb_excitation_fx[L_FRAME16k + L_SHB_LAHEAD]; - Word32 GainFrame_fx; - Word16 GainShape_fx[NUM_SHB_SUBFR]; - Word16 lpc_shb_fx[LPC_SHB_ORDER + 1], lsp_shb_fx[LPC_SHB_ORDER], lsf_shb_fx[LPC_SHB_ORDER]; - Word16 weights_lsp[LPC_SHB_ORDER]; - Word16 Q_out; - Word16 *shb_frame_fx, *shb_new_speech_fx; - Word16 R_h[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech MSB */ - Word16 R_l[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech LSB */ + Word16 shaped_wb_excitation[( L_FRAME16k + L_SHB_LAHEAD ) / 4]; + Word16 exc4kWhtnd[L_FRAME16k / 4]; + /*Word16 ana_align_delay = WBTBE_ANA_ALIGNDELAY; */ /* -L_SHB_LAHEAD/4 - 5 */ + Word32 GainFrame; + Word16 GainShape[NUM_SHB_SUBFR]; + Word16 lpc_wb[LPC_SHB_ORDER_WB + 1]; + Word32 lpc_wb_32_fx[LPC_SHB_ORDER_WB + 1]; + Word16 lsp_wb[LPC_SHB_ORDER_WB], weights_lsp[LPC_SHB_ORDER_WB] = { 32767, 32767 }; + Word16 *hb_new_speech, *hb_frame /*, hb_speech[ L_FRAME16k ]*/; + Word16 R_h[LPC_SHB_ORDER_WB + 2], R_l[LPC_SHB_ORDER_WB + 2]; Word16 Q_R; - Word32 LepsP[LPC_SHB_ORDER + 1]; - - Word16 ana_align_delay[2] = { -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ), -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ) }; - Word32 prev_pow_fx, curr_pow_fx, Lscale; - Word32 p2m_in_fx, p2m_out_fx; + Word32 LepsP[LPC_SHB_ORDER_WB + 1]; + move16(); + move16(); - Word16 exp_out, exp, exp1, frac; - Word16 cnt, n_mem, n_mem2; - Word32 L_tmp, L_tmp1; - Word16 Q_bwe_exc; + Word32 prev_pow, curr_pow, Lscale; + /* Word16 scale; */ + /*Word16 ramp_flag;*/ + Word32 p2m_in, p2m_out; + /*Word16 cnt, max =0;*/ + Word16 n_mem, Q_bwe_exc, Q_bwe_exc_ext, exp_out; /* Q_hb_frame; */ + Word32 L_tmp, Lmax; + Word16 tmp, exp, Q_out, sc; + Word16 Q_ns = -1; + move16(); - Word16 frGainAttenuate, frGainSmoothEn; - Word16 MA_lsp_shb_spacing; - Word16 temp_swb_fac, feedback; - Word32 L_feedback; - Word16 tmp, tmp1, tmp2; - Word32 Lmax; - Word16 sc; - Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; - Word16 sd_uq_q_fx; + Word16 pitBufAvg_fx, voicingBufAvg_fx; Word16 vf_modified_fx[NB_SUBFR16k]; - Word16 pitBufAvg_fx; - Word16 voicingBufAvg_fx; - Word16 sum1, sum2; - Word16 recip, Q_recip; - const Word16 *ptr_lsp_interp_coef_fx; - - Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; - Word16 lpc_shb_sf_fx[4 * ( LPC_SHB_ORDER + 1 )]; - - /*Word32 shb_ener_sf_fx_32[4];*/ - Word32 shb_ener_sf_Q31; - Word16 shb_res_fx[L_FRAME16k]; - Word16 shb_res_gshape_fx[NB_SUBFR16k]; - Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; - Word16 vf_ind_fx; - - Word16 formant_fac_fx; - Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; - - Word16 mean_vf; - Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; - Word16 refl[M]; - Word16 tilt_para; - Word16 Q_bwe_exc_fb; - Word16 n_subfr_saturation; + Word16 temp_wb_fac_fx, feedback_fx; + Word16 lsp_spacing_fx; + Word16 lsp_wb_temp_fx[LPC_SHB_ORDER_WB], lpc_wb_temp_fx[LPC_SHB_ORDER_WB + 1]; + Word32 L_feedback; + Word16 frac, exp1; + Word16 uv_flag; + Word16 dummy = 0; + Word16 avg_voice_fac; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif - TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; - RF_ENC_HANDLE hRF = st_fx->hRF; - - /* init and buffers set up */ - exp1 = 0; /* to avoid compilation warnings */ - set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); - - /* compensate for the delay in target generation and subframe LA */ - shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay[0]; move16(); - /* set up the speech buffers for TBE processing*/ - shb_new_speech_fx = shb_old_speech_fx + ( L_LOOK_16k + L_SUBFR16k ); - move16(); - Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, ( L_LOOK_16k + L_SUBFR16k ) ); - Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); - Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, ( L_LOOK_16k + L_SUBFR16k ) ); + /*Word16 att = 32767;*/ - /* autocorrelation of SHB speech for 10-th order LP analysis */ - autocorr_fx( shb_old_speech_fx, - LPC_SHB_ORDER + 1, - R_h, /* autocorr (msb) Q15 */ - R_l, /* autocorr (lsb) */ - &Q_R, - NS2SA( INT_FS_16k, ACELP_LOOK_NS ) + L_SUBFR16k + L_FRAME16k, - win_lpc_shb_fx, - 0, - 1 ); + hb_new_speech = hb_old_speech + WBTBE_LOOK_LSUFBR_5_OVER_16; + hb_frame = hb_old_speech + WBTBE_LSUBFR_5_OVER_16 + WBTBE_ANA_ALIGNDELAY; + Copy( hBWE_TD->old_speech_wb_fx, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + Copy( hb_speech, hb_new_speech, LFRAME16K_OVER_4 ); + Copy( hb_old_speech + LFRAME16K_OVER_4, hBWE_TD->old_speech_wb_fx, WBTBE_LOOK_LSUFBR_5_OVER_16 ); - /* Spectral smoothing of autocorrelation coefficients */ test(); - IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + test(); + test(); + test(); + test(); + test(); + IF( ( NE_16( st_fx->last_extl, WB_TBE ) && NE_16( st_fx->last_extl, WB_BWE ) ) && ( EQ_16( st_fx->clas, UNVOICED_CLAS ) || ( LT_16( st_fx->voicing_fx[0], 16384 ) && LT_16( st_fx->voicing_fx[1], 16384 ) && LT_16( st_fx->voicing_fx[2], 16384 ) ) ) && !st_fx->igf ) { - FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + /* In case of unvoiced signals after switching cores, back-propagate the target signal */ + Copy( hb_speech, hb_old_speech, WBTBE_LOOK_LSUFBR_5_OVER_16 ); + + i = WBTBE_LOOK_LSUFBR_5_OVER_16; + move16(); + k = 0; + move16(); + + FOR( j = 0; j < L_SUBFR16k; j = j + 4 ) { - L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); - L_Extract( L_tmp, &R_h[i], &R_l[i] ); + L_tmp = L_mult( hb_old_speech[i], ola_win_shb_switch_fold_fx[j] ); + hb_old_speech[i] = mac_r( L_tmp, hb_speech[j], ola_win_shb_switch_fold_fx[L_SUBFR16k - 4 - j] ); + move16(); + i = sub( i, 1 ); + k = add( k, 1 ); } } - /* Set the autocorr[0] element to a non-negative value */ - R_l[0] = s_max( R_l[0], 1 ); - move16(); - - E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL ); /* LPC in Q14 */ - { - Word16 enerG, lpc_shb1[M + 1]; + autocorr_fx( hb_old_speech, LPC_SHB_ORDER_WB + 1, R_h, R_l, &Q_R, WBTBE_LPCWIN_LENGTH, win_lpc_hb_wb_fx, 0, 1 ); - /* extend the lpc_shb to a 16th order gain calc */ - set16_fx( lpc_shb1, 0, M + 1 ); - Copy( lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1 ); + E_LPC_lev_dur( R_h, R_l, lpc_wb_temp_fx, LepsP, LPC_SHB_ORDER_WB, NULL ); - /* estimate the LP gain */ - enerG = Enr_1_Az_fx( lpc_shb1, 2 * L_SUBFR ); /* Q3 */ + Copy_Scale_sig( lpc_wb_temp_fx, lpc_wb_temp_fx, LPC_SHB_ORDER_WB + 1, sub( norm_s( lpc_wb_temp_fx[0] ), 2 ) ); - /* if the LP gain is greater than a threshold, avoid saturation */ - IF( GT_16( enerG, 256 /*32 Q3*/ ) ) - { - set16_fx( lpc_shb_fx, 0, LPC_SHB_ORDER + 1 ); - E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, 2, NULL ); /* LPC in Q14 */ - } + /* convert into lsps and calculate weights */ + FOR( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb_temp_fx[i] ), 1 ) ); + move32(); } - /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ - Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb_temp_fx, st_fx->prev_lsp_wb_temp_fx, LPC_SHB_ORDER_WB ); - /* Expand bandwidth of the LP coeffs */ - test(); - IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) { - FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) - { - lpc_shb_fx[i] = mult_r( lpc_shb_fx[i], lpc_weights_fx[i] ); - } + st_fx->prev_lsp_wb_temp_fx[i] = lsp_wb_temp_fx[i]; + move16(); } - /* LPC to LSP conversion */ - /* LPC: Q12, LSP: Q15 */ - E_LPC_a_lsp_conversion( lpc_shb_fx, lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); - - /* LSP to LSF conversion */ + /* lsp_spacing_fx = 16384; move16(); */ + lsp_spacing_fx = lsp_wb_temp_fx[0]; + move16(); + FOR( i = 1; i < LPC_SHB_ORDER_WB; i++ ) + { + /*if ( i == 0 ) + { + tmp = lsp_wb_temp_fx[0]; move16(); + } + else + {*/ + tmp = sub( lsp_wb_temp_fx[i], lsp_wb_temp_fx[i - 1] ); + /*} */ + + lsp_spacing_fx = s_min( lsp_spacing_fx, tmp ); + } + + /* Spectral smoothing of autocorrelation coefficients */ + FOR( i = 1; i <= LPC_SHB_ORDER_WB; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_h[i - 1], wac_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + test(); + IF( EQ_16( st_fx->rf_mode, 1 ) || EQ_32( st_fx->extl_brate, WB_TBE_0k35 ) ) + { + E_LPC_lev_dur( R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_LBR_WB, NULL ); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_LBR_WB + 1, sub( norm_s( lpc_wb[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + FOR( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR( i = 0; i <= LPC_SHB_ORDER_LBR_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ), 1 ) ); + move32(); /*Q27 */ + } + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx, LPC_SHB_ORDER_LBR_WB ); + + FOR( i = 0; i < LPC_SHB_ORDER_LBR_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_LBR_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, lbr_wb_bwe_lsfvq_cbook_2bit_fx, 4, LPC_SHB_ORDER_LBR_WB ); + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->lsf_WB = i; + move16(); + } + ELSE + { + push_indice( st_fx->hBstr, IND_SHB_LSF, i, NUM_BITS_LBR_WB_LSF ); + } + + Copy( lbr_wb_bwe_lsfvq_cbook_2bit_fx + i * LPC_SHB_ORDER_LBR_WB, lsp_wb, LPC_SHB_ORDER_LBR_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_LBR_WB ); + + set16_fx( lpc_wb + LPC_SHB_ORDER_LBR_WB + 1, 0, ( LPC_SHB_ORDER_WB - LPC_SHB_ORDER_LBR_WB ) ); + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + + FOR( i = 1; i < LPC_SHB_ORDER_LBR_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + ELSE /* 13.2kbps */ + { + E_LPC_lev_dur( R_h, R_l, lpc_wb, LepsP, LPC_SHB_ORDER_WB, NULL ); + Copy_Scale_sig( lpc_wb, lpc_wb, LPC_SHB_ORDER_WB + 1, sub( norm_s( lpc_wb[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + FOR( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb[i] = mult_r( lpc_wb[i], lpc_weights_fx[i] ); + move16(); + } + + /* convert into lsps and calculate weights */ + FOR( i = 0; i <= LPC_SHB_ORDER_WB; i++ ) + { + lpc_wb_32_fx[i] = L_negate( L_shr( L_deposit_h( lpc_wb[i] ), 1 ) ); + move32(); /*Q27 */ + } + + lpc2lsp_fx( &lpc_wb_32_fx[1], lsp_wb, st_fx->prev_lsp_wb_fx, LPC_SHB_ORDER_WB ); + + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lsp_wb_fx[i] = lsp_wb[i]; + move16(); + } + + lsp_weights_fx( lsp_wb, weights_lsp, LPC_SHB_ORDER_WB, &Q_out ); + + /* Quantization of LSFs */ + i = closest_centroid_fx( lsp_wb, weights_lsp, wb_bwe_lsfvq_cbook_8bit_fx, 256, LPC_SHB_ORDER_WB ); /*move16(); */ + + push_indice( st_fx->hBstr, IND_SHB_LSF, i, NUM_BITS_WB_LSF ); + Copy( wb_bwe_lsfvq_cbook_8bit_fx + i * LPC_SHB_ORDER_WB, lsp_wb, LPC_SHB_ORDER_WB ); + + lsp2lpc_fx( &lpc_wb[1], lsp_wb, st_fx->prev_lpc_wb_fx, LPC_SHB_ORDER_WB ); + + FOR( i = 0; i < LPC_SHB_ORDER_WB; i++ ) + { + st_fx->prev_lpc_wb_fx[i] = lpc_wb[i + 1]; + move16(); + } + FOR( i = 1; i < LPC_SHB_ORDER_WB + 1; i++ ) + { + lpc_wb[i] = negate( lpc_wb[i] ); + move16(); + } + lpc_wb[0] = 4096; + move16(); + } + + uv_flag = 0; + move16(); + test(); + if ( EQ_32( st_fx->extl_brate, WB_TBE_1k05 ) && EQ_16( st_fx->coder_type_raw, UNVOICED ) ) + { + uv_flag = 1; + move16(); + } + + Copy( voice_factors, vf_modified_fx, NB_SUBFR16k ); + IF( EQ_16( st_fx->coder_type, VOICED ) ) + { + FOR( i = 1; i < NB_SUBFR; i++ ) + { + /*vf_modified[i] = 0.8f * voice_factors[i] + 0.2f * voice_factors[i-1];*/ + vf_modified_fx[i] = add( mult_r( 26214, voice_factors[i] ), mult_r( 6553, voice_factors[i - 1] ) ); + move16(); + } + IF( NE_16( st_fx->L_frame, L_FRAME ) ) + { + vf_modified_fx[4] = add( mult_r( 26214, voice_factors[4] ), mult_r( 6553, voice_factors[3] ) ); + move16(); + } + } + + /* From low band excitation, generate highband excitation */ + Lmax = L_deposit_l( 0 ); + FOR( i = 0; i < L_FRAME32k; i++ ) + { + Lmax = L_max( Lmax, L_abs( bwe_exc_extended[i] ) ); + } + + Q_bwe_exc = 31; + move16(); + if ( Lmax != 0 ) + { + Q_bwe_exc = norm_l( Lmax ); + } + Q_bwe_exc = sub( Q_bwe_exc, 3 ); + Q_bwe_exc = add( Q_bwe_exc, add( Q_new, Q_new ) ); + + find_max_mem_wb_enc( st_fx, &n_mem ); + + if ( GT_16( sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ), n_mem ) ) + { + Q_bwe_exc = add( st_fx->prev_Q_bwe_exc, n_mem ); + } + + IF( uv_flag ) + { + if ( GT_16( Q_bwe_exc, 20 ) ) + { + Q_bwe_exc = 20; + move16(); /* restrict this to 20 due to the Q factor requireemnt of the random number generator (keep 1 bit headroom) */ + } + } + + prev_pow = 0; + move32(); +#ifdef NONBE_FIX_1132_THRESHOLD_POW_IN_SWB_TBE + IF( st_fx->element_mode > EVS_MONO ) + { + tmp = sub( shl( sub( st_fx->prev_Q_bwe_exc, 16 ), 1 ), 31 + 16 ); +#ifdef BASOP_NOGLOB + prev_pow = L_shl_sat( 1407374848l /*0.00001f Q47*/, tmp ); /*Q(2*(st_fx->prev_Q_bwe_exc-16))*/ +#else + prev_pow = L_shl( 1407374848l /*0.00001f Q47*/, tmp ); /*Q(2*(st_fx->prev_Q_bwe_exc-16))*/ +#endif + } +#endif + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + prev_pow = L_mac0( prev_pow, hBWE_TD->state_syn_shbexc_fx[i], hBWE_TD->state_syn_shbexc_fx[i] ); /* Q(2*st_fx->prev_Q_bwe_exc) */ + } + + rescale_genWB_mem_enc( st_fx, sub( Q_bwe_exc, st_fx->prev_Q_bwe_exc ) ); + + Copy( hBWE_TD->old_bwe_exc_extended_fx, bwe_exc_extended_16, NL_BUFF_OFFSET ); + sc = sub( Q_bwe_exc, add( Q_new, Q_new ) ); + FOR( i = 0; i < L_FRAME32k; i++ ) + { + bwe_exc_extended_16[i + NL_BUFF_OFFSET] = round_fx( L_shl( bwe_exc_extended[i], sc ) ); + move16(); + } + Copy( bwe_exc_extended_16 + L_FRAME32k, hBWE_TD->old_bwe_exc_extended_fx, NL_BUFF_OFFSET ); + + Copy( hBWE_TD->state_syn_shbexc_fx, shaped_wb_excitation, L_SHB_LAHEAD / 4 ); + Q_bwe_exc_ext = sub( Q_bwe_exc, 16 ); + + GenShapedWBExcitation_fx( shaped_wb_excitation + L_SHB_LAHEAD / 4, lpc_wb, exc4kWhtnd, hBWE_TD->mem_csfilt_fx, + hBWE_TD->mem_genSHBexc_filt_down_shb_fx, hBWE_TD->mem_genSHBexc_filt_down_wb2_fx, hBWE_TD->mem_genSHBexc_filt_down_wb3_fx, + hBWE_TD->state_lpc_syn_fx, st_fx->coder_type, bwe_exc_extended_16, Q_bwe_exc_ext, hBWE_TD->bwe_seed, + vf_modified_fx, uv_flag, st_fx->igf ); + + curr_pow = 0; + move32(); +#ifdef NONBE_FIX_1132_THRESHOLD_POW_IN_SWB_TBE + IF( st_fx->element_mode > EVS_MONO ) + { + tmp = sub( shl( Q_bwe_exc_ext, 1 ), 31 + 16 ); +#ifdef BASOP_NOGLOB + curr_pow = L_shl_sat( 1407374848l /*0.00001f Q47*/, tmp ); /*Q(2*(Q_bwe_exc_ext))*/ +#else + curr_pow = L_shl( 1407374848l /*0.00001f Q47*/, tmp ); /* 2*(Q_bwe_exc_ext) */ +#endif + } +#endif + FOR( i = 0; i < L_SHB_LAHEAD / 4; i++ ) + { + curr_pow = L_mac0( curr_pow, shaped_wb_excitation[i + L_SHB_LAHEAD / 4], shaped_wb_excitation[i + L_SHB_LAHEAD / 4] ); /* Q(2*Q_bwe_exc_ext) */ + } + + IF( GT_16( voice_factors[0], 24576 ) ) + { + curr_pow = L_shr( curr_pow, 2 ); /* Q(2*Q_bwe_exc_ext) */ + } + + Lscale = root_a_over_b_fx( curr_pow, shl_r( Q_bwe_exc_ext, 1 ), prev_pow, shl_r( sub( st_fx->prev_Q_bwe_exc, 16 ), 1 ), &exp ); + + FOR( i = 0; i < L_SHB_LAHEAD / 4 - 1; i++ ) + { + L_tmp = Mpy_32_16_1( Lscale, shaped_wb_excitation[i] ); /* Q(16-exp+Q_bwe_exc_ext) */ +#ifdef BASOP_NOGLOB + shaped_wb_excitation[i] = round_fx_sat( L_shl_sat( L_tmp, exp ) ); /* Q_bwe_exc_ext */ +#else + shaped_wb_excitation[i] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ +#endif + move16(); + } + + Lscale = root_a_fx( Lscale, sub( 31, exp ), &exp ); + L_tmp = Mpy_32_16_1( Lscale, shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] ); /* Q(16-exp+Q_bwe_exc_ext) */ + shaped_wb_excitation[L_SHB_LAHEAD / 4 - 1] = round_fx( L_shl( L_tmp, exp ) ); /* Q_bwe_exc_ext */ + move16(); + + /* Update WB excitation */ + Copy( shaped_wb_excitation + L_FRAME16k / 4, hBWE_TD->state_syn_shbexc_fx, L_SHB_LAHEAD / 4 ); + + EstimateSHBGainShape_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, + shaped_wb_excitation, Q_bwe_exc_ext, GainShape, subwin_wb_fx, NULL ); + + /* Gain frame adjustment factor */ + test(); + IF( GainShape[0] && hBWE_TD->prev_wb_GainShape ) + { + exp = norm_s( hBWE_TD->prev_wb_GainShape ); + tmp = div_s( shl( 1, sub( 14, exp ) ), hBWE_TD->prev_wb_GainShape ); + L_tmp = L_mult( GainShape[0], tmp ); /* Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + L_feedback = L_mult0( temp_wb_fac_fx, temp_wb_fac_fx ); + FOR( i = 1; i < NUM_SHB_SUBFR / 4; i++ ) + { + /* temp_swb_fac = (float)log( (GainShape[i]+0.00001f) / (GainShape[i-1]+0.0001f) ); */ + test(); + IF( GainShape[i] && GainShape[i - 1] ) + { + exp = norm_s( GainShape[i - 1] ); + tmp = div_s( shl( 1, sub( 14, exp ) ), GainShape[i - 1] ); + L_tmp = L_mult( GainShape[i], tmp ); /*Q(30 - exp) */ + + exp1 = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp1 ) ); + exp1 = sub( exp, exp1 ); + L_tmp = Mpy_32_16( exp1, frac, 22713 ); + temp_wb_fac_fx = round_fx( L_shl( L_tmp, 10 ) ); + } + ELSE + { + temp_wb_fac_fx = 0; + move16(); + } + + L_feedback = L_mac( L_feedback, temp_wb_fac_fx, temp_wb_fac_fx ); + } + L_tmp = L_add( L_shr( L_feedback, 1 ), 1 << 21 ); /* Q30 */ + + IF( L_tmp != 0 ) + { + exp = norm_l( L_tmp ); + tmp = extract_h( L_shl( L_tmp, exp ) ); + exp = sub( sub( 30, exp ), 21 ); + tmp = div_s( 16384, tmp ); /* Q(15+exp) */ + L_tmp = L_shr( L_mult( 13107, tmp ), exp ); /* Q31 */ + feedback_fx = round_fx( L_tmp ); /* Q15 */ + } + ELSE + { + feedback_fx = 8738; + move16(); /* Q15 */ + } + + + temp_wb_fac_fx = hBWE_TD->prev_wb_GainShape; + move16(); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + GainShape[i] = add( mult_r( sub( 32767, feedback_fx ), GainShape[i] ), mult_r( feedback_fx, temp_wb_fac_fx ) ); + move16(); + temp_wb_fac_fx = GainShape[i]; + move16(); + } + + hBWE_TD->prev_wb_GainShape = GainShape[sub( shr( NUM_SHB_SUBFR, 2 ), 1 )]; + move16(); + + /* Compute the power of gains away from the peak gain prior to quantization */ + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_in = pow_off_pk_corrected_fx( GainShape, NUM_SHB_SUBFR / 4, 1 ); + } + ELSE + { + p2m_in = pow_off_pk_fx( GainShape, NUM_SHB_SUBFR / 4, 1 ); + } + + IF( EQ_32( st_fx->extl_brate, WB_TBE_0k35 ) ) + { + FOR( i = 0; i < 8; i++ ) + { + GainShape[i] = RECIP_ROOT_EIGHT_FX; + move16(); + } + } + ELSE + { + push_indice( st_fx->hBstr, IND_UV_FLAG, uv_flag, 1 ); + + /* Quantization of the subframe gain parameter */ + QuantizeSHBsubgains_ivas_fx( st_fx, GainShape, st_fx->extl ); + } + + /* Compute the power of gains away from the peak gain after quantization */ + IF( st_fx->element_mode > EVS_MONO ) + { + p2m_out = pow_off_pk_corrected_fx( GainShape, NUM_SHB_SUBFR / 2, 2 ); + } + ELSE + { + p2m_out = pow_off_pk_fx( GainShape, NUM_SHB_SUBFR / 2, 2 ); + } + + /* Estimate the gain parameter */ + EstimateSHBFrameGain_fx( SHB_OVERLAP_LEN / 2, hb_frame, Q_ns, shaped_wb_excitation, Q_bwe_exc_ext, GainShape, + &GainFrame, window_wb_fx, subwin_wb_fx, 0 ); + + + /* If there's a big difference in the power of gains away from the peak gain */ + /* due to poor quantization then suppress energy of the high band. */ + + IF( GT_32( p2m_out, L_shl( p2m_in, 1 ) ) ) + { + L_tmp = root_a_over_b_fx( L_shl( p2m_in, 1 ), 29, p2m_out, 29, &exp_out ); + GainFrame = L_shl( Mpy_32_32( GainFrame, L_tmp ), exp_out ); /* Q18 */ + } + + pitBufAvg_fx = 0; + move16(); + + FOR( i = 0; i < NB_SUBFR; i++ ) + { + pitBufAvg_fx = add( pitBufAvg_fx, mult_r( pitch_buf[i], 82 ) ); /*Q6 */ + } + voicingBufAvg_fx = 0; + move16(); + FOR( i = 0; i < 3; i++ ) + { + voicingBufAvg_fx = add( voicingBufAvg_fx, mult_r( st_fx->voicing_fx[i], 10912 ) ); /*Q15 */ + } + /* GainFrame *= max(min((float)(pitBufAvg/voicingBufAvg), 1.0f), 0.7f); */ + tmp = 32767; + move16(); + IF( voicingBufAvg_fx > 0 ) + { + exp = norm_s( voicingBufAvg_fx ); + tmp = div_s( shl( 1, sub( 14, exp ) ), voicingBufAvg_fx ); /* (14-exp) */ + L_tmp = L_mult( pitBufAvg_fx, tmp ); /* (21-exp) */ +#ifdef BASOP_NOGLOB + L_tmp = L_shl_o( L_tmp, add( exp, 10 ), &Overflow ); + tmp = round_fx_o( L_tmp, &Overflow ); /* Q15 */ +#else /* BASOP_NOGLOB */ + L_tmp = L_shl( L_tmp, add( exp, 10 ) ); + tmp = round_fx( L_tmp ); /* Q15 */ +#endif + } + + tmp = s_max( s_min( tmp, 32767 ), 22938 ); /* Q15 */ + GainFrame = Mpy_32_16_1( GainFrame, tmp ); /* Q18 */ + + IF( LT_16( lsp_spacing_fx, 328 ) && lsp_spacing_fx ) + { + GainFrame = Mpy_32_16_1( GainFrame, 21299 ); /* Q18 */ + } + + /*0.25f*sum_f(voice_factors, NB_SUBFR)*/ + L_tmp = L_mult( voice_factors[0], 8192 ); + FOR( i = 1; i < NB_SUBFR; i++ ) + { + L_tmp = L_mac( L_tmp, voice_factors[i], 8192 ); + } + avg_voice_fac = round_fx( L_tmp ); + + test(); + test(); + IF( st_fx->igf != 0 && EQ_16( st_fx->coder_type, VOICED ) ) + { + /*GainFrame *= 0.5f;*/ + GainFrame = Mpy_32_16_1( GainFrame, 16384 ); + } + ELSE IF( st_fx->igf != 0 && GT_16( avg_voice_fac, 11469 ) ) /*Q15 -> 0.35f*/ + { + /*GainFrame *= 0.75f;*/ + GainFrame = Mpy_32_16_1( GainFrame, 24576 ); + } + + /* Quantization of the frame gain parameter */ + IF( st_fx->rf_mode ) + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame, st_fx->extl, st_fx->extl_brate, &st_fx->hRF->RF_bwe_gainFr_ind, 0 ); + } + ELSE + { + QuantizeSHBframegain_ivas_fx( st_fx, &GainFrame, st_fx->extl, st_fx->extl_brate, NULL, 0 ); + } + + /* Adjust the subframe and frame gain of the synthesized SHB signal */ + /* Scale the shaped excitation*/ + ScaleShapedSHB_fx( SHB_OVERLAP_LEN / 2, shaped_wb_excitation, hBWE_TD->syn_overlap_fx, GainShape, GainFrame, window_wb_fx, subwin_wb_fx, + &Q_bwe_exc_ext, &dummy, dummy, dummy ); + + st_fx->prev_Q_bwe_exc = Q_bwe_exc; + move16(); + + return; +} + + +void fb_tbe_reset_enc_fx( + Word32 elliptic_bpf_2_48k_mem_fx[][4], + Word32 *prev_fb_energy_fx, + Word16 elliptic_bpf_2_48k_mem_fx_Q[], + Word16 *prev_fb_energy_fx_Q ) +{ + set32_fx( elliptic_bpf_2_48k_mem_fx[0], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[1], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[2], 0, 4 ); + set32_fx( elliptic_bpf_2_48k_mem_fx[3], 0, 4 ); + *prev_fb_energy_fx = 0; + move16(); + set16_fx( elliptic_bpf_2_48k_mem_fx_Q, 0, 4 ); + *prev_fb_energy_fx_Q = 0; + move16(); + + return; +} +/*======================================================================================*/ +/* FUNCTION : void swb_tbe_enc_fx () */ +/*--------------------------------------------------------------------------------------*/ +/* PURPOSE : SWB TBE encoder, 6 - 14 kHz (or 7.5 - 15.5 kHz) band encoding module */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) coder_type : coding type */ +/* _(Word16*) shb_speech_fx : SHB target signal (6-14kHz) at 16kHz Q0 */ +/* _(Word16*) bwe_exc_extended :bandwidth extended exciatation Q0 */ +/* _(Word16[]) voice_factors :voicing factors Q15 */ +/* _(Word16*) Q_white_exc :Q Format of White Exc */ +/*--------------------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _(Word16[])White_exc16k_fx : shaped white excitation for the FB TBE Q_white_exc */ +/* _(Word16*)fb_slope_fx : slope +ve (high freq > low freq), -ve or neutral Q12 */ +/*--------------------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _ Encoder_State *st_fx: : Encoder state structure */ +/*--------------------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------------------*/ +/* CALLED FROM : TX */ +/*======================================================================================*/ + +void swb_tbe_enc_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + const Word16 coder_type, /* i : coding type */ + Word16 *shb_speech_fx, /* i : SHB target signal (6-14kHz) at 16kHz Q_shb*/ + Word32 *bwe_exc_extended, /* i : bandwidth extended exciatation 2*Q_new*/ + const Word16 voice_factors_fx[], /* i : voicing factors Q15*/ + Word16 *White_exc16k_fx, /* o : shaped white excitation for the FB TBE Q_white_exc*/ + Word16 *Q_white_exc, + Word16 Q_new, + Word16 Q_shb, + Word16 *voicing, /* i : OL maximum normalized correlation */ + const Word16 pitch_buf[] /* i : subframe pitch Q6*/ +) +{ + Word16 i, j; + + Word16 shb_old_speech_fx[L_LOOK_16k + L_SUBFR16k + L_FRAME16k]; + Word16 bwe_exc_extended_16[L_FRAME32k + NL_BUFF_OFFSET]; + + Word16 shaped_shb_excitation_fx[L_FRAME16k + L_SHB_LAHEAD]; + Word32 GainFrame_fx; + Word16 GainShape_fx[NUM_SHB_SUBFR]; + Word16 lpc_shb_fx[LPC_SHB_ORDER + 1], lsp_shb_fx[LPC_SHB_ORDER], lsf_shb_fx[LPC_SHB_ORDER]; + Word16 weights_lsp[LPC_SHB_ORDER]; + Word16 Q_out; + Word16 *shb_frame_fx, *shb_new_speech_fx; + Word16 R_h[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech MSB */ + Word16 R_l[LPC_SHB_ORDER + 2]; /* Autocorrelations of windowed speech LSB */ + Word16 Q_R; + Word32 LepsP[LPC_SHB_ORDER + 1]; + + Word16 ana_align_delay[2] = { -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ), -L_SHB_LAHEAD - ( NL_BUFF_OFFSET / 2 ) }; + Word32 prev_pow_fx, curr_pow_fx, Lscale; + Word32 p2m_in_fx, p2m_out_fx; + + Word16 exp_out, exp, exp1, frac; + Word16 cnt, n_mem, n_mem2; + Word32 L_tmp, L_tmp1; + Word16 Q_bwe_exc; + + Word16 frGainAttenuate, frGainSmoothEn; + Word16 MA_lsp_shb_spacing; + Word16 temp_swb_fac, feedback; + Word32 L_feedback; + Word16 tmp, tmp1, tmp2; + Word32 Lmax; + Word16 sc; + Word16 lsf_shb_orig_fx[LPC_SHB_ORDER]; + Word16 sd_uq_q_fx; + Word16 vf_modified_fx[NB_SUBFR16k]; + Word16 pitBufAvg_fx; + Word16 voicingBufAvg_fx; + Word16 sum1, sum2; + Word16 recip, Q_recip; + const Word16 *ptr_lsp_interp_coef_fx; + + Word16 lsp_shb_1_fx[LPC_SHB_ORDER], lsp_shb_2_fx[LPC_SHB_ORDER], lsp_temp_fx[LPC_SHB_ORDER]; + Word16 lpc_shb_sf_fx[4 * ( LPC_SHB_ORDER + 1 )]; + + /*Word32 shb_ener_sf_fx_32[4];*/ + Word32 shb_ener_sf_Q31; + Word16 shb_res_fx[L_FRAME16k]; + Word16 shb_res_gshape_fx[NB_SUBFR16k]; + Word32 shb_res_gshape_fx_32[NB_SUBFR16k]; + Word16 vf_ind_fx; + + Word16 formant_fac_fx; + Word16 shaped_shb_excitationTemp_fx[L_FRAME16k]; + + Word16 mean_vf; + Word16 lsf_diff[LPC_SHB_ORDER], w[LPC_SHB_ORDER]; + Word16 refl[M]; + Word16 tilt_para; + Word16 Q_bwe_exc_fb; + Word16 n_subfr_saturation; +#ifdef BASOP_NOGLOB_DECLARE_LOCAL + Flag Overflow = 0; +#endif + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + + /* init and buffers set up */ + exp1 = 0; /* to avoid compilation warnings */ + set16_fx( shaped_shb_excitationTemp_fx, 0, L_FRAME16k ); + + /* compensate for the delay in target generation and subframe LA */ + shb_frame_fx = shb_old_speech_fx + L_SUBFR16k + ana_align_delay[0]; + move16(); + + /* set up the speech buffers for TBE processing*/ + shb_new_speech_fx = shb_old_speech_fx + ( L_LOOK_16k + L_SUBFR16k ); + move16(); + Copy( hBWE_TD->old_speech_shb_fx, shb_old_speech_fx, ( L_LOOK_16k + L_SUBFR16k ) ); + Copy( shb_speech_fx, shb_new_speech_fx, L_FRAME16k ); + Copy( shb_old_speech_fx + L_FRAME16k, hBWE_TD->old_speech_shb_fx, ( L_LOOK_16k + L_SUBFR16k ) ); + + /* autocorrelation of SHB speech for 10-th order LP analysis */ + autocorr_fx( shb_old_speech_fx, + LPC_SHB_ORDER + 1, + R_h, /* autocorr (msb) Q15 */ + R_l, /* autocorr (lsb) */ + &Q_R, + NS2SA( INT_FS_16k, ACELP_LOOK_NS ) + L_SUBFR16k + L_FRAME16k, + win_lpc_shb_fx, + 0, + 1 ); + + + /* Spectral smoothing of autocorrelation coefficients */ + test(); + IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + L_tmp = Mpy_32( R_h[i], R_l[i], wac_swb_h[i - 1], wac_swb_l[i - 1] ); + L_Extract( L_tmp, &R_h[i], &R_l[i] ); + } + } + + /* Set the autocorr[0] element to a non-negative value */ + R_l[0] = s_max( R_l[0], 1 ); + move16(); + + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, LPC_SHB_ORDER, NULL ); /* LPC in Q14 */ + { + Word16 enerG, lpc_shb1[M + 1]; + + /* extend the lpc_shb to a 16th order gain calc */ + set16_fx( lpc_shb1, 0, M + 1 ); + Copy( lpc_shb_fx, lpc_shb1, LPC_SHB_ORDER + 1 ); + + /* estimate the LP gain */ + enerG = Enr_1_Az_fx( lpc_shb1, 2 * L_SUBFR ); /* Q3 */ + + /* if the LP gain is greater than a threshold, avoid saturation */ + IF( GT_16( enerG, 256 /*32 Q3*/ ) ) + { + set16_fx( lpc_shb_fx, 0, LPC_SHB_ORDER + 1 ); + E_LPC_lev_dur( R_h, R_l, lpc_shb_fx, LepsP, 2, NULL ); /* LPC in Q14 */ + } + } + + /* this is needed as the E_LPC_lev_dur function outputs lpc in Q14 */ + Copy_Scale_sig( lpc_shb_fx, lpc_shb_fx, LPC_SHB_ORDER + 1, sub( norm_s( lpc_shb_fx[0] ), 2 ) ); + + /* Expand bandwidth of the LP coeffs */ + test(); + IF( ( st_fx->rf_mode != 0 ) || EQ_32( st_fx->total_brate, ACELP_9k60 ) ) + { + FOR( i = 1; i <= LPC_SHB_ORDER; i++ ) + { + lpc_shb_fx[i] = mult_r( lpc_shb_fx[i], lpc_weights_fx[i] ); + } + } + + /* LPC to LSP conversion */ + /* LPC: Q12, LSP: Q15 */ + E_LPC_a_lsp_conversion( lpc_shb_fx, lsp_shb_fx, hBWE_TD->prev_lsp_shb_fx, LPC_SHB_ORDER ); + + /* LSP to LSF conversion */ /* LSP: Q15, LSF: Q15 */ E_LPC_lsp_lsf_conversion( lsp_shb_fx, lsf_shb_fx, LPC_SHB_ORDER ); @@ -2053,16 +2682,15 @@ void swb_tbe_enc_fx( /*--------------------------------------------------------------------------*/ static void EstimateSHBFrameGain_fx( - const Word16 length, /* i : SHB overlap length */ - const Word16 *oriSHB, /* i : target original SHB frame Q_oriSHB */ - const Word16 Q_oriSHB, - const Word16 *synSHB, /* i : shaped SHB excitation Q_synSHB */ - const Word16 Q_synSHB, - Word16 *subgain, /* i : estimate of gain shape Q15 */ - Word32 *GainFrame, /* o : estimat of gain frame Q18 */ - const Word16 *win_shb, /* i : SHB window Q15 */ - const Word16 *subwin_shb_local /* i : SHB subframe window Q15 */ - , + const Word16 length, /* i : SHB overlap length */ + const Word16 *oriSHB, /* i : target original SHB frame Q(Q_oriSHB) */ + const Word16 Q_oriSHB, /* i : Q of arget original SHB frame */ + const Word16 *synSHB, /* i : shaped SHB excitation Q(Q_synSHB) */ + const Word16 Q_synSHB, /* i : Q of shaped SHB excitation */ + Word16 *subgain, /* i : estimate of gain shape Q15 */ + Word32 *GainFrame, /* o : estimat of gain frame Q18 */ + const Word16 *win_shb, /* i : SHB window Q15 */ + const Word16 *subwin_shb_local, /* i : SHB subframe window Q15 */ const Word16 n_subfr_saturation /* i : Number of subframes which saturated in GainShape oriNrg calculation */ ) { @@ -2070,7 +2698,7 @@ static void EstimateSHBFrameGain_fx( Word16 i, j, k, l_shb_lahead, l_frame; Word16 join_length, num_join, sig; Word32 mod_syn[L_FRAME16k + L_SHB_LAHEAD]; - Word32 oriNrg = 0, synNrg = 0; + Word32 oriNrg, synNrg; Word16 sum_gain; Word32 frame_gain; Word32 L_tmp; @@ -2079,7 +2707,9 @@ static void EstimateSHBFrameGain_fx( Word16 scaling = 0; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + move16(); /* initilaization */ l_frame = L_FRAME16k; @@ -2088,7 +2718,6 @@ static void EstimateSHBFrameGain_fx( move16(); skip = skip_bands_SWB_TBE; - IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { skip = skip_bands_WB_TBE; @@ -2101,7 +2730,6 @@ static void EstimateSHBFrameGain_fx( /* apply gain for each subframe, and store noise output signal using overlap-add*/ set32_fx( mod_syn, 0, l_frame + l_shb_lahead ); - IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { sum_gain = 0; @@ -2123,7 +2751,6 @@ static void EstimateSHBFrameGain_fx( move16(); FOR( k = 0; k < length; k++ ) { - L_tmp = L_mult0( subwin_shb_local[k + 1], subgain[i] ); /* Q30 */ sum_gain = round_fx( L_mac0( L_tmp, subwin_shb_local[length - k - 1], subgain[i - 1] ) ); /* Q14 */ mod_syn[j + k] = L_shl( L_mult( sum_gain, synSHB[j + k] ), 1 ); @@ -2151,7 +2778,7 @@ static void EstimateSHBFrameGain_fx( sum_gain = mult_r( subwin_shb_local[k + 1], subgain[0] ); /* Q15 */ mod_syn[j] = L_mult( synSHB[j], sum_gain ); move32(); /* Q(16+Q_synSHB) */ - j++; + j = add( j, 1 ); } FOR( i = 0; i < NUM_SHB_SUBGAINS - 1; i++ ) { @@ -2159,7 +2786,7 @@ static void EstimateSHBFrameGain_fx( { mod_syn[j] = L_mult( synSHB[j], subgain[i * num_join] ); move32(); /* Q(16+Q_synSHB) */ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) @@ -2168,21 +2795,21 @@ static void EstimateSHBFrameGain_fx( tmp = round_fx( L_mac0( L_tmp, subwin_shb_local[k + 1], subgain[( i + 1 ) * num_join] ) ); /* Q14 */ mod_syn[j] = L_shl( L_mult( tmp, synSHB[j] ), 1 ); move32(); /* Q(16+Q_synSHB) */ - j++; + j = add( j, 1 ); } } FOR( k = 0; k < join_length - length; k++ ) { mod_syn[j] = L_mult( synSHB[j], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); move32(); /* Q(16+Q_synSHB)*/ - j++; + j = add( j, 1 ); } FOR( k = 0; k < length; k++ ) { tmp = mult_r( subwin_shb_local[length - k - 1], subgain[( NUM_SHB_SUBGAINS - 1 ) * num_join] ); /* Q15 */ mod_syn[j] = L_mult( tmp, synSHB[j] ); move32(); /* Q(16+Q_synSHB ) */ - j++; + j = add( j, 1 ); } } /* adjust frame energy */ @@ -2236,8 +2863,7 @@ static void EstimateSHBFrameGain_fx( } IF( EQ_32( oriNrg, MAX_32 ) ) { - scaling = negate( shr( n_subfr_saturation, 1 ) + 1 ); - move16(); + scaling = negate( add( shr( n_subfr_saturation, 1 ), 1 ) ); oriNrg = 0; move32(); FOR( i = 0; i < l_shb_lahead; i++ ) @@ -2287,7 +2913,7 @@ static void EstimateSHBFrameGain_fx( static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) { - Word16 i, j = 0; + Word16 i, j; Word32 sum, L_tmp; sum = L_shr( L_mult0( a[0], a[0] ), 1 ); /* Q29 */ @@ -2311,6 +2937,32 @@ static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) } +static Word32 pow_off_pk_corrected_fx( Word16 a[], Word16 len, Word16 step ) +{ + Word16 i, j; + Word32 sum, L_tmp; + + sum = L_shr( L_mult0( a[0], a[0] ), 1 ); /* Q29 */ + + j = 0; + move16(); + FOR( i = step; i < len; i += step ) + { + L_tmp = L_shr( L_mult0( a[i], a[i] ), 1 ); /* Q29 */ + sum = L_add( sum, L_tmp ); /* Q29 */ + if ( GT_16( a[i], a[j] ) ) + { + j = i; + move16(); + } + } + L_tmp = L_shr( L_mult0( a[j], a[j] ), 1 ); /* Q29 */ + sum = L_sub( sum, L_tmp ); /* Q29 */ + + return ( sum ); +} + + /*==========================================================================*/ /* FUNCTION : static void EstimateSHBGainShape_fx() */ /*--------------------------------------------------------------------------*/ @@ -2333,15 +2985,15 @@ static Word32 pow_off_pk_fx( Word16 a[], Word16 len, Word16 step ) /* RETURN ARGUMENTS : */ /* _ None */ /*--------------------------------------------------------------------------*/ + static void EstimateSHBGainShape_fx( - const Word16 length, /* i : SHB overlap length */ - const Word16 *oriSHB, /* i : target original SHB frame Q_oriSHB*/ - const Word16 Q_oriSHB, - const Word16 *synSHB, /* i : shaped SHB excitation Q_synSHB*/ - const Word16 Q_synSHB, - Word16 *subgain, /* o : estimate of gain shape Q15*/ - const Word16 *subwin /* i : SHB subframe window Q15*/ - , + const Word16 length, /* i : SHB overlap length */ + const Word16 *oriSHB, /* i : target original SHB frame Q(Q_oriSHB) */ + const Word16 Q_oriSHB, /* i : Q of target original SHB frame */ + const Word16 *synSHB, /* i : shaped SHB excitation Q(Q_synSHB) */ + const Word16 Q_synSHB, /* i : Q of shaped SHB excitation */ + Word16 *subgain, /* o : estimate of gain shape Q15 */ + const Word16 *subwin, /* i : SHB subframe window Q15 */ Word16 *n_subfr_saturation /* o : Number of subframes which saturated while calculating oriNrg */ ) { @@ -2361,8 +3013,12 @@ static void EstimateSHBGainShape_fx( Word16 scaling = 0; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif + move32(); move16(); + move16(); + num_join = NUM_SHB_SUBFR / NUM_SHB_SUBGAINS; move16(); num_gains = NUM_SHB_SUBGAINS; @@ -2374,13 +3030,12 @@ static void EstimateSHBGainShape_fx( num_gains = NUM_SHB_SUBFR / 4; move16(); skip = skip_bands_WB_TBE; - move16(); } /* calculate and normalize the subgain */ oriNrg = 0; - move16(); + move32(); synNrg = 0; - move16(); + move32(); IF( EQ_16( length, SHB_OVERLAP_LEN / 2 ) ) { @@ -2390,11 +3045,12 @@ static void EstimateSHBGainShape_fx( IF( ( i & 0x1 ) == 0 ) { oriNrg = 0; - move16(); + move32(); synNrg = 0; - move16(); + move32(); } j = skip[i]; + move16(); IF( i == 0 ) { FOR( k = 0; k < length / 2; k++ ) @@ -2445,7 +3101,7 @@ static void EstimateSHBGainShape_fx( #endif } } - IF( i == NUM_SHB_SUBFR / 2 - 1 ) + IF( EQ_16( i, NUM_SHB_SUBFR / 2 - 1 ) ) { length_tmp = sub( length2, shr( length, 1 ) ); FOR( ; k < length_tmp; k++ ) @@ -2487,7 +3143,7 @@ static void EstimateSHBGainShape_fx( logic16(); IF( EQ_16( ( i & 0x1 ), 1 ) ) { - L_subgain[i / 2] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + L_subgain[i / 2] = root_a_over_b_fx( oriNrg, shl( Q_oriSHB, 1 ), synNrg, shl( Q_synSHB, 1 ), &n ); move16(); /* Q(31-n) */ norm[i / 2] = n; move16(); @@ -2505,12 +3161,11 @@ static void EstimateSHBGainShape_fx( FOR( i = 0; i < num_gains; i++ ) { oriNrg = 0; - move16(); + move32(); synNrg = 0; - move16(); + move32(); - j = join_length * i; - move16(); + j = i_mult2( join_length, i ); FOR( k = 0; k < length; k++ ) { sig = mult_r( oriSHB[j + k], subwin[k + 1] ); /* Q_oriSHB */ @@ -2563,9 +3218,10 @@ static void EstimateSHBGainShape_fx( move16(); IF( EQ_32( oriNrg, MAX_32 ) ) { - if ( n_subfr_saturation != NULL ) + IF( n_subfr_saturation != NULL ) { *n_subfr_saturation = add( *n_subfr_saturation, 1 ); + move16(); } scaling = -1; move16(); @@ -2599,7 +3255,7 @@ static void EstimateSHBGainShape_fx( #endif } } - L_subgain[i] = root_a_over_b_fx( oriNrg, 2 * Q_oriSHB, synNrg, 2 * Q_synSHB, &n ); + L_subgain[i] = root_a_over_b_fx( oriNrg, shl( Q_oriSHB, 1 ), synNrg, shl( Q_synSHB, 1 ), &n ); move32(); /* Q(31-n) */ n = sub( n, scaling ); norm[i] = n; @@ -2621,22 +3277,24 @@ static void EstimateSHBGainShape_fx( subgain[i] = round_fx( L_shl( L_subgain[i], sub( norm[i], n_max + 1 ) ) ); /* Q(14-n_max) */ L_sum_gain = L_mac0( L_sum_gain, subgain[i], subgain[i] ); /* Q(28-2*n_max) */ #endif + move16(); } /* normalize the subgain */ n = norm_l( L_sum_gain ); L_sum_gain = L_shl( L_sum_gain, n ); - n = sub( 31, add( n, ( sub( 28, n_max * 2 ) ) ) ); + n = sub( 31, add( n, ( sub( 28, shl( n_max, 1 ) ) ) ) ); normFact = Isqrt_lc( L_sum_gain, &n ); FOR( i = 0; i < num_gains; i++ ) { - L_tmp = Mult_32_16( normFact, subgain[i] ); /*Q(31-n) * Q(31-norm[i]) */ /* Q(30-n-n_max) */ + L_tmp = Mpy_32_16_1( normFact, subgain[i] ); /*Q(31-n) * Q(31-norm[i]) */ /* Q(30-n-n_max) */ #ifdef BASOP_NOGLOB subgain[i] = s_max( round_fx_o( L_shl_o( L_tmp, add( n, n_max + 1 ), &Overflow ), &Overflow ), 3277 /*0.1f Q15*/ ); /* Q15 */ #else subgain[i] = s_max( round_fx( L_shl( L_tmp, add( n, n_max + 1 ) ) ), 3277 /*0.1f Q15*/ ); /* Q15 */ #endif + move16(); } return; @@ -2731,31 +3389,162 @@ static Word16 closest_centroid_lc_fx( tmp = sub( data[0], quantizer[tmpL] ); werr = L_mult( tmp, tmp ); - /* index 1 */ - tmp = sub( data[1], quantizer[tmpL + 1] ); - werr = L_mac( werr, tmp, tmp ); + /* index 1 */ + tmp = sub( data[1], quantizer[tmpL + 1] ); + werr = L_mac( werr, tmp, tmp ); + + /* index 2 */ + tmp = sub( data[2], quantizer[tmpL + 2] ); + werr = L_mac( werr, tmp, tmp ); + + /* index 3 */ + tmp = sub( data[3], quantizer[tmpL + 3] ); + werr = L_mac( werr, tmp, tmp ); + + if ( LT_32( werr, best_werr ) ) + { + index = i; + move16(); + } + best_werr = L_min( best_werr, werr ); + } + + return index; +} + +/*============================================================*/ +/* FUNCTION : static void QuantizeSHBsubgains_fx() */ +/*------------------------------------------------------------*/ +/* PURPOSE : Quantize super highband temporal gains */ +/*------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* _(Word16) extl : extension layer Q0 */ +/*------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* _(Word16[])subgains :super highband temporal gains Q15 */ +/*------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*------------------------------------------------------------*/ + +static void QuantizeSHBsubgains_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 subgains[], /* i/o: super highband temporal gains Q15*/ + const Word16 extl /* i : extension layer */ +) +{ + Word16 i, idxSubGain; + Word16 Unit_weights10[NUM_SHB_SUBFR]; + Word16 exp, frac; + Word32 L_tmp; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16( extl, WB_TBE ) ) + { + set16_fx( Unit_weights10, 32767, (Word16) NUM_SHB_SUBFR / 4 ); + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + IF( EQ_16( subgains[i], 0 ) ) + { + subgains[i + NUM_SHB_SUBFR / 4] = -18432; + move16(); /* (-72) in Q8 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); /* move16(); */ + /*exp = -1 - exp; */ + exp = sub( -1, exp ); + L_tmp = Mpy_32_16( exp, frac, 24660 ); /* Q13 ; 20.0 * log10(2) in Q12*/ + subgains[i + NUM_SHB_SUBFR / 4] = round_fx( L_shl( L_tmp, 11 ) ); /* Q8 */ + } + } + idxSubGain = closest_centroid_lc_fx( subgains + NUM_SHB_SUBFR / 4, HBCB_SubGain5bit_fx, 1 << NUM_BITS_SHB_SUBGAINS ); + Copy( HBCB_SubGain5bit_fx + idxSubGain * NUM_SHB_SUBFR / 4, subgains, NUM_SHB_SUBFR / 4 ); + + push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + + FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) + { + L_tmp = L_mult( subgains[i], 21771 ); /* *0.166096 in Q17 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16(); /*Q15 */ + } + + FOR( i = NUM_SHB_SUBFR / 2 - 1; i >= 0; i-- ) + { + subgains[i] = subgains[i / 2]; + move16(); + } + } + ELSE + { + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + IF( EQ_16( subgains[i], 0 ) ) + { + subgains[i] = -12288; + move16(); /* (-3) in Q12 */ + } + ELSE + { + L_tmp = L_deposit_h( subgains[i] ); /* Q31 */ + exp = norm_l( L_tmp ); + frac = Log2_norm_lc( L_shl( L_tmp, exp ) ); + /*exp = -1 - exp; */ + exp = sub( -1, exp ); + + L_tmp = Mpy_32_16( exp, frac, 9864 ); /*move32(); // Q16 ; log10(2) in Q15 */ + subgains[i] = round_fx( L_shl( L_tmp, 12 ) ); /*Q12 */ + } + } - /* index 2 */ - tmp = sub( data[2], quantizer[tmpL + 2] ); - werr = L_mac( werr, tmp, tmp ); + idxSubGain = (Word16) vquant_fx( subgains, 0, subgains, SHBCB_SubGain5bit_12_fx, NUM_SHB_SUBGAINS, 1 << NUM_BITS_SHB_SUBGAINS ); - /* index 3 */ - tmp = sub( data[3], quantizer[tmpL + 3] ); - werr = L_mac( werr, tmp, tmp ); + FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) + { + L_tmp = L_mult( subgains[i], 27213 ); /* *3.321928 in Q13 -> Q26 */ + L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + subgains[i] = extract_l( Pow2( 14, frac ) ); + /* Put 14 as exponent so that */ + /* output of Pow2() will be: */ + /* 16384 < Pow2() <= 32767 */ + subgains[i] = shl( subgains[i], exp + 1 ); + move16(); /*Q15 */ + } - if ( LT_32( werr, best_werr ) ) + FOR( i = NUM_SHB_SUBFR - 1; i >= 0; i-- ) { - index = i; + subgains[i] = subgains[i * NUM_SHB_SUBGAINS / NUM_SHB_SUBFR]; move16(); } - best_werr = L_min( best_werr, werr ); + + hBWE_TD->idxSubGains = idxSubGain; + move16(); + IF( NE_16( st_fx->codec_mode, MODE2 ) ) + { + push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + } } - return index; + return; } + /*============================================================*/ -/* FUNCTION : static void QuantizeSHBsubgains_fx() */ +/* FUNCTION : static void QuantizeSHBsubgains_ivas_fx() */ /*------------------------------------------------------------*/ /* PURPOSE : Quantize super highband temporal gains */ /*------------------------------------------------------------*/ @@ -2772,10 +3561,10 @@ static Word16 closest_centroid_lc_fx( /* _ None */ /*------------------------------------------------------------*/ -static void QuantizeSHBsubgains_fx( - Encoder_State *st_fx, /* i/o: encoder state structure */ - Word16 subgains[], /* i/o: super highband temporal gains Q15*/ - const Word16 extl /* i : extension layer */ +static void QuantizeSHBsubgains_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word16 subgains[], /* i/o: super highband temporal gains Q15 */ + const Word16 extl /* i : extension layer */ ) { Word16 i, idxSubGain; @@ -2787,7 +3576,7 @@ static void QuantizeSHBsubgains_fx( IF( EQ_16( extl, WB_TBE ) ) { - set16_fx( Unit_weights10, 32767, (Word16) NUM_SHB_SUBFR / 4 ); + set16_fx( Unit_weights10, 32767, NUM_SHB_SUBFR / 4 ); FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) { IF( EQ_16( subgains[i], 0 ) ) @@ -2804,12 +3593,13 @@ static void QuantizeSHBsubgains_fx( exp = sub( -1, exp ); L_tmp = Mpy_32_16( exp, frac, 24660 ); /* Q13 ; 20.0 * log10(2) in Q12*/ subgains[i + NUM_SHB_SUBFR / 4] = round_fx( L_shl( L_tmp, 11 ) ); /* Q8 */ + move16(); } } idxSubGain = closest_centroid_lc_fx( subgains + NUM_SHB_SUBFR / 4, HBCB_SubGain5bit_fx, 1 << NUM_BITS_SHB_SUBGAINS ); Copy( HBCB_SubGain5bit_fx + idxSubGain * NUM_SHB_SUBFR / 4, subgains, NUM_SHB_SUBFR / 4 ); - push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + push_indice( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); FOR( i = 0; i < NUM_SHB_SUBFR / 4; i++ ) { @@ -2817,6 +3607,7 @@ static void QuantizeSHBsubgains_fx( L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ frac = L_Extract_lc( L_tmp, &exp ); subgains[i] = extract_l( Pow2( 14, frac ) ); + move16(); /* Put 14 as exponent so that */ /* output of Pow2() will be: */ /* 16384 < Pow2() <= 32767 */ @@ -2849,10 +3640,11 @@ static void QuantizeSHBsubgains_fx( L_tmp = Mpy_32_16( exp, frac, 9864 ); /*move32(); // Q16 ; log10(2) in Q15 */ subgains[i] = round_fx( L_shl( L_tmp, 12 ) ); /*Q12 */ + move16(); } } - idxSubGain = (Word16) vquant_fx( subgains, 0, subgains, SHBCB_SubGain5bit_12_fx, NUM_SHB_SUBGAINS, 1 << NUM_BITS_SHB_SUBGAINS ); + idxSubGain = vquant_fx( subgains, 0, subgains, SHBCB_SubGain5bit_12_fx, NUM_SHB_SUBGAINS, 1 << NUM_BITS_SHB_SUBGAINS ); FOR( i = 0; i < NUM_SHB_SUBGAINS; i++ ) { @@ -2860,6 +3652,7 @@ static void QuantizeSHBsubgains_fx( L_tmp = L_shr( L_tmp, 10 ); /* From Q26 to Q16 */ frac = L_Extract_lc( L_tmp, &exp ); subgains[i] = extract_l( Pow2( 14, frac ) ); + move16(); /* Put 14 as exponent so that */ /* output of Pow2() will be: */ /* 16384 < Pow2() <= 32767 */ @@ -2873,11 +3666,14 @@ static void QuantizeSHBsubgains_fx( move16(); } - hBWE_TD->idxSubGains = idxSubGain; - move16(); - IF( NE_16( st_fx->codec_mode, MODE2 ) ) + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) { - push_indice_fx( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); + hBWE_TD->idxSubGains = idxSubGain; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_SUBGAIN, idxSubGain, NUM_BITS_SHB_SUBGAINS ); } } @@ -2967,6 +3763,7 @@ static void Quant_shb_res_gshape_fx( } } + /*==========================================================================*/ /* FUNCTION : static void QuantizeSHBframegain_fx() */ /*--------------------------------------------------------------------------*/ @@ -2986,6 +3783,7 @@ static void Quant_shb_res_gshape_fx( /*--------------------------------------------------------------------------*/ /* */ /*==========================================================================*/ + static void QuantizeSHBframegain_fx( Encoder_State *st_fx, /* i/o: encoder state structure */ Word32 *GainFrame, /* i/o: Gain Q18 */ @@ -3126,6 +3924,246 @@ return; } +/*==========================================================================*/ +/* FUNCTION : static void QuantizeSHBframegain_ivas_fx() */ +/*--------------------------------------------------------------------------*/ +/* PURPOSE : QQuantize super highband frame gain */ +/*--------------------------------------------------------------------------*/ +/* INPUT ARGUMENTS : */ +/* Word16 extl i : extension layer */ +/* Word32 extl_brate i : extension layer bitrate */ +/*--------------------------------------------------------------------------*/ +/* OUTPUT ARGUMENTS : */ +/*--------------------------------------------------------------------------*/ +/* INPUT/OUTPUT ARGUMENTS : */ +/* Word32 *GainFrame i/o: Gain Q18 */ +/*--------------------------------------------------------------------------*/ +/* RETURN ARGUMENTS : */ +/* _ None */ +/*--------------------------------------------------------------------------*/ +/* */ +/*==========================================================================*/ + +static void QuantizeSHBframegain_ivas_fx( + Encoder_State *st_fx, /* i/o: encoder state structure */ + Word32 *GainFrame, /* i/o: Gain Q18 */ + const Word16 extl, /* i : extension layer */ + Word32 extl_brate, /* i : extension layer bitrate */ + Word16 *rf_gainFrame_ind, + const Word16 flag_conservative /* i : flag to indicate more conservative gain quantization */ +) +{ + Word16 idxFrameGain; + Word32 Q_GainFrame; + Word16 Unit_weights1 = 1; + Word16 exp, frac, tmp; + Word32 L_tmp; + Word32 GainFrameLog; + TD_BWE_ENC_HANDLE hBWE_TD = st_fx->hBWE_TD; + RF_ENC_HANDLE hRF = st_fx->hRF; + move16(); + + BSTR_ENC_HANDLE hBstr = st_fx->hBstr; + + IF( EQ_16( extl, WB_TBE ) ) + { + determine_gain_weights_fx( GainFrame, &( Unit_weights1 ), 1 ); + IF( EQ_32( extl_brate, WB_TBE_0k35 ) ) + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain_LBR_WB, &idxFrameGain, + &Q_GainFrame, SHBCB_FrameGain16_fx ); + test(); + IF( GT_32( Q_GainFrame, L_shl( Mult_32_16( *GainFrame, 17367 ), 1 ) ) && idxFrameGain > 0 ) /* 1.06 = +0.5 dB */ + { + idxFrameGain--; + Q_GainFrame = L_add( SHBCB_FrameGain16_fx[idxFrameGain], 0 ); /* Q18 */ + } + + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + hBWE_TD->gFrame_WB = idxFrameGain; + move16(); + } + ELSE + { + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FrameGain_LBR_WB ); + } + + if ( st_fx->rf_mode ) + { + *rf_gainFrame_ind = idxFrameGain; + move16(); + } + } + ELSE + { + singlevectortest_gain_fx( GainFrame, 1, + 1 << NUM_BITS_SHB_FrameGain, &idxFrameGain, &Q_GainFrame, + SHBCB_FrameGain64_fx ); + + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FrameGain ); + + if ( st_fx->rf_mode ) + { + *rf_gainFrame_ind = idxFrameGain; + move16(); + } + } + } + ELSE + { + IF( *GainFrame == 0 ) + { + GainFrameLog = -196608; /* Q16 */ + move32(); + } + ELSE + { + exp = norm_l( *GainFrame ); + frac = Log2_norm_lc( L_shl( *GainFrame, exp ) ); + exp = ( 30 - exp - 18 ); + GainFrameLog = Mpy_32_16( exp, frac, 9864 ); + /*GainFrameLog= round_fx(L_shl(L_tmp,12)); //Q12 */ + } + + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + /* idxFrameGain = (int16_t) usquant( GainFrameLog, &Q_GainFrame, SHB_GAIN_QLOW_1k75, SHB_GAIN_QDELTA_1k75, 1 << NUM_BITS_SHB_FRAMEGAIN_1k75 ); */ + exp = norm_s( SHB_GAIN_QDELTA_1k75_FX_15 ); + tmp = div_s( shl( 1, sub( 14, exp ) ), SHB_GAIN_QDELTA_1k75_FX_15 ); + L_tmp = Mpy_32_16_1( L_sub( GainFrameLog, SHB_GAIN_QLOW_1k75_FX ), tmp ); + idxFrameGain = extract_l( L_shr( L_add( L_tmp, shl( 1, sub( 14, exp ) ) ), sub( 15, exp ) ) ); /*Q0*/ + IF( GT_16( idxFrameGain, ( 1 << NUM_BITS_SHB_FRAMEGAIN_1k75 ) - 1 ) ) + { + idxFrameGain = ( 1 << NUM_BITS_SHB_FRAMEGAIN_1k75 ) - 1; + move16(); + } + ELSE + { + if ( idxFrameGain < 0 ) + { + idxFrameGain = 0; + move16(); + } + } + L_tmp = SHB_GAIN_QLOW_1k75_FX; + move32(); + Q_GainFrame = L_mac( L_tmp, idxFrameGain, SHB_GAIN_QDELTA_1k75_FX_15 ); + } + ELSE + { + /* idxFrameGain = (int16_t) usquant( GainFrameLog, &Q_GainFrame, SHB_GAIN_QLOW, SHB_GAIN_QDELTA, 1 << NUM_BITS_SHB_FRAMEGAIN ); */ + exp = norm_s( SHB_GAIN_QDELTA_FX_15 ); + tmp = div_s( shl( 1, sub( 14, exp ) ), SHB_GAIN_QDELTA_FX_15 ); + L_tmp = Mpy_32_16_1( L_sub( GainFrameLog, SHB_GAIN_QLOW_FX_16 ), tmp ); + idxFrameGain = extract_l( L_shr( L_add( L_tmp, shl( 1, sub( 14, exp ) ) ), sub( 15, exp ) ) ); /*Q0*/ + IF( GT_16( idxFrameGain, ( 1 << NUM_BITS_SHB_FRAMEGAIN ) - 1 ) ) + { + idxFrameGain = ( 1 << NUM_BITS_SHB_FRAMEGAIN ) - 1; + move16(); + } + ELSE + { + if ( idxFrameGain < 0 ) + { + idxFrameGain = 0; + move16(); + } + } + L_tmp = SHB_GAIN_QLOW_FX_16; + move32(); + Q_GainFrame = L_mac( L_tmp, idxFrameGain, SHB_GAIN_QDELTA_FX_15 ); + } + + + WHILE( GT_32( Q_GainFrame, L_add( GainFrameLog, 4866 ) ) && + idxFrameGain != 0 ) + { + idxFrameGain = sub( idxFrameGain, 1 ); + Q_GainFrame = L_mac0( SHB_GAIN_QLOW_FX_16, idxFrameGain, SHB_GAIN_QDELTA_FX_16 ); + } + + test(); + test(); + IF( flag_conservative && GT_32( Q_GainFrame, L_add( GainFrameLog, Mpy_32_16_1( SHB_GAIN_QDELTA_FX_16, 13435 /* 0.41 in Q15 */ ) ) ) && idxFrameGain != 0 ) + { + /* be more conservative in the quantization process -> prevent energy overshoot */ + idxFrameGain = sub( idxFrameGain, 1 ); + Q_GainFrame = L_mac0( SHB_GAIN_QLOW_FX_16, idxFrameGain, SHB_GAIN_QDELTA_FX_16 ); + } + + /* Q_GainFrame = (float) pow(10.0, Q_GainFrame ); */ + /* i: Q_GainFrame in Q16 */ + L_tmp = Mpy_32_16_1( Q_GainFrame, 27213 ); /* *3.321928 in Q13 -> Q25 */ + L_tmp = L_shr( L_tmp, -2 ); /* From Q26 to Q16 */ + frac = L_Extract_lc( L_tmp, &exp ); + Q_GainFrame = Pow2( 30, frac ); + exp = sub( exp, 30 ); + Q_GainFrame = L_shl( Q_GainFrame, exp + 18 ); /* Q18 */ + + IF( EQ_16( st_fx->codec_mode, MODE2 ) ) + { + st_fx->hBWE_TD->idxFrameGain = idxFrameGain; + move16(); + } + ELSE + { + IF( EQ_32( st_fx->extl_brate, SWB_TBE_1k75 ) ) + { + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN_1k75 ); + } + ELSE + { + push_indice( hBstr, IND_SHB_FRAMEGAIN, idxFrameGain, NUM_BITS_SHB_FRAMEGAIN ); + } + } + + if ( st_fx->rf_mode ) + { + *rf_gainFrame_ind = idxFrameGain; + move16(); + } + } + + IF( EQ_16( st_fx->rf_mode, 1 ) ){ + /*Currently intended for SWB only. Modify for WB is needed later!*/ + IF( EQ_16( hRF->rf_frame_type, RF_NELP ) ){ + *rf_gainFrame_ind = idxFrameGain; /* NELP Frame uses full 5 bits */ + move16(); +} +ELSE /*RF_ALLPRED, RF_GENPRED, RF_NOPRED modes*/ +{ + IF( LE_32( *GainFrame, 327680 /*1.25 in Q18*/ ) ) /* [0 to 1.25] range --> 0.5*/ + { + *rf_gainFrame_ind = 0; + move16(); + } + ELSE IF( LE_32( *GainFrame, 786432 /*3 in Q18*/ ) ) /* (1.25 to 3] --> 2 */ + { + *rf_gainFrame_ind = 1; + move16(); + } + ELSE IF( LE_32( *GainFrame, 1572864 /*6 in Q18*/ ) ) /* (3 to 6] --> 4 */ + { + *rf_gainFrame_ind = 2; + move16(); + } + ELSE /* (6 to Inf) --> 8 */ + { + *rf_gainFrame_ind = 3; + move16(); + } +} +} + +*GainFrame = Q_GainFrame; +move32(); /* Q18 */ + +return; +} + + /*============================================================*/ /* FUNCTION : static void determine_gain_weights_fx() */ /*------------------------------------------------------------*/ diff --git a/lib_enc/tcx_utils_enc_fx.c b/lib_enc/tcx_utils_enc_fx.c index b64532e69816a5374c4443de056e1758ce65b6bd..1ff3633601e678bc6cdebdc6c790c056b76f5e3c 100644 --- a/lib_enc/tcx_utils_enc_fx.c +++ b/lib_enc/tcx_utils_enc_fx.c @@ -689,6 +689,225 @@ Word16 SQ_gain_fx( /* output: SQ gain */ return tmp16; } +Word16 SQ_gain_estimate_fx( /* output: SQ gain */ + Word32 x[], /* input: vector to quantize */ + Word16 x_e, /* input: exponent */ + Word16 nbitsSQ, /* input: number of bits targeted */ + Word16 lg, /* input: vector size (2048 max) */ + Word16 *gain_e ) /* output: SQ gain exponent */ +{ + Word16 i, iter, max_iter, lg_4, s, tmp16; + Word32 ener, tmp32; + Word32 target, fac, offset; + Word32 en[N_MAX / 4]; + Word32 tmp = 0, tmpp = 0; + move32(); + move32(); + + /* tmp = 0.5f * (float) log10( (float) lg / (float) NORM_MDCT_FACTOR ) + + 0.94f; lowest gain + expected value of the quantization noise energy per quadruple (log10(4/12)) in Q16*/ + /* tmpp = 0.5f * (float) log10( (float) lg / (float) NORM_MDCT_FACTOR ) * log2(10) in Q16 */ + SWITCH( lg ) + { + case 80: + tmp = 171876; + tmpp = -32768; + move32(); + move32(); + BREAK; + case 100: + tmp = 182424; + tmpp = -22219; + move32(); + move32(); + BREAK; + case 160: + tmp = 204644; + tmpp = 0; + move32(); + BREAK; + case 200: + tmp = 215192; + tmpp = 10549; + move32(); + move32(); + BREAK; + case 240: + tmp = 223812; + tmpp = 19168; + move32(); + move32(); + BREAK; + case 300: + tmp = 234361; + tmpp = 29717; + move32(); + move32(); + BREAK; + case 320: + tmp = 237412; + tmpp = 32768; + move32(); + move32(); + BREAK; + case 400: + tmp = 247960; + tmpp = 43317; + move32(); + move32(); + BREAK; + case 480: + tmp = 256580; + tmpp = 51936; + move32(); + move32(); + BREAK; + case 600: + tmp = 267128; + tmpp = 62485; + move32(); + move32(); + BREAK; + case 640: + tmp = 270180; + tmpp = 65536; + move32(); + move32(); + BREAK; + case 800: + tmp = 280728; + tmpp = 76085; + move32(); + move32(); + BREAK; + case 960: + tmp = 289348; + tmpp = 84704; + move32(); + move32(); + BREAK; + case 1200: + tmp = 299896; + tmpp = 95253; + move32(); + move32(); + BREAK; + case 1440: + tmp = 308516; + tmpp = 103872; + move32(); + move32(); + BREAK; + case 1800: + tmp = 319064; + tmpp = 114422; + move32(); + move32(); + BREAK; + case 2048: + tmp = 325167; + tmpp = 120523; + move32(); + move32(); + BREAK; + default: + assert( 0 ); + } + + lg_4 = shr( lg, 2 ); + + /* SNR of quadruples for unit step quantizer and lowest possible gain */ + FOR( i = 0; i < lg_4; i++ ) + { + /* normalization */ + s = 15; + move16(); + + tmp16 = norm_l( x[0] ); + if ( x[0] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x[1] ); + if ( x[1] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x[2] ); + if ( x[2] != 0 ) + s = s_min( s, tmp16 ); + + tmp16 = norm_l( x[3] ); + if ( x[3] != 0 ) + s = s_min( s, tmp16 ); + + s = sub( s, 2 ); /* 2 bits headroom */ + + /* calc quadruple energy */ + ener = L_deposit_l( 1 ); + + tmp16 = extract_h( L_shl( x[0], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x[1], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x[2], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + tmp16 = extract_h( L_shl( x[3], s ) ); + ener = L_mac( ener, tmp16, tmp16 ); + + s = shl( sub( x_e, s ), 1 ); + + /* log */ + tmp32 = L_add_sat( BASOP_Util_Log2( ener ), L_shl_sat( L_deposit_l( s ), 25 ) ); /* log2, 6Q25 */ + en[i] = L_add_sat( L_shr( tmp32, 9 ), tmp ); /* 15Q16 */ + move32(); + x += 4; + } + + /* SQ scale: 4 bits / 6 dB per quadruple */ + target = L_mult( 0x3FC8, sub( nbitsSQ, shr( lg, 4 ) ) ); /* 0x3FC8 -> 0.15*log2(10) */ + fac = L_add( 4005789, 0 ); /* -> 18.4f*log2(10); */ + offset = 3997967; /*fac - fac / (float) ( 2 << max_iter )*/ + move32(); + max_iter = 8; + move16(); + /* find offset, resolution similar to SQ gain quantizer resolution (92dB range, 0.719db resolution) */ + FOR( iter = 0; iter < max_iter; iter++ ) + { + fac = L_shr( fac, 1 ); + offset = L_sub( offset, fac ); + ener = L_deposit_l( 0 ); + + FOR( i = 0; i < lg_4; i++ ) + { + tmp32 = L_sub( en[i], offset ); + + /* avoid SV with 1 bin of amp < 0.5f */ + IF( GT_32( tmp32, 0xFF20 ) ) /* 0xFF20 -> 0.3*log2(10); */ + { + ener = L_add( ener, tmp32 ); + } + + /* if SNR is above target -> break and increase offset */ + IF( GT_32( ener, target ) ) + { + offset = L_add( offset, fac ); + BREAK; + } + } + } + + offset = L_sub( L_shr( offset, 1 ), tmpp ); /* tmpp -> minGainInv*log2(10) */ + *gain_e = add( extract_h( offset ), 1 ); + move16(); + offset = L_sub( L_and( offset, 0xFFFF ), 0x10000 ); + tmp16 = extract_h( BASOP_Util_InvLog2( L_shl( offset, 9 ) ) ); + + /* return gain */ + + return tmp16; +} + void tcx_scalar_quantization_fx( Word32 *x, /* i: input coefficients */ Word16 x_e, /* i: exponent */ @@ -1066,51 +1285,444 @@ Word16 tcx_scalar_quantization_rateloop_fx( return sqBits; } -void QuantizeGain( Word16 n, Word16 *pGain, Word16 *pGain_e, Word16 *pQuantizedGain ) +Word16 tcx_scalar_quantization_rateloop_ivas_fx( + Word32 *x, /* i : input coefficients Q = 31 - x_e*/ + Word16 x_e, /* i : exponent Q0*/ + Word16 *xq, /* o : quantized coefficients Q0*/ + Word16 L_frame, /* i : frame length Q0*/ + Word16 *gain, /* i/o: quantization gain Q = gaine_e*/ + Word16 *gain_e, /* i/o: gain exponent Q0*/ + Word16 offset, /* i : rounding offset (deadzone) Q0*/ + Word8 const *memQuantZeros_fx, /* i : coefficients to be set to 0 Q0*/ + Word16 *lastnz_out, /* i/o: last nonzero coeff index Q0*/ + Word16 target, /* i : target number of bits Q0*/ + Word16 *nEncoded, /* o : number of encoded coeff Q0*/ + Word16 *stop, /* i/o: stop param Q0*/ + Word16 sqBits_in_noStop, /* i : number of sqBits as determined in prev. quant. stage, w/o using stop mechanism (ie might exceed target bits) Q0*/ + Word16 sqBits_in, /* i : number of sqBits as determined in prev. quant. stage, using stop mechanism (ie always <= target bits) Q0*/ + Word16 tcxRateLoopOpt, /* i : turns on/off rateloop optimization */ + const Word16 tcxonly, + CONTEXT_HM_CONFIG *hm_cfg, /* i : configuration of the context-based harmonic model */ + const Word16 iter_max, + const Word16 element_mode ) { - Word16 ener, ener_e, enerInv, enerInv_e, gain, gain_e; - Word16 quantizedGain; + Word16 sqBits; + Word16 stopFlag; + Word8 ubfound, lbfound; + Word16 ub, ub_e, lb, lb_e; + Word16 shift, shiftInv; + Word16 iter; + Word16 sqGain, sqGain_e; + Word16 w_lb, w_ub; + const Word16 kDampen = 10; + move16(); + Word16 old_stopFlag; + Word16 old_nEncoded; + Word16 old_sqBits; + Word16 mod_adjust0, mod_adjust1; + Word16 inv_target, inv_target_e; + const Word16 kMargin = 0x7AE1; /* 0.96 */ + move16(); + const Word16 kMarginInv = 0x42AB; /* 1/0.96 (1Q14) */ + move16(); + Word16 tmp, fac1, fac2; Word32 tmp32; -#ifdef BASOP_NOGLOB_DECLARE_LOCAL - Flag Overflow = 0; -#endif + Word16 lastnz, saturated, minSqGain = 0; + move16(); -#ifdef BASOP_NOGLOB - ener = mult_r( shl_o( n, 5, &Overflow ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); -#else - ener = mult_r( shl( n, 5 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); -#endif - ener_e = 15 - 5 - 7; + + /* Init */ + saturated = 0; move16(); - IF( n >= 1024 ) + /* minSqGain = (float) sqrt( (float) NORM_MDCT_FACTOR / (float) L_frame ); in Q14*/ + SWITCH( L_frame ) { - /*reduce precision for avoiding overflow*/ - ener = mult_r( shl( n, 4 ), 26214 /*128.f/NORM_MDCT_FACTOR Q15*/ ); - ener_e = 15 - 4 - 7; + case 80: + minSqGain = 23170; + BREAK; + case 100: + minSqGain = 20724; + BREAK; + case 160: + minSqGain = 16384; + BREAK; + case 200: + minSqGain = 14654; + BREAK; + case 240: + minSqGain = 13377; + BREAK; + case 300: + minSqGain = 11965; + BREAK; + case 320: + minSqGain = 11585; + BREAK; + case 400: + minSqGain = 10362; + BREAK; + case 480: + minSqGain = 9459; + BREAK; + case 600: + minSqGain = 8461; + BREAK; + case 640: + minSqGain = 8192; + BREAK; + case 800: + minSqGain = 7327; + BREAK; + case 960: + minSqGain = 6689; + BREAK; + case 1200: + minSqGain = 5983; + BREAK; + case 1440: + minSqGain = 5461; + BREAK; + case 1800: + minSqGain = 4885; + BREAK; + case 2048: + minSqGain = 4579; + BREAK; + default: + assert( 0 ); } - BASOP_Util_Sqrt_InvSqrt_MantExp( ener, ener_e, &ener, &ener_e, &enerInv, &enerInv_e ); + move16(); + sqGain = *gain; + move16(); + sqGain_e = *gain_e; + move16(); + stopFlag = *stop; + move16(); + ubfound = 0; + move16(); + lbfound = 0; + move16(); + shift = 0x41DE; /* 10^(1/80), 1Q14 */ + move16(); + shiftInv = 0x78D7; /* 10^(-1/40) */ + move16(); + lb = lb_e = 0; + move16(); + ub = ub_e = 0; + move16(); + w_lb = 0; + move16(); + w_ub = 0; + move16(); + lastnz = *lastnz_out; + move16(); + old_stopFlag = stopFlag; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_sqBits = sqBits_in_noStop; + move16(); - gain = mult( *pGain, ener ); - gain_e = *pGain_e + ener_e; + sqBits = sqBits_in; + move16(); - assert( gain > 0 ); + mod_adjust0 = extract_l( L_shr( L_max( 0x10000, L_sub( 0x24CCD, L_mult( 0x0052, target ) ) ), 3 ) ); /* 2Q13 */ + mod_adjust1 = div_s( 0x2000, mod_adjust0 ); /* 0Q15 */ - /* quantize gain with step of 0.714 dB */ - quantizedGain = add( round_fx( BASOP_Util_Log2( L_deposit_h( gain ) ) ), shl( gain_e, 9 ) ); /* 6Q9 */ - quantizedGain = mult( quantizedGain, 0x436E ); /* 10Q5; 0x436E -> 28/log2(10) (4Q11) */ - quantizedGain = shr( add( quantizedGain, 0x10 ), 5 ); /* round */ + inv_target_e = 15; + move16(); + inv_target = Inv16( target, &inv_target_e ); - if ( quantizedGain < 0 ) - { - quantizedGain = 0; - move16(); - } + fac1 = shl( mult( mult( kMarginInv, mod_adjust0 ), inv_target ), 1 ); /* 2Q13 */ + fac2 = mult( mult( kMargin, mod_adjust1 ), inv_target ); - if ( quantizedGain > 127 ) + /* Loop */ + FOR( iter = 0; iter < iter_max; iter++ ) { - quantizedGain = 127; - move16(); - } + IF( GE_16( tcxRateLoopOpt, 2 ) ) + { + /* Ajust sqGain */ + IF( stopFlag != 0 ) + { + lbfound = 1; + move16(); + lb = sqGain; + move16(); + lb_e = sqGain_e; + move16(); + w_lb = add( sub( stopFlag, target ), kDampen ); + saturated = 0; + move16(); + IF( ubfound != 0 ) + { + /* common exponent for addition */ + sqGain_e = s_max( lb_e, ub_e ); + + /* multiply and add */ + tmp32 = L_shr( L_mult( lb, w_ub ), sub( sqGain_e, lb_e ) ); + tmp32 = L_add( tmp32, L_shr( L_mult( ub, w_lb ), sub( sqGain_e, ub_e ) ) ); + + /* convert to normalized 16 bit */ + tmp = norm_l( tmp32 ); +#ifdef BASOP_NOGLOB + sqGain = round_fx_sat( L_shl( tmp32, tmp ) ); +#else + sqGain = round_fx( L_shl( tmp32, tmp ) ); +#endif + sqGain_e = sub( sqGain_e, tmp ); + + /* divide */ + sqGain = BASOP_Util_Divide1616_Scale( sqGain, add( w_ub, w_lb ), &tmp ); + sqGain_e = add( sqGain_e, tmp ); + } + ELSE + { + tmp = round_fx_sat( L_shl_sat( L_mult( stopFlag, fac1 ), add( inv_target_e, 15 ) ) ); + sqGain = mult( sqGain, sub( tmp, sub( mod_adjust0, 0x2000 ) ) ); + sqGain = normalize16( sqGain, &sqGain_e ); + sqGain_e = add( sqGain_e, 2 ); + } + } + ELSE IF( saturated == 0 ) + { + ubfound = 1; + move16(); + ub = sqGain; + move16(); + ub_e = sqGain_e; + move16(); + w_ub = add( sub( target, sqBits ), kDampen ); + + IF( lbfound != 0 ) + { + /* common exponent for addition */ + sqGain_e = s_max( lb_e, ub_e ); + + /* multiply and add */ + tmp32 = L_shr( L_mult( lb, w_ub ), sub( sqGain_e, lb_e ) ); + tmp32 = L_add( tmp32, L_shr( L_mult( ub, w_lb ), sub( sqGain_e, ub_e ) ) ); + + /* convert to normalized 16 bit */ + tmp = norm_l( tmp32 ); +#ifdef BASOP_NOGLOB + sqGain = round_fx_sat( L_shl_sat( tmp32, tmp ) ); +#else + sqGain = round_fx( L_shl( tmp32, tmp ) ); +#endif + sqGain_e = sub( sqGain_e, tmp ); + + /* divide */ + sqGain = BASOP_Util_Divide1616_Scale( sqGain, add( w_ub, w_lb ), &tmp ); + sqGain_e = add( sqGain_e, tmp ); + } + ELSE + { + tmp = round_fx( L_shl( L_mult( sqBits, fac2 ), add( inv_target_e, 15 ) ) ); + sqGain = mult( sqGain, sub( tmp, add( mod_adjust1, (Word16) 0x8000 ) ) ); + sqGain = normalize16( sqGain, &sqGain_e ); + } + + Word16 shift_tmp = s_max( sqGain_e, 1 ); + test(); + IF( LT_16( shl( sqGain, sub( sqGain_e, shift_tmp ) ), shl( minSqGain, sub( 1, shift_tmp ) ) ) && EQ_16( tcxRateLoopOpt, 3 ) ) + { + sqGain = minSqGain; + move16(); + sqGain_e = 1; + move16(); + saturated = 1; + move16(); + } + } + ELSE + { + break; /* we cannot go any lower anyway*/ + } + } + ELSE /* tcxRateLoopOpt != 2 */ + { + + /* Ajust sqGain */ + IF( stopFlag != 0 ) + { + lbfound = 1; + move16(); + lb = sqGain; + move16(); + lb_e = sqGain_e; + move16(); + + IF( ubfound != 0 ) + { + sqGain = mult( lb, ub ); + sqGain_e = add( lb_e, ub_e ); + sqGain = Sqrt16( sqGain, &sqGain_e ); + } + ELSE + { + shift = shl( mult( shift, shift ), 1 ); + shiftInv = mult( shiftInv, shiftInv ); + + sqGain = mult( sqGain, shift ); + sqGain = normalize16( sqGain, &sqGain_e ); + sqGain_e = add( sqGain_e, 1 ); + } + } + ELSE + { + ubfound = 1; + move16(); + ub = sqGain; + move16(); + ub_e = sqGain_e; + move16(); + + IF( lbfound != 0 ) + { + sqGain = mult( lb, ub ); + sqGain_e = add( lb_e, ub_e ); + sqGain = Sqrt16( sqGain, &sqGain_e ); + } + ELSE + { + sqGain = mult( sqGain, shiftInv ); + sqGain = normalize16( sqGain, &sqGain_e ); + + shift = shl( mult( shift, shift ), 1 ); + shiftInv = mult( shiftInv, shiftInv ); + } + } + } + + /* Quantize spectrum */ + tcx_scalar_quantization_ivas_fx( x, x_e, xq, L_frame, sqGain, sqGain_e, offset, memQuantZeros_fx, tcxonly ); + + /* Estimate bitrate */ + stopFlag = 1; + move16(); + if ( tcxRateLoopOpt > 0 ) + { + stopFlag = 0; + move16(); + } + + IF( GT_16( element_mode, EVS_MONO ) ) + { + sqBits = RCcontextMapping_encode2_estimate_no_mem_s17_LCS( xq, L_frame, &lastnz, nEncoded, target, &stopFlag, 0, hm_cfg ); + } + ELSE + { + sqBits = ACcontextMapping_encode2_estimate_no_mem_s17_LC_fx( xq, L_frame, + &lastnz, + nEncoded, target, &stopFlag, + hm_cfg ); + } + + IF( GE_16( tcxRateLoopOpt, 1 ) ) + { + test(); + test(); + test(); + test(); + test(); + test(); + IF( ( ( GE_16( *nEncoded, old_nEncoded ) ) && ( GE_16( stopFlag, old_stopFlag ) ) ) || + ( ( GT_16( *nEncoded, old_nEncoded ) ) && ( ( stopFlag == 0 ) && ( old_stopFlag > 0 ) ) ) || + ( ( stopFlag == 0 ) && ( old_stopFlag == 0 ) ) ) + { + *gain = sqGain; + move16(); + *gain_e = sqGain_e; + move16(); + old_nEncoded = *nEncoded; + move16(); + old_stopFlag = stopFlag; + move16(); + old_sqBits = sqBits; + move16(); + *lastnz_out = lastnz; + move16(); + } + } + } /* for ( iter=0 ; iter 0 ); + + /* quantize gain with step of 0.714 dB */ + quantizedGain = add( round_fx( BASOP_Util_Log2( L_deposit_h( gain ) ) ), shl( gain_e, 9 ) ); /* 6Q9 */ + quantizedGain = mult( quantizedGain, 0x436E ); /* 10Q5; 0x436E -> 28/log2(10) (4Q11) */ + quantizedGain = shr( add( quantizedGain, 0x10 ), 5 ); /* round */ + + if ( quantizedGain < 0 ) + { + quantizedGain = 0; + move16(); + } + + if ( GT_16( quantizedGain, 127 ) ) + { + quantizedGain = 127; + move16(); + } *pQuantizedGain = quantizedGain; move16(); @@ -1824,33 +2436,229 @@ void tcx_encoder_memory_update_fx( move16(); E_UTIL_f_preemph2( Q_new - 1, synth - M, preemph, add( M, L_frame_glob ), &tmp ); - Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn, M ); - Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn2, M ); - Copy( synth + sub( L_frame_glob, L_SYN_MEM ), LPDmem->mem_syn_r, L_SYN_MEM ); + Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn, M ); + Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn2, M ); + Copy( synth + sub( L_frame_glob, L_SYN_MEM ), LPDmem->mem_syn_r, L_SYN_MEM ); + + test(); + IF( st->tcxonly == 0 || LE_16( L_frame_glob, L_FRAME16k ) ) + { + /* Update excitation */ + IF( LT_16( L_frame_glob, L_EXC_MEM ) ) + { + Copy( LPDmem->old_exc + L_frame_glob, LPDmem->old_exc, sub( L_EXC_MEM, L_frame_glob ) ); + Residu3_fx( A, synth, LPDmem->old_exc + sub( L_EXC_MEM, L_frame_glob ), L_frame_glob, 1 ); + } + ELSE + { + Residu3_fx( A, synth + sub( L_frame_glob, L_EXC_MEM ), LPDmem->old_exc, L_EXC_MEM, 1 ); + } + } +} + +#ifdef IVAS_FLOAT_FIXED +void tcx_encoder_memory_update_ivas_fx( + Word16 *wsig, /* i : target weighted signal, Q_new */ + Word16 *xn_buf, /* i/o: mdct output buffer/time domain weigthed synthesis, Q_new */ + Word16 L_frame_glob, /* i: global frame length */ + const Word16 *Ai, /* i: Unquantized (interpolated) LPC coefficients, Q12 */ + const Word16 *A, /* i: Quantized LPC coefficients, Q = 14 - norm_s(A[0]) */ + Word16 preemph, /* i: preemphasis factor, Q15 */ + LPD_state *LPDmem, /* i/o: coder memory state */ + Encoder_State *st, + Word16 *synthout, /* Q_new */ + Word16 Q_new ) +{ + Word16 tmp; + Word16 buf[1 + M + LFAC + L_FRAME_PLUS]; + Word16 *synth; + + + /* Output synth */ + Copy( xn_buf, synthout, L_frame_glob ); + + + /* Update synth */ + synth = buf + M + 1; + Copy( LPDmem->syn, buf, M + 1 ); + + Copy( xn_buf, synth, L_frame_glob ); + Copy( synth + sub( L_frame_glob, M + 1 ), LPDmem->syn, M + 1 ); + + IF( st->tcxonly == 0 ) + { + /* Update weighted synthesis */ + Residu3_fx( Ai + imult1616( sub( st->nb_subfr, 1 ), ( M + 1 ) ), synth + sub( L_frame_glob, 1 ), &tmp, 1, 0 ); + LPDmem->mem_w0 = sub( wsig[sub( L_frame_glob, 1 )], tmp ); + move16(); + } + + + /* Emphasis of synth -> synth_pe */ + tmp = synth[-( M + 1 )]; + move16(); + E_UTIL_f_preemph2( Q_new - 1, synth - M, preemph, add( M, L_frame_glob ), &tmp ); + + Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn, M ); + Copy( synth + sub( L_frame_glob, M ), LPDmem->mem_syn2, M ); + Copy( synth + sub( L_frame_glob, L_SYN_MEM ), LPDmem->mem_syn_r, L_SYN_MEM ); + + test(); + IF( st->tcxonly == 0 || LE_16( L_frame_glob, L_FRAME16k ) ) + { + /* Update excitation */ + IF( LT_16( L_frame_glob, L_EXC_MEM ) ) + { + Copy( LPDmem->old_exc + L_frame_glob, LPDmem->old_exc, sub( L_EXC_MEM, L_frame_glob ) ); + Residu3_fx( A, synth, LPDmem->old_exc + sub( L_EXC_MEM, L_frame_glob ), L_frame_glob, 1 ); + } + ELSE + { + Residu3_fx( A, synth + sub( L_frame_glob, L_EXC_MEM ), LPDmem->old_exc, L_EXC_MEM, 1 ); + } + } +} +#endif + + +/*--------------------------------------------------------------- + * Residual Quantization + *--------------------------------------------------------------*/ + +/* Returns: number of bits used (including "bits") Q0 */ +Word16 tcx_ari_res_Q_spec_fx( + const Word32 x_orig[], /* i: original spectrum Q31-e */ + Word16 x_orig_e, /* i: original spectrum exponent Q0 */ + const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ + Word32 x_Q[], /* i/o: quantized spectrum Q31-e */ + Word16 x_Q_e, /* i: quantized spectrum exponent Q0 */ + Word16 L_frame, /* i: number of lines Q0 */ + Word16 gain, /* i: TCX gain Q15-e */ + Word16 gain_e, /* i: TCX gain exponent Q0 */ + Word16 prm[], /* o: bit-stream Q0 */ + Word16 target_bits, /* i: number of bits available Q0 */ + Word16 bits, /* i: number of bits used so far Q0 */ + Word16 deadzone, /* i: quantizer deadzone Q15 */ + const Word16 x_fac[] /* i: spectrum post-quantization factors Q14 */ +) +{ + Word16 i, j, num_zeros; + Word16 zeros[L_FRAME_PLUS]; + Word16 fac_p, sign; + Word32 thres, x_Q_m, x_Q_p; + Word32 L_tmp, L_tmp2; + Word16 s, s2; + + + /* Limit the number of residual bits */ + target_bits = s_min( target_bits, NPRM_RESQ ); + + + /* Requantize the spectrum line-by-line */ + /* fac_m = deadzone * 0.5f; + fac_p = 0.5f - fac_m; */ + num_zeros = 0; + move16(); + + s = sub( add( gain_e, x_Q_e ), x_orig_e ); + FOR( i = 0; i < L_frame; i++ ) + { + IF( GE_16( bits, target_bits ) ) /* no bits left */ + { + BREAK; + } + + IF( x_Q[i] != 0 ) + { + sign = x_fac[i]; + move16(); + if ( signs[i] != 0 ) + sign = negate( sign ); + + /* x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; */ + + L_tmp = L_mult( sign, deadzone ); /* sign*deadzone/2 in Q31 */ + x_Q_m = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + L_tmp = L_mac( L_tmp, sign, (Word16) 0x8000 ); /* sign*(deadzone-1)/2 in Q31 */ + x_Q_p = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + /* if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) */ + L_tmp = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_m, gain ), s ) ) ); + L_tmp2 = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_p, gain ), s ) ) ); + + IF( LT_32( L_tmp, L_tmp2 ) ) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + move32(); + prm[bits] = 0; + move16(); + } + ELSE /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + move32(); + prm[bits] = 1; + move16(); + } + bits = add( bits, 1 ); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add( num_zeros, 1 ); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r( 1417339264l /*2*0.33f Q31*/, deadzone, 21627 /*2*0.33f Q15*/ ); /* Q16 */ + target_bits = sub( target_bits, 1 ); /* reserve 1 bit for the check below */ + + s = sub( gain_e, x_orig_e ); + s2 = sub( x_Q_e, 1 ); + FOR( j = 0; j < num_zeros; j++ ) + { + IF( GE_16( bits, target_bits ) ) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + thres = L_mult( fac_p, x_fac[i] ); /* Q31 */ - test(); - IF( st->tcxonly == 0 || LE_16( L_frame_glob, L_FRAME16k ) ) - { - /* Update excitation */ - IF( LT_16( L_frame_glob, L_EXC_MEM ) ) + IF( GT_32( L_abs( x_orig[i] ), L_shl( Mpy_32_16_1( thres, gain ), s ) ) ) { - Copy( LPDmem->old_exc + L_frame_glob, LPDmem->old_exc, sub( L_EXC_MEM, L_frame_glob ) ); - Residu3_fx( A, synth, LPDmem->old_exc + sub( L_EXC_MEM, L_frame_glob ), L_frame_glob, 1 ); + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = sub( 1, signs[i] ); + move16(); + bits = add( bits, 1 ); + + L_tmp = L_shr( thres, s2 ); + if ( signs[i] ) + L_tmp = L_negate( L_tmp ); + x_Q[i] = L_tmp; + move32(); } ELSE { - Residu3_fx( A, synth + sub( L_frame_glob, L_EXC_MEM ), LPDmem->old_exc, L_EXC_MEM, 1 ); + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); } } -} -/*--------------------------------------------------------------- - * Residual Quantization - *--------------------------------------------------------------*/ + return bits; +} -/* Returns: number of bits used (including "bits") Q0 */ -Word16 tcx_ari_res_Q_spec_fx( +Word16 tcx_ari_res_Q_spec_ivas_fx( const Word32 x_orig[], /* i: original spectrum Q31-e */ Word16 x_orig_e, /* i: original spectrum exponent Q0 */ const Word16 signs[], /* i: signs (x_orig[.]<0) Q0 */ @@ -1883,6 +2691,102 @@ Word16 tcx_ari_res_Q_spec_fx( fac_p = 0.5f - fac_m; */ num_zeros = 0; move16(); + s = sub( add( gain_e, x_Q_e ), x_orig_e ); + IF( x_fac == NULL ) + { + FOR( i = 0; i < L_frame; ++i ) + { + IF( GE_16( bits, target_bits ) ) /* no bits left */ + { + BREAK; + } + + IF( x_Q[i] != 0 ) + { + sign = shl( sub( 1, shl( signs[i], 1 ) ), Q14 ); + move16(); + + /* x_Q_m = x_Q[i] - sign*fac_m; + x_Q_p = x_Q[i] + sign*fac_p; */ + + L_tmp = L_mult( sign, deadzone ); /* sign*deadzone/2 in Q31 */ + x_Q_m = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + L_tmp = L_mac( L_tmp, sign, (Word16) 0x8000 ); /* sign*(deadzone-1)/2 in Q31 */ + x_Q_p = L_sub( x_Q[i], L_shr( L_tmp, x_Q_e ) ); + + /* if (fabs(x_orig[i] - gain * x_Q_m) < fabs(x_orig[i] - gain * x_Q_p)) */ + L_tmp = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_m, gain ), s ) ) ); + L_tmp2 = L_abs( L_sub( x_orig[i], L_shl( Mpy_32_16_1( x_Q_p, gain ), s ) ) ); + + IF( LT_32( L_tmp, L_tmp2 ) ) /* Decrease magnitude */ + { + x_Q[i] = x_Q_m; + move32(); + prm[bits] = 0; + move16(); + } + ELSE /* Increase magnitude */ + { + x_Q[i] = x_Q_p; + move32(); + prm[bits] = 1; + move16(); + } + bits = add( bits, 1 ); + } + ELSE + { + zeros[num_zeros] = i; + move16(); + num_zeros = add( num_zeros, 1 ); + } + } + + /* Requantize zeroed-lines of the spectrum */ + fac_p = msu_r( 1417339264l /*2*0.33f Q31*/, deadzone, 21627 /*2*0.33f Q15*/ ); /* Q16 */ + target_bits = sub( target_bits, 1 ); /* reserve 1 bit for the check below */ + + s = sub( gain_e, x_orig_e ); + s2 = sub( x_Q_e, 1 ); + FOR( j = 0; j < num_zeros; j++ ) + { + IF( GE_16( bits, target_bits ) ) /* 1 or 0 bits left */ + { + BREAK; + } + + i = zeros[j]; + move16(); + + thres = L_shl( fac_p, Q15 ); /* Q31 */ + + IF( GT_32( L_abs( x_orig[i] ), L_shl( Mpy_32_16_1( thres, gain ), s ) ) ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = sub( 1, signs[i] ); + move16(); + bits = add( bits, 1 ); + + L_tmp = L_shr( thres, s2 ); + if ( signs[i] ) + L_tmp = L_negate( L_tmp ); + x_Q[i] = L_tmp; + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + } + } + + return bits; + } s = sub( add( gain_e, x_Q_e ), x_orig_e ); FOR( i = 0; i < L_frame; i++ ) @@ -2210,6 +3114,175 @@ Word16 tcx_res_Q_spec_fx( return bits; } + +Word16 tcx_res_Q_spec_ivas_fx( + Word32 *x_orig, + Word16 x_orig_e, + Word32 *x_Q, + Word16 x_Q_e, + Word16 L_frame, + Word16 sqGain, + Word16 sqGain_e, + Word16 *prm, + Word16 sqTargetBits, + Word16 bits, + Word16 sq_round, + const Word16 lf_deemph_factors[] /* 1Q14 */ +) +{ + Word16 i; + Word16 fac_m, fac_p; + Word32 tmp1, tmp2; + Word16 s, s2, lf_deemph_factor; + Word16 c; + Word32 thres; + + + /* Limit the number of residual bits */ + sqTargetBits = s_min( sqTargetBits, NPRM_RESQ ); + + /* Requantize the spectrum line-by-line */ + fac_m = shr( sq_round, 1 ); + fac_p = sub( 0x4000, fac_m ); + + /* exponent difference of x_orig and x_Q * sqGain */ + s = sub( x_orig_e, add( x_Q_e, sqGain_e ) ); + + lf_deemph_factor = 0x4000; + move16(); + s2 = sub( x_Q_e, 1 ); + + FOR( i = 0; i < L_frame; i++ ) + { + IF( GE_16( bits, sub( sqTargetBits, kMaxEstimatorUndershoot ) ) ) + { + fac_m = 0; + move16(); + fac_p = 0; + move16(); + + IF( GE_16( bits, s_min( NPRM_RESQ, add( sqTargetBits, kMaxEstimatorOvershoot ) ) ) ) + { + BREAK; + } + } + + test(); + test(); + IF( ( x_Q[i] != 0 ) && ( ( lf_deemph_factors == NULL ) || ( GT_16( lf_deemph_factors[i], 0x2000 ) ) ) ) + { + tmp1 = L_add( x_orig[i], 0 ); + tmp2 = Mpy_32_16_1( x_Q[i], sqGain ); + if ( s > 0 ) + tmp2 = L_shr( tmp2, s ); + if ( s < 0 ) + tmp1 = L_shl( tmp1, s ); + + if ( lf_deemph_factors != NULL ) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + IF( LT_32( tmp1, tmp2 ) ) + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + + if ( x_Q[i] > 0 ) + tmp1 = L_mult( fac_m, lf_deemph_factor ); + if ( x_Q[i] < 0 ) + tmp1 = L_mult( fac_p, lf_deemph_factor ); + x_Q[i] = L_sub( x_Q[i], L_shr( tmp1, s2 ) ); + move32(); + } + ELSE + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + if ( x_Q[i] > 0 ) + tmp1 = L_mult( fac_p, lf_deemph_factor ); + if ( x_Q[i] < 0 ) + tmp1 = L_mult( fac_m, lf_deemph_factor ); + x_Q[i] = L_add( x_Q[i], L_shr( tmp1, s2 ) ); + move32(); + } + } + } + + /*Quantize zeroed-line of the spectrum*/ + c = sub( 21627 /*0.66f Q15*/, mult_r( sq_round, 21627 /*0.66f Q15*/ ) ); + + FOR( i = 0; i < L_frame; i++ ) + { + IF( GE_16( bits, sub( sqTargetBits, 2 ) ) ) + { + BREAK; + } + + test(); + test(); + IF( ( x_Q[i] == 0 ) && ( ( lf_deemph_factors == NULL ) || ( GT_16( lf_deemph_factors[i], 0x2000 ) ) ) ) + { + if ( lf_deemph_factors != NULL ) + { + lf_deemph_factor = lf_deemph_factors[i]; + move16(); + } + + thres = L_mult( c, lf_deemph_factor ); // Q31 + Word16 shift_tmp = s_max( sqGain_e, x_orig_e ); + + tmp1 = Mpy_32_16_1( thres, sqGain ); + + IF( GT_32( L_shl( x_orig[i], sub( x_orig_e, shift_tmp ) ), L_shl( tmp1, sub( sqGain_e, shift_tmp ) ) ) ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + x_Q[i] = L_shl( thres, sub( 1, x_Q_e ) ); + move32(); + } + ELSE IF( L_add( L_shl( x_orig[i], sub( x_orig_e, shift_tmp ) ), L_shl( tmp1, sub( sqGain_e, shift_tmp ) ) ) < 0 ) + { + prm[bits] = 1; + move16(); + bits = add( bits, 1 ); + + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + + x_Q[i] = L_shl( L_negate( thres ), sub( 1, x_Q_e ) ); + move32(); + } + ELSE + { + prm[bits] = 0; + move16(); + bits = add( bits, 1 ); + } + } + } + + /*Be sure that every possible bits are initialized*/ + FOR( i = bits; i < NPRM_RESQ; i++ ) + { + prm[i] = 0; + move16(); + } + + return bits; +} + void ProcessIGF_fx( IGF_ENC_INSTANCE_HANDLE const hInstance, /**< in: instance handle of IGF Encoder */ Encoder_State *st, /**< in: Encoder state */ diff --git a/lib_enc/vbr_average_rate.c b/lib_enc/vbr_average_rate.c index a3dc254d02be6ece3a4c405043fcae5a85c60bdc..0f758041af4487db951c4ca63d28a4e684a9dbda 100644 --- a/lib_enc/vbr_average_rate.c +++ b/lib_enc/vbr_average_rate.c @@ -52,7 +52,7 @@ * * SC-VBR update average data rate *------------------------------------------------------------------*/ - +#ifndef IVAS_FLOAT_FIXED void update_average_rate( SC_VBR_ENC_HANDLE hSC_VBR, /* i/o: SC-VBR state structure */ const int32_t core_brate /* i : core bitrate */ @@ -197,3 +197,4 @@ void update_average_rate( return; } +#endif diff --git a/lib_enc/vbr_average_rate_fx.c b/lib_enc/vbr_average_rate_fx.c index fe5766eea883fd5a3fd87d8ce8f7265d06b0c09b..931333ebe264c01ecdf50d5a276127413b5ad34f 100644 --- a/lib_enc/vbr_average_rate_fx.c +++ b/lib_enc/vbr_average_rate_fx.c @@ -51,6 +51,7 @@ void update_average_rate_fx( Word32 L_tmp1, L_tmp2; #ifdef BASOP_NOGLOB_DECLARE_LOCAL Flag Overflow = 0; + move32(); #endif Word16 exp, recip, Qrecip; @@ -61,35 +62,41 @@ void update_average_rate_fx( st->global_avr_rate=0.99*st->global_avr_rate+0.01*st->sum_of_rates. This will avoid veriables growing indefinitely while providing a good long term average rate */ - IF( LT_32( hSC_VBR->frame_cnt_ratewin_fx, 1000 ) ) + IF( LT_32( hSC_VBR->global_frame_cnt, 1000 ) ) { - hSC_VBR->frame_cnt_ratewin_fx = add( hSC_VBR->frame_cnt_ratewin_fx, 1 ); + hSC_VBR->global_frame_cnt = add( hSC_VBR->global_frame_cnt, 1 ); + move16(); /*st->global_avr_rate = (st->global_avr_rate * (st->global_frame_cnt-1) + st->sum_of_rates) / st->global_frame_cnt; */ - exp = norm_s( hSC_VBR->frame_cnt_ratewin_fx ); - tmp = shl( hSC_VBR->frame_cnt_ratewin_fx, exp ); + exp = norm_s( hSC_VBR->global_frame_cnt ); + tmp = shl( hSC_VBR->global_frame_cnt, exp ); recip = div_s( 16384, tmp ); - Qrecip = 15 - ( exp - 14 ); + Qrecip = sub( 15, sub( exp, 14 ) ); - IF( GT_32( hSC_VBR->frame_cnt_ratewin_fx, 1 ) ) + IF( GT_32( hSC_VBR->global_frame_cnt, 1 ) ) { - tmp = div_s( sub( hSC_VBR->frame_cnt_ratewin_fx, 1 ), hSC_VBR->frame_cnt_ratewin_fx ); /*Q15*/ - L_tmp1 = Mult_32_16( hSC_VBR->global_avr_rate_fx, tmp ); /* Q13*Q15 = Q13 */ + tmp = div_s( sub( hSC_VBR->global_frame_cnt, 1 ), hSC_VBR->global_frame_cnt ); /*Q15*/ + L_tmp1 = Mult_32_16( hSC_VBR->global_avr_rate_fx, tmp ); /* Q13*Q15 = Q13 */ L_tmp2 = Mult_32_16( hSC_VBR->sum_of_rates_fx, recip ); /*Q13*Qrecip = 13+Qrecip+1-16 = Qrecip-2 */ - hSC_VBR->global_avr_rate_fx = L_add( L_tmp1, L_shl( L_tmp2, 13 - ( Qrecip - 2 ) ) ); /*Q13 */ + hSC_VBR->global_avr_rate_fx = L_add( L_tmp1, L_shl( L_tmp2, sub( 13, ( sub( Qrecip, 2 ) ) ) ) ); /*Q13 */ + move32(); } ELSE { hSC_VBR->global_avr_rate_fx = hSC_VBR->sum_of_rates_fx; /*handle the first frame*/ + move32(); } /* Q13 */ } ELSE { - /* st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; */ + /* st->global_avr_rate = 0.01f * st->sum_of_rates + 0.99f * st->global_avr_rate; + 0.01f=328 (Q15) , .99f=32441 (Q15) + */ hSC_VBR->global_avr_rate_fx = L_add( Mult_32_16( hSC_VBR->sum_of_rates_fx, 328 ), Mult_32_16( hSC_VBR->global_avr_rate_fx, 32441 ) ); /*Q13 */ + move32(); } @@ -97,6 +104,7 @@ void update_average_rate_fx( { /* st->sum_of_rates = (float) (RATEWIN * VBR_ADR_MAX_TARGET * 10); */ hSC_VBR->sum_of_rates_fx = L_shl( L_mult0( RATEWIN, VBR_ADR_MAX_TARGET_x10_Q1 ), 12 ); /*Q13 */ + move32(); } /* target = VBR_ADR_MAX_TARGET * 10 * RATEWIN; */ @@ -107,6 +115,7 @@ void update_average_rate_fx( /* Check the vad snr values to table the noisey/not noisey decision */ test(); + /*67=17152 (Q8)*/ IF( LT_16( hSC_VBR->SNR_THLD_fx, 17152 ) ) /*Q8 */ /* Currently in QFF mode. The bumpup thresholds are slightly relaxed for noisy speech. */ { @@ -114,7 +123,9 @@ void update_average_rate_fx( Use 3.5 steps to quickly ramp up the rate control to reduce the settling time */ /* st->SNR_THLD += 3.5f; */ + /*896=3.5 (Q8)*/ hSC_VBR->SNR_THLD_fx = add( hSC_VBR->SNR_THLD_fx, 896 ); /*Q8 */ + move16(); } ELSE IF( hSC_VBR->mode_QQF == 0 && GT_32( hSC_VBR->sum_of_rates_fx, target_fx ) ) /* Now SNR_THLD is in the max allowed. Sill the global average is higher and last RATEWIN frames have a higher agerage than the target rate. Now slightly @@ -135,6 +146,7 @@ void update_average_rate_fx( move16(); /* This will be triggered only if the gloabl average rate is considerablly higher than the target rate. Keep a higher threshold to avoid short term rate increases over the target rate. */ + /* 3440640=420.0f Q(13) */ IF( GT_32( hSC_VBR->global_avr_rate_fx, L_add( target_fx, 3440640 ) ) ) /* Last resort rate control. This is a safer rate control mechanism by increasing NELPS */ { hSC_VBR->Last_Resort = 1; @@ -175,19 +187,20 @@ void update_average_rate_fx( move16(); } ELSE - { + { /*15360=60 (Q8)*/ IF( GE_16( hSC_VBR->SNR_THLD_fx, 15360 ) ) - { + { /*384=1.5 (Q8)*/ hSC_VBR->SNR_THLD_fx = sub( hSC_VBR->SNR_THLD_fx, 384 ); /*Q8 */ + move16(); } ELSE - { + { /*15360=60 (Q8)*/ hSC_VBR->SNR_THLD_fx = 15360; move16(); } } } - + /*983040=120 (Q13)*/ IF( LT_32( hSC_VBR->global_avr_rate_fx, L_sub( target_fx, 983040 ) ) ) /* In QFF mode and global rate is less than target rate-0.2kbps. We can send some Q frames to F frames to improve the quality */ { @@ -208,6 +221,7 @@ void update_average_rate_fx( L_tmp = L_mult0( RATEWIN, VBR_ADR_MAX_TARGET_x10_Q1 ); L_tmp = L_shl( L_tmp, 12 ); L_tmp = L_sub( avratetarg_fx, L_tmp ); + /*27307=(1000/(RATEWIN))Q14 */ tmp = extract_h( L_shl( Mult_32_16( L_tmp, 27307 ), 4 ) ); hSC_VBR->pattern_m = tmp; move16(); @@ -234,13 +248,13 @@ void update_average_rate_fx( } hSC_VBR->sum_of_rates_fx = 0; - move16(); + move32(); hSC_VBR->numactive = 0; move16(); } hSC_VBR->numactive = add( hSC_VBR->numactive, 1 ); - + move16(); /* sum the total number of bits (in kbytes) * 10 here */ /*st->sum_of_rates += (hSC_VBR->core_brate / 1000.0f) * 10; */ L_tmp = L_shl( Mult_32_16( core_brate_fx, 20972 ), 7 ); @@ -249,6 +263,6 @@ void update_average_rate_fx( #else hSC_VBR->sum_of_rates_fx = L_add( hSC_VBR->sum_of_rates_fx, L_tmp ); #endif - + move32(); return; } diff --git a/lib_enc/voiced_enc.c b/lib_enc/voiced_enc.c index 08d1efefbba6698b6f41709f33dc41c5e41946d5..183ec84817e3ec0beedf5087e2417da11ae46f9a 100644 --- a/lib_enc/voiced_enc.c +++ b/lib_enc/voiced_enc.c @@ -1155,10 +1155,17 @@ void sc_vbr_enc_init( hSC_VBR->set_ppp_generic = 0; hSC_VBR->Q_to_F = 0; - hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ +#ifndef IVAS_FLOAT_FIXED hSC_VBR->sum_of_rates = 0.0f; /* sum of the rates of past 600 active frames*/ hSC_VBR->global_avr_rate = 0.0f; /* global rate upto current time. recorded a (rate in kbps) *6000*/ - hSC_VBR->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ +#else + hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ + move32(); + hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + move32(); +#endif + hSC_VBR->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ hSC_VBR->rate_control = 0; hSC_VBR->SNR_THLD = 67.0f; diff --git a/lib_enc/voiced_enc_fx.c b/lib_enc/voiced_enc_fx.c index b9e0b9c425c7dcbf19ffd794b99f6686696ab86d..cf08ebe5af47d25336b81e8abc4dc077fc654f87 100644 --- a/lib_enc/voiced_enc_fx.c +++ b/lib_enc/voiced_enc_fx.c @@ -1688,10 +1688,11 @@ void sc_vbr_enc_init_fx( hSC_VBR->Q_to_F = 0; move16(); - hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ - hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ - hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ - hSC_VBR->frame_cnt_ratewin_fx = 0; /* 600 active frame block count. Used to update the global rate*/ + hSC_VBR->numactive = 0; /* keep the count of the frames inside current 600 frame bloack.*/ + hSC_VBR->sum_of_rates_fx = 0; /* sum of the rates of past 600 active frames*/ + hSC_VBR->global_avr_rate_fx = 0; /* global rate upto current time. recorded a (rate in kbps) *6000*/ + hSC_VBR->global_frame_cnt = 0; /* 600 active frame block count. Used to update the global rate*/ + move16(); hSC_VBR->rate_control = 0; move16(); hSC_VBR->SNR_THLD_fx = SNR_THLD_FX_Q8; diff --git a/lib_rend/ivas_allrad_dec.c b/lib_rend/ivas_allrad_dec.c index 6b780f9bb46d43fc29608b5690e9f5b00ff00f90..09e2a09340100742178ed12ad2a117656e48deb0 100644 --- a/lib_rend/ivas_allrad_dec.c +++ b/lib_rend/ivas_allrad_dec.c @@ -1,3 +1,4 @@ + /****************************************************************************************************** (C) 2022-2024 IVAS codec Public Collaboration with portions copyright Dolby International AB, Ericsson AB, @@ -166,9 +167,9 @@ ivas_error ivas_sba_get_hoa_dec_matrix( #else #define TEMP_VAL 1963413621 // Q37 (1.f / num_td) ivas_error ivas_sba_get_hoa_dec_matrix_fx( - const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ - Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ - const Word16 ambisonics_order /* i : Ambisonics order */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ + Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix, Q29 */ + const Word16 ambisonics_order /* i : Ambisonics order */ ) { Word16 i, j, k; diff --git a/lib_rend/ivas_dirac_ana.c b/lib_rend/ivas_dirac_ana.c index ec9a05dbd79a1c2dcd639cb3f528a5bd82921aa2..2b2f9cc1ce6cda33dddec8b86962ad8d33c95492 100644 --- a/lib_rend/ivas_dirac_ana.c +++ b/lib_rend/ivas_dirac_ana.c @@ -379,10 +379,10 @@ void ivas_dirac_ana_close( #ifdef IVAS_FLOAT_FIXED void ivas_dirac_ana_fx( - DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ - Word32 data_fx[][L_FRAME48k], /* i/o: Input / transport audio signals */ - const Word16 input_frame, /* i : Input frame size */ - const Word16 nchan_transport /* i : Number of transport channels */ + DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ + Word32 data_fx[][L_FRAME48k], /* i/o: Input / transport audio signals, Q7 */ + const Word16 input_frame, /* i : Input frame size */ + const Word16 nchan_transport /* i : Number of transport channels */ ) { Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS]; @@ -442,12 +442,12 @@ void ivas_dirac_ana( /* Estimate MASA parameters from the SBA signals */ static void ivas_dirac_param_est_ana_fx( DIRAC_ANA_HANDLE hDirAC, - Word32 data_fx[][L_FRAME48k], - Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], - Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], + Word32 data_fx[][L_FRAME48k], /* Q7 */ + Word32 elevation_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q22 */ + Word32 azimuth_m_values[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q22 */ + Word32 energyRatio[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Q30 */ + Word32 spreadCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Qx */ + Word32 surroundingCoherence[MAX_PARAM_SPATIAL_SUBFRAMES][MASA_FREQUENCY_BANDS], /* Qx */ const Word16 input_frame ) { Word32 reference_power_fx[CLDFB_NO_COL_MAX][CLDFB_NO_CHANNELS_MAX]; @@ -475,7 +475,6 @@ static void ivas_dirac_param_est_ana_fx( Word16 q_factor_intensity, q_factor_intensity_old = 0; Word16 q_factor_energy = 0, q_factor_energy_old = 0; Word16 exp = 0, exp_div = 0; - // Word16 exp2; num_freq_bands = hDirAC->nbands; /* l_ts = input_frame / CLDFB_NO_COL_MAX; */ l_ts = shr( input_frame, 4 ); @@ -554,7 +553,7 @@ static void ivas_dirac_param_est_ana_fx( /* Power estimation for diffuseness */ computeReferencePower_ana_fx( hDirAC->band_grouping, Foa_RealBuffer_fx, Foa_ImagBuffer_fx, reference_power_fx[ts], num_freq_bands ); //( 2 * ( scale_fact - Q1 ) - 31 - 1 ); // computeReferencePower_ana( hDirAC->band_grouping, Foa_RealBuffer, Foa_ImagBuffer, reference_power[ts], num_freq_bands ); - // exp2 = sub( shl( scale_fact, 1 ), 31 ); + /* Fill buffers of length "averaging_length" time slots for intensity and energy */ hDirAC->index_buffer_intensity = add( ( hDirAC->index_buffer_intensity % DIRAC_NO_COL_AVG_DIFF ), 1 ); /* averaging_length = 32 */ move16(); @@ -893,7 +892,7 @@ static void ivas_dirac_param_est_ana( #ifdef IVAS_FLOAT_FIXED /* Compute downmix */ static void ivas_dirac_dmx_fx( - Word32 data_in_fx[][L_FRAME48k], + Word32 data_in_fx[][L_FRAME48k], /* Qx (same as the input Q) */ const Word16 input_frame, const Word16 nchan_transport ) { diff --git a/lib_rend/ivas_output_init.c b/lib_rend/ivas_output_init.c index 32af0e0158ae66c938ecc2f1068c33a16ae9b0f1..ca2440753dc1c45ef06d7bbb09de4898c700e0fd 100644 --- a/lib_rend/ivas_output_init.c +++ b/lib_rend/ivas_output_init.c @@ -267,8 +267,8 @@ void ivas_output_init( case IVAS_AUDIO_CONFIG_STEREO: hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP2_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP2_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP2_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP2_fx; // Q22 BREAK; case IVAS_AUDIO_CONFIG_FOA: hOutSetup->ambisonics_order = SBA_FOA_ORDER; @@ -289,8 +289,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP6_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP6_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP6_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP6_fx; // Q22 hOutSetup->is_planar_setup = 1; move16(); BREAK; @@ -301,8 +301,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP12_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP12_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP12_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP12_fx; // Q22 hOutSetup->is_planar_setup = 1; move16(); BREAK; @@ -313,8 +313,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP14_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP14_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP14_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP14_fx; // Q22 hOutSetup->is_planar_setup = 0; move16(); BREAK; @@ -325,8 +325,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP16_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP16_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP16_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP16_fx; // Q22 hOutSetup->is_planar_setup = 0; move16(); BREAK; @@ -337,8 +337,8 @@ void ivas_output_init( move16(); hOutSetup->is_loudspeaker_setup = 1; move16(); - hOutSetup->ls_azimuth_fx = ls_azimuth_CICP19_fx; - hOutSetup->ls_elevation_fx = ls_elevation_CICP19_fx; + hOutSetup->ls_azimuth_fx = ls_azimuth_CICP19_fx; // Q22 + hOutSetup->ls_elevation_fx = ls_elevation_CICP19_fx; // Q22 hOutSetup->is_planar_setup = 0; move16(); BREAK; diff --git a/lib_rend/ivas_prot_rend.h b/lib_rend/ivas_prot_rend.h index 3d783bbaa73a8336ba0294a367bab092c34aad02..46aea4299273ece62b87b49432a66ee790060e65 100644 --- a/lib_rend/ivas_prot_rend.h +++ b/lib_rend/ivas_prot_rend.h @@ -320,8 +320,8 @@ ivas_error ivas_sba_get_hoa_dec_matrix( ); #else ivas_error ivas_sba_get_hoa_dec_matrix_fx( - const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ - Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix */ + const IVAS_OUTPUT_SETUP hOutSetup, /* i : target output setup */ + Word32 **hoa_dec_mtx, /* o : ALLRAD decoder matrix, Q29 */ const Word16 ambisonics_order /* i : Ambisonics order */ ); #endif @@ -2824,8 +2824,8 @@ ivas_error ivas_dirac_ana_open( #ifdef IVAS_FLOAT_FIXED void ivas_dirac_ana_fx( - DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ - Word32 data_in_f[][L_FRAME48k], /* i/o: Input / transport audio signals */ + DIRAC_ANA_HANDLE hDirAC, /* i/o: DIRAC analysis handle */ + Word32 data_in_fx[][L_FRAME48k], /* i/o: Input / transport audio signals, Q7 */ const Word16 input_frame, /* i : Input frame size */ const Word16 nchan_transport /* i : Number of transport channels */ ); diff --git a/lib_rend/ivas_stat_rend.h b/lib_rend/ivas_stat_rend.h index d5d23e49c19a93e00a16a96ae7f6f431d7b9cd2b..c5661dc39403e8646439091c1704ffe9c6ea82e5 100644 --- a/lib_rend/ivas_stat_rend.h +++ b/lib_rend/ivas_stat_rend.h @@ -58,8 +58,8 @@ typedef struct ivas_output_setup_structure Word16 num_lfe; Word16 index_lfe[1]; - const Word32 *ls_azimuth_fx; - const Word32 *ls_elevation_fx; + const Word32 *ls_azimuth_fx; // Q22 + const Word32 *ls_elevation_fx; // Q22 UWord8 separateChannelEnabled; Word16 separateChannelIndex;